diff options
author | Andrew Comminos <andrewcomminos@gmail.com> | 2014-01-22 06:59:46 +0400 |
---|---|---|
committer | Andrew Comminos <andrewcomminos@gmail.com> | 2014-01-22 07:01:09 +0400 |
commit | ef7a1c576080b02a5a5460558646eea0ebb3a9da (patch) | |
tree | 85714c962f35a55739f3a13cfbb8241f457f90f8 | |
parent | 8f1bb059a1e93583aa19f85b04d492c626128942 (diff) |
A few optimizations.
-rw-r--r-- | src/main/java/com/morlunk/jumble/JumbleService.java | 3 | ||||
-rw-r--r-- | src/main/java/com/morlunk/jumble/audio/AudioOutput.java | 9 | ||||
-rw-r--r-- | src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java | 5 | ||||
-rw-r--r-- | src/main/java/com/morlunk/jumble/net/CryptState.java | 22 | ||||
-rw-r--r-- | src/main/java/com/morlunk/jumble/net/JumbleConnection.java | 50 | ||||
-rw-r--r-- | src/main/java/com/morlunk/jumble/protocol/JumbleTCPMessageListener.java (renamed from src/main/java/com/morlunk/jumble/protocol/JumbleMessageListener.java) | 9 | ||||
-rw-r--r-- | src/main/java/com/morlunk/jumble/protocol/JumbleUDPMessageListener.java | 35 | ||||
-rw-r--r-- | src/main/java/com/morlunk/jumble/protocol/ProtocolHandler.java | 2 |
8 files changed, 92 insertions, 43 deletions
diff --git a/src/main/java/com/morlunk/jumble/JumbleService.java b/src/main/java/com/morlunk/jumble/JumbleService.java index b88831c..10ed653 100644 --- a/src/main/java/com/morlunk/jumble/JumbleService.java +++ b/src/main/java/com/morlunk/jumble/JumbleService.java @@ -595,7 +595,8 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon mTextMessageHandler = new TextMessageHandler(this); mAudioOutput = new AudioOutput(this); mAudioInput = new AudioInput(this, JumbleUDPMessageType.UDPVoiceOpus, mInputQuality, mTransmitMode, mDetectionThreshold, mAudioInputListener); - mConnection.addMessageHandlers(mChannelHandler, mUserHandler, mTextMessageHandler, mAudioOutput, mAudioInput); + mConnection.addTCPMessageHandlers(mChannelHandler, mUserHandler, mTextMessageHandler, mAudioOutput, mAudioInput); + mConnection.addUDPMessageHandlers(mAudioOutput); mConnection.connect(); } diff --git a/src/main/java/com/morlunk/jumble/audio/AudioOutput.java b/src/main/java/com/morlunk/jumble/audio/AudioOutput.java index 0bfde1b..7855cdc 100644 --- a/src/main/java/com/morlunk/jumble/audio/AudioOutput.java +++ b/src/main/java/com/morlunk/jumble/audio/AudioOutput.java @@ -31,6 +31,8 @@ import com.morlunk.jumble.JumbleService; import com.morlunk.jumble.model.User; import com.morlunk.jumble.net.JumbleUDPMessageType; import com.morlunk.jumble.net.PacketDataStream; +import com.morlunk.jumble.protocol.JumbleTCPMessageListener; +import com.morlunk.jumble.protocol.JumbleUDPMessageListener; import com.morlunk.jumble.protocol.ProtocolHandler; import java.nio.ByteBuffer; @@ -42,7 +44,7 @@ import java.util.concurrent.ConcurrentHashMap; /** * Created by andrew on 16/07/13. */ -public class AudioOutput extends ProtocolHandler implements Runnable, AudioOutputSpeech.TalkStateListener { +public class AudioOutput extends ProtocolHandler implements Runnable, AudioOutputSpeech.TalkStateListener, JumbleUDPMessageListener { /** Number of nanoseconds until sleeping audio output thread. */ private static final long SLEEP_THRESHOLD = 3000000000L; @@ -207,6 +209,11 @@ public class AudioOutput extends ProtocolHandler implements Runnable, AudioOutpu } @Override + public void messageUDPPing(byte[] data) { + // nothing + } + + @Override public void onTalkStateUpdated(int session, User.TalkState state) { final User user = getService().getUserHandler().getUser(session); if(user != null && user.getTalkState() != state) { diff --git a/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java b/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java index 7ca7f46..0f2cd13 100644 --- a/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java +++ b/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java @@ -63,6 +63,7 @@ public class AudioOutputSpeech { private boolean mLastAlive = true; private int mBufferFilled, mLastConsume = 0; private int ucFlags; + private IntPointer avail = new IntPointer(1); private TalkStateListener mTalkStateListener; @@ -164,7 +165,6 @@ public class AudioOutputSpeech { if(!mLastAlive) Arrays.fill(mOut, 0); else { - IntPointer avail = new IntPointer(1); avail.put(0); int ts; @@ -189,11 +189,10 @@ public class AudioOutputSpeech { if(mFrames.isEmpty()) { Speex.JitterBufferPacket jbp = new Speex.JitterBufferPacket(null, 4096, 0, 0, 0); - IntPointer startofs = new IntPointer(1); int result; synchronized (mJitterBuffer) { - result = mJitterBuffer.get(jbp, startofs); + result = mJitterBuffer.get(jbp, null); } if(result == Speex.JitterBuffer.JITTER_BUFFER_OK) { diff --git a/src/main/java/com/morlunk/jumble/net/CryptState.java b/src/main/java/com/morlunk/jumble/net/CryptState.java index cffc527..949b3c8 100644 --- a/src/main/java/com/morlunk/jumble/net/CryptState.java +++ b/src/main/java/com/morlunk/jumble/net/CryptState.java @@ -111,13 +111,16 @@ public class CryptState { mInit = true; } - public byte[] decrypt(final byte[] source, final int length) { - if (length < 4) { - return null; - } + /** + * Decrypts data using the OCB-AES128 standard. + * @param source The encoded audio data. + * @param length The length of the source array. + * @param dst A destination array of size length - 4. + */ + public void decrypt(final byte[] source, final byte[] dst, final int length) { + if (length < 4) return; final int plainLength = length - 4; - final byte[] dst = new byte[plainLength]; final byte[] saveiv = new byte[AES_BLOCK_SIZE]; final short ivbyte = (short) (source[0] & 0xFF); @@ -141,7 +144,7 @@ public class CryptState { } } } else { - return null; + return; } } else { // This is either out of order or a repeat. @@ -184,12 +187,12 @@ public class CryptState { } } } else { - return null; + return; } if (mDecryptHistory[mDecryptIV[0] & 0xFF] == mEncryptIV[0]) { System.arraycopy(saveiv, 0, mDecryptIV, 0, AES_BLOCK_SIZE); - return null; + return; } } @@ -209,7 +212,7 @@ public class CryptState { if (tag[0] != source[1] || tag[1] != source[2] || tag[2] != source[3]) { System.arraycopy(saveiv, 0, mDecryptIV, 0, AES_BLOCK_SIZE); - return null; + return; } mDecryptHistory[mDecryptIV[0] & 0xff] = mDecryptIV[1]; @@ -221,7 +224,6 @@ public class CryptState { mUiLost += lost; mLastGoodStart = System.nanoTime(); - return dst; } public void ocbDecrypt(byte[] encrypted, byte[] plain, byte[] nonce, byte[] tag) throws BadPaddingException, IllegalBlockSizeException, ShortBufferException { diff --git a/src/main/java/com/morlunk/jumble/net/JumbleConnection.java b/src/main/java/com/morlunk/jumble/net/JumbleConnection.java index 01caf99..1bfe735 100644 --- a/src/main/java/com/morlunk/jumble/net/JumbleConnection.java +++ b/src/main/java/com/morlunk/jumble/net/JumbleConnection.java @@ -28,7 +28,8 @@ import com.google.protobuf.Message; import com.morlunk.jumble.Constants; import com.morlunk.jumble.model.Server; import com.morlunk.jumble.protobuf.Mumble; -import com.morlunk.jumble.protocol.JumbleMessageListener; +import com.morlunk.jumble.protocol.JumbleTCPMessageListener; +import com.morlunk.jumble.protocol.JumbleUDPMessageListener; import java.io.ByteArrayInputStream; import java.io.DataInputStream; @@ -129,12 +130,13 @@ public class JumbleConnection { private int mSession; // Message handlers - private ConcurrentLinkedQueue<JumbleMessageListener> mHandlers = new ConcurrentLinkedQueue<JumbleMessageListener>(); + private ConcurrentLinkedQueue<JumbleTCPMessageListener> mTCPHandlers = new ConcurrentLinkedQueue<JumbleTCPMessageListener>(); + private ConcurrentLinkedQueue<JumbleUDPMessageListener> mUDPHandlers = new ConcurrentLinkedQueue<JumbleUDPMessageListener>(); /** * Handles packets received that are critical to the connection state. */ - private JumbleMessageListener mConnectionMessageHandler = new JumbleMessageListener.Stub() { + private JumbleTCPMessageListener mConnectionMessageHandler = new JumbleTCPMessageListener.Stub() { @Override public void messageServerSync(Mumble.ServerSync msg) { @@ -251,6 +253,9 @@ public class JumbleConnection { mListener.onConnectionWarning("UDP packets can be sent to and received from the server. Switching back to UDP mode."); } } + }; + + private JumbleUDPMessageListener mUDPPingListener = new JumbleUDPMessageListener.Stub() { @Override public void messageUDPPing(byte[] data) { @@ -319,7 +324,8 @@ public class JumbleConnection { mUseOpus = useOpus; mUseTor = useTor; mMainHandler = new Handler(context.getMainLooper()); - mHandlers.add(mConnectionMessageHandler); + mTCPHandlers.add(mConnectionMessageHandler); + mUDPHandlers.add(mUDPPingListener); setupSocketFactory(certificate, certificatePassword); } @@ -359,13 +365,21 @@ public class JumbleConnection { return (System.nanoTime()-mStartTimestamp)/1000; } - public void addMessageHandlers(JumbleMessageListener... handlers) { - for(JumbleMessageListener listener : handlers) - mHandlers.add(listener); + public void addTCPMessageHandlers(JumbleTCPMessageListener... handlers) { + for(JumbleTCPMessageListener listener : handlers) + mTCPHandlers.add(listener); + } + + public void removeTCPMessageHandler(JumbleTCPMessageListener handler) { + mTCPHandlers.remove(handler); + } + public void addUDPMessageHandlers(JumbleUDPMessageListener... handlers) { + for(JumbleUDPMessageListener listener : handlers) + mUDPHandlers.add(listener); } - public void removeMessageHandler(JumbleMessageListener handler) { - mHandlers.remove(handler); + public void removeUDPMessageHandler(JumbleUDPMessageListener handler) { + mUDPHandlers.remove(handler); } public int getServerVersion() { @@ -564,7 +578,7 @@ public class JumbleConnection { try { Message message = getProtobufMessage(data, messageType); - for(JumbleMessageListener handler : mHandlers) { + for(JumbleTCPMessageListener handler : mTCPHandlers) { broadcastTCPMessage(handler, message, messageType); } } catch (InvalidProtocolBufferException e) { @@ -574,7 +588,7 @@ public class JumbleConnection { private final void handleUDPMessage(byte[] data) { final JumbleUDPMessageType dataType = JumbleUDPMessageType.values()[data[0] >> 5 & 0x7]; - for(JumbleMessageListener handler : mHandlers) { + for(JumbleUDPMessageListener handler : mUDPHandlers) { broadcastUDPMessage(handler, data, dataType); } } @@ -651,7 +665,7 @@ public class JumbleConnection { * @param msg Protobuf message. * @param messageType The type of the message. */ - public final void broadcastTCPMessage(JumbleMessageListener handler, Message msg, JumbleTCPMessageType messageType) { + public final void broadcastTCPMessage(JumbleTCPMessageListener handler, Message msg, JumbleTCPMessageType messageType) { switch (messageType) { case Authenticate: handler.messageAuthenticate((Mumble.Authenticate) msg); @@ -744,7 +758,7 @@ public class JumbleConnection { * @param data Raw UDP data of the message. * @param messageType The type of the message. */ - public final void broadcastUDPMessage(JumbleMessageListener handler, byte[] data, JumbleUDPMessageType messageType) { + public final void broadcastUDPMessage(JumbleUDPMessageListener handler, byte[] data, JumbleUDPMessageType messageType) { switch (messageType) { case UDPPing: handler.messageUDPPing(data); @@ -900,6 +914,7 @@ public class JumbleConnection { private class JumbleUDP implements Runnable { private static final int BUFFER_SIZE = 2048; private DatagramSocket mUDPSocket; + private byte[] mDecryptedBuffer = new byte[BUFFER_SIZE]; public void disconnect() { mUDPSocket.disconnect(); @@ -935,14 +950,9 @@ public class JumbleConnection { // Decrypt UDP packet using OCB-AES128 final byte[] data = packet.getData(); final int length = packet.getLength(); - final byte[] decryptedData = mCryptState.decrypt(data, length); + mCryptState.decrypt(data, mDecryptedBuffer, length); - mMainHandler.post(new Runnable() { - @Override - public void run() { - if (decryptedData != null) handleUDPMessage(decryptedData); - } - }); + handleUDPMessage(mDecryptedBuffer); } catch (IOException e) { e.printStackTrace(); break; diff --git a/src/main/java/com/morlunk/jumble/protocol/JumbleMessageListener.java b/src/main/java/com/morlunk/jumble/protocol/JumbleTCPMessageListener.java index 3f39372..93ed471 100644 --- a/src/main/java/com/morlunk/jumble/protocol/JumbleMessageListener.java +++ b/src/main/java/com/morlunk/jumble/protocol/JumbleTCPMessageListener.java @@ -18,7 +18,7 @@ package com.morlunk.jumble.protocol; import com.morlunk.jumble.protobuf.Mumble; -public interface JumbleMessageListener { +public interface JumbleTCPMessageListener { public void messageAuthenticate(Mumble.Authenticate msg); public void messageBanList(Mumble.BanList msg); public void messageReject(Mumble.Reject msg); @@ -47,15 +47,12 @@ public interface JumbleMessageListener { public void messageSuggestConfig(Mumble.SuggestConfig msg); public void messageVoiceTarget(Mumble.VoiceTarget msg); - public void messageUDPPing(byte[] data); - public void messageVoiceData(byte[] data); - /** * Reads incoming protobuf TCP messages and performs the necessary action(s). * Designed to be subclassed at any level of the library, the default implementations do nothing. * Created by andrew on 24/06/13. */ - public static class Stub implements JumbleMessageListener { + public static class Stub implements JumbleTCPMessageListener { public void messageAuthenticate(Mumble.Authenticate msg) {} public void messageBanList(Mumble.BanList msg) {} @@ -84,7 +81,5 @@ public interface JumbleMessageListener { public void messageRequestBlob(Mumble.RequestBlob msg) {} public void messageSuggestConfig(Mumble.SuggestConfig msg) {} public void messageVoiceTarget(Mumble.VoiceTarget msg) {} - public void messageUDPPing(byte[] data) {} - public void messageVoiceData(byte[] data) {} } }
\ No newline at end of file diff --git a/src/main/java/com/morlunk/jumble/protocol/JumbleUDPMessageListener.java b/src/main/java/com/morlunk/jumble/protocol/JumbleUDPMessageListener.java new file mode 100644 index 0000000..bc1cc71 --- /dev/null +++ b/src/main/java/com/morlunk/jumble/protocol/JumbleUDPMessageListener.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2014 Andrew Comminos + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.morlunk.jumble.protocol; + +import com.morlunk.jumble.protobuf.Mumble; + +/** + * Created by andrew on 21/01/14. + */ + +public interface JumbleUDPMessageListener { + + public void messageUDPPing(byte[] data); + public void messageVoiceData(byte[] data); + + public static class Stub implements JumbleUDPMessageListener { + + public void messageUDPPing(byte[] data) {} + public void messageVoiceData(byte[] data) {} + } +}
\ No newline at end of file diff --git a/src/main/java/com/morlunk/jumble/protocol/ProtocolHandler.java b/src/main/java/com/morlunk/jumble/protocol/ProtocolHandler.java index f850321..6015e27 100644 --- a/src/main/java/com/morlunk/jumble/protocol/ProtocolHandler.java +++ b/src/main/java/com/morlunk/jumble/protocol/ProtocolHandler.java @@ -24,7 +24,7 @@ import com.morlunk.jumble.JumbleService; * server (i.e. audio, user state, channels) into their own classes. * Created by andrew on 21/11/13. */ -public class ProtocolHandler extends JumbleMessageListener.Stub { +public class ProtocolHandler extends JumbleTCPMessageListener.Stub { private JumbleService mService; |