Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Comminos <andrewcomminos@gmail.com>2013-08-08 11:43:31 +0400
committerAndrew Comminos <andrewcomminos@gmail.com>2013-08-08 11:43:31 +0400
commitf76b49c3e8072795e13f6bd4fb1634ab38514e10 (patch)
tree96165966b06ca387fc1f978ba92c4067ddea6d26 /src/main/java
parent9808e0611e413985e1ee7afeb0e0b51b371224c3 (diff)
Added initial Tor support, as well as various user and channel tweaks.
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/morlunk/jumble/JumbleService.java7
-rw-r--r--src/main/java/com/morlunk/jumble/model/Channel.java18
-rw-r--r--src/main/java/com/morlunk/jumble/net/ChannelHandler.java40
-rw-r--r--src/main/java/com/morlunk/jumble/net/JumbleConnection.java38
-rw-r--r--src/main/java/com/morlunk/jumble/net/JumbleObserver.java2
-rw-r--r--src/main/java/com/morlunk/jumble/net/JumbleSSLSocketFactory.java3
-rw-r--r--src/main/java/com/morlunk/jumble/net/UserHandler.java28
7 files changed, 101 insertions, 35 deletions
diff --git a/src/main/java/com/morlunk/jumble/JumbleService.java b/src/main/java/com/morlunk/jumble/JumbleService.java
index f4c6d17..e458fd5 100644
--- a/src/main/java/com/morlunk/jumble/JumbleService.java
+++ b/src/main/java/com/morlunk/jumble/JumbleService.java
@@ -57,6 +57,7 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
public static final String EXTRAS_TRANSMIT_MODE = "transmit_mode";
public static final String EXTRAS_USE_OPUS = "use_opus";
public static final String EXTRAS_FORCE_TCP = "force_tcp";
+ public static final String EXTRAS_USE_TOR = "use_tor";
public static final String EXTRAS_CLIENT_NAME = "client_name";
public static final String ACTION_DISCONNECT = "com.morlunk.jumble.DISCONNECT";
@@ -71,6 +72,7 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
public int mTransmitMode;
public boolean mUseOpus;
public boolean mForceTcp;
+ public boolean mUseTor;
public String mClientName;
private JumbleConnection mConnection;
@@ -274,7 +276,8 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
mDetectionThreshold = extras.getInt(EXTRAS_DETECTION_THRESHOLD, 1400);
mTransmitMode = extras.getInt(EXTRAS_TRANSMIT_MODE, Constants.TRANSMIT_VOICE_ACTIVITY);
mUseOpus = extras.getBoolean(EXTRAS_USE_OPUS, true);
- mForceTcp = extras.getBoolean(EXTRAS_FORCE_TCP, false);
+ mUseTor = extras.getBoolean(EXTRAS_USE_TOR, false);
+ mForceTcp = extras.getBoolean(EXTRAS_FORCE_TCP, false) || mUseTor; // Tor requires TCP connections to work- if it's on, force TCP.
mClientName = extras.containsKey(EXTRAS_CLIENT_NAME) ? extras.getString(EXTRAS_CLIENT_NAME) : "Jumble";
connect();
}
@@ -299,7 +302,7 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
public void connect() {
try {
- mConnection = new JumbleConnection(this, this, mServer, mClientName, mCertificate, mCertificatePassword, mForceTcp, mUseOpus);
+ mConnection = new JumbleConnection(this, this, mServer, mClientName, mCertificate, mCertificatePassword, mForceTcp, mUseOpus, mUseTor);
} catch (final JumbleConnectionException e) {
e.printStackTrace();
diff --git a/src/main/java/com/morlunk/jumble/model/Channel.java b/src/main/java/com/morlunk/jumble/model/Channel.java
index 76c93c3..300e28e 100644
--- a/src/main/java/com/morlunk/jumble/model/Channel.java
+++ b/src/main/java/com/morlunk/jumble/model/Channel.java
@@ -20,11 +20,13 @@ import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public final class Channel implements Parcelable {
private int mId;
private int mPosition;
+ private int mLevel;
private boolean mTemporary;
private int mParent = -1;
private String mName;
@@ -63,6 +65,7 @@ public final class Channel implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mId);
out.writeInt(mPosition);
+ out.writeInt(mLevel);
out.writeValue(mTemporary);
out.writeInt(mParent);
out.writeString(mName);
@@ -77,6 +80,7 @@ public final class Channel implements Parcelable {
public void readFromParcel(Parcel in) {
mId = in.readInt();
mPosition = in.readInt();
+ mLevel = in.readInt();
mTemporary = (Boolean)in.readValue(null);
mParent = in.readInt();
mName = in.readString();
@@ -94,7 +98,7 @@ public final class Channel implements Parcelable {
}
public void addUser(int userId) {
- mUsers.add(userId); // TODO sorting
+ mUsers.add(userId);
}
public void removeUser(int userId) {
@@ -161,6 +165,18 @@ public final class Channel implements Parcelable {
this.mDescriptionHash = mDescriptionHash;
}
+ public List<Integer> getSubchannels() {
+ return mSubchannels;
+ }
+
+ public void addSubchannel(int channelId) {
+ mSubchannels.add(channelId);
+ }
+
+ public void removeSubchannel(int channelId) {
+ mSubchannels.remove((Object)channelId);
+ }
+
public List<Integer> getLinks() {
return mLinks;
}
diff --git a/src/main/java/com/morlunk/jumble/net/ChannelHandler.java b/src/main/java/com/morlunk/jumble/net/ChannelHandler.java
index ed281a5..2457311 100644
--- a/src/main/java/com/morlunk/jumble/net/ChannelHandler.java
+++ b/src/main/java/com/morlunk/jumble/net/ChannelHandler.java
@@ -24,32 +24,32 @@ import com.morlunk.jumble.model.Channel;
import com.morlunk.jumble.protobuf.Mumble;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
/**
* Created by andrew on 18/07/13.
*/
public class ChannelHandler extends JumbleMessageHandler.Stub {
- /**
- * Channel comparator that first sorts by position, then alphabetical order.
- */
- class ChannelSortComparator implements Comparator<Integer> {
-
+ private Comparator<Integer> mChannelComparator = new Comparator<Integer>() {
@Override
public int compare(Integer lhs, Integer rhs) {
- Channel clhs = mChannels.get(lhs);
- Channel crhs = mChannels.get(rhs);
- if(clhs.getPosition() > clhs.getPosition()) return 1;
- else if(clhs.getPosition() < clhs.getPosition()) return -1;
+ Channel clhs = getChannel(lhs);
+ Channel crhs = getChannel(rhs);
+ if(clhs.getPosition() != crhs.getPosition())
+ return ((Integer)clhs.getPosition()).compareTo(crhs.getPosition());
return clhs.getName().compareTo(crhs.getName());
}
- }
+ };
private JumbleService mService;
- private HashMap<Integer, Channel> mChannels = new HashMap<Integer, Channel>();
+ private Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>();
public ChannelHandler(JumbleService service) {
mService = service;
@@ -78,21 +78,27 @@ public class ChannelHandler extends JumbleMessageHandler.Stub {
mChannels.put(msg.getChannelId(), channel);
}
- if(msg.hasParent())
- channel.setParent(parent.getId());
-
if(msg.hasName())
channel.setName(msg.getName());
+ if(msg.hasPosition())
+ channel.setPosition(msg.getPosition());
+
+ if(msg.hasParent()) {
+ Channel oldParent = mChannels.get(channel.getParent());
+ channel.setParent(parent.getId());
+ parent.addSubchannel(channel.getId());
+ Collections.sort(parent.getSubchannels(), mChannelComparator); // Re-sort after subchannel addition
+ if(oldParent != null)
+ oldParent.removeSubchannel(channel.getId());
+ }
+
if(msg.hasDescriptionHash())
channel.setDescriptionHash(msg.getDescriptionHash().toByteArray());
if(msg.hasDescription())
channel.setDescription(msg.getDescription());
- if(msg.hasPosition())
- channel.setPosition(msg.getPosition());
-
if(msg.getLinksCount() > 0) {
channel.clearLinks();
for(int link : msg.getLinksList())
diff --git a/src/main/java/com/morlunk/jumble/net/JumbleConnection.java b/src/main/java/com/morlunk/jumble/net/JumbleConnection.java
index d3a055b..fc9400c 100644
--- a/src/main/java/com/morlunk/jumble/net/JumbleConnection.java
+++ b/src/main/java/com/morlunk/jumble/net/JumbleConnection.java
@@ -28,6 +28,7 @@ import com.google.protobuf.Message;
import com.morlunk.jumble.Constants;
import com.morlunk.jumble.model.Server;
import com.morlunk.jumble.protobuf.Mumble;
+
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
@@ -43,6 +44,9 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import socks.Socks5Proxy;
+import socks.SocksSocket;
+
public class JumbleConnection {
public interface JumbleConnectionListener {
public void onConnectionEstablished();
@@ -51,6 +55,10 @@ public class JumbleConnection {
public void onConnectionWarning(String warning);
}
+ // Tor connection details
+ public static final String TOR_HOST = "localhost";
+ public static final int TOR_PORT = 9050;
+
private Context mContext;
private JumbleConnectionListener mListener;
private String mClientName;
@@ -69,8 +77,9 @@ public class JumbleConnection {
private InetAddress mHost;
private JumbleTCP mTCP;
private JumbleUDP mUDP;
- private boolean mForceTCP = false;
+ private boolean mForceTCP;
private boolean mUseOpus = true;
+ private boolean mUseTor;
private boolean mUsingUDP = true;
private boolean mConnected;
private CryptState mCryptState = new CryptState();
@@ -261,7 +270,8 @@ public class JumbleConnection {
byte[] certificate,
String certificatePassword,
boolean forceTcp,
- boolean useOpus) throws JumbleConnectionException {
+ boolean useOpus,
+ boolean useTor) throws JumbleConnectionException {
mContext = context;
mListener = listener;
@@ -269,6 +279,7 @@ public class JumbleConnection {
mClientName = clientName;
mForceTCP = forceTcp;
mUseOpus = useOpus;
+ mUseTor = useTor;
mMainHandler = new Handler(context.getMainLooper());
mHandlers.add(mConnectionMessageHandler);
setupSocketFactory(certificate, certificatePassword);
@@ -371,6 +382,7 @@ public class JumbleConnection {
* @param e The exception that caused termination.
*/
private void handleFatalException(final JumbleConnectionException e) {
+ e.printStackTrace();
if(mListener != null) {
mMainHandler.post(new Runnable() {
@Override
@@ -396,6 +408,7 @@ public class JumbleConnection {
ByteArrayInputStream inputStream = new ByteArrayInputStream(certificate);
keyStore.load(inputStream, certificatePassword != null ? certificatePassword.toCharArray() : new char[0]);
}
+
mSocketFactory = new JumbleSSLSocketFactory(keyStore, certificatePassword);
} catch (KeyManagementException e) {
throw new JumbleConnectionException("Could not recover keys from certificate", e, false);
@@ -407,14 +420,14 @@ public class JumbleConnection {
throw new JumbleConnectionException("Could not read certificate file", e, false);
} catch (CertificateException e) {
e.printStackTrace();
- }catch (NoSuchProviderException e) {
+ } catch (NoSuchAlgorithmException e) {
/*
* This will actually NEVER occur.
* We use Spongy Castle to provide the algorithm and provider implementations.
* There's no platform dependency.
*/
throw new RuntimeException("We use Spongy Castle- what? ", e);
- } catch (NoSuchAlgorithmException e) {
+ } catch (NoSuchProviderException e) {
/*
* This will actually NEVER occur.
* We use Spongy Castle to provide the algorithm and provider implementations.
@@ -481,7 +494,8 @@ public class JumbleConnection {
* @param data Raw protobuf TCP data.
* @param messageType Type of the message.
* @return The parsed protobuf message.
- * @throws InvalidProtocolBufferException Called if the messageType does not match the data.
+ * @throws InvalidProtocolBufferException Called if the messageType doe
+ }s not match the data.
*/
public static final Message getProtobufMessage(byte[] data, JumbleTCPMessageType messageType) throws InvalidProtocolBufferException {
switch (messageType) {
@@ -680,13 +694,15 @@ public class JumbleConnection {
handleFatalException(new JumbleConnectionException("Could not resolve host", e, true));
}
- mTCPSocket = (SSLSocket)mSocketFactory.createSocket();
- mTCPSocket.setKeepAlive(true);
- mTCPSocket.setEnabledProtocols(new String[] {"TLSv1"});
- mTCPSocket.setUseClientMode(true);
-
HttpParams httpParams = new BasicHttpParams();
- mSocketFactory.connectSocket(mTCPSocket, mServer.getHost(), mServer.getPort(), null, 0, httpParams);
+
+ if(mUseTor) {
+ Socks5Proxy proxy = new Socks5Proxy(TOR_HOST, TOR_PORT);
+ proxy.resolveAddrLocally(false); // Tor requirement for SOCKS5 is to let it resolve the host.
+ SocksSocket proxySocket = new SocksSocket(proxy, mServer.getHost(), mServer.getPort());
+ mTCPSocket = (SSLSocket) mSocketFactory.connectSocket(proxySocket, mServer.getHost(), mServer.getPort(), null, 0, httpParams);
+ } else
+ mTCPSocket = (SSLSocket) mSocketFactory.connectSocket(null, mServer.getHost(), mServer.getPort(), null, 0, httpParams);
mTCPSocket.startHandshake();
diff --git a/src/main/java/com/morlunk/jumble/net/JumbleObserver.java b/src/main/java/com/morlunk/jumble/net/JumbleObserver.java
index e2c1bae..b95ec11 100644
--- a/src/main/java/com/morlunk/jumble/net/JumbleObserver.java
+++ b/src/main/java/com/morlunk/jumble/net/JumbleObserver.java
@@ -78,7 +78,7 @@ public class JumbleObserver extends IJumbleObserver.Stub {
}
@Override
- public void onUserRemoved(User user) throws RemoteException {
+ public void onUserRemoved(User user, String reason) throws RemoteException {
}
diff --git a/src/main/java/com/morlunk/jumble/net/JumbleSSLSocketFactory.java b/src/main/java/com/morlunk/jumble/net/JumbleSSLSocketFactory.java
index c506146..55697a5 100644
--- a/src/main/java/com/morlunk/jumble/net/JumbleSSLSocketFactory.java
+++ b/src/main/java/com/morlunk/jumble/net/JumbleSSLSocketFactory.java
@@ -17,7 +17,9 @@
package com.morlunk.jumble.net;
import java.io.IOException;
+import java.net.Proxy;
import java.net.Socket;
+import java.net.SocketAddress;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
@@ -87,5 +89,4 @@ public class JumbleSSLSocketFactory extends SSLSocketFactory {
public Socket createSocket() throws IOException {
return mSslContext.getSocketFactory().createSocket();
}
-
} \ No newline at end of file
diff --git a/src/main/java/com/morlunk/jumble/net/UserHandler.java b/src/main/java/com/morlunk/jumble/net/UserHandler.java
index fe557ca..e004a97 100644
--- a/src/main/java/com/morlunk/jumble/net/UserHandler.java
+++ b/src/main/java/com/morlunk/jumble/net/UserHandler.java
@@ -28,6 +28,8 @@ import com.morlunk.jumble.model.User;
import com.morlunk.jumble.protobuf.Mumble;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@@ -36,6 +38,18 @@ import java.util.List;
*/
public class UserHandler extends JumbleMessageHandler.Stub {
+ /**
+ * Comparator to sort users alphabetically.
+ */
+ private Comparator<Integer> mUserComparator = new Comparator<Integer>() {
+ @Override
+ public int compare(Integer lhs, Integer rhs) {
+ User ulhs = mUsers.get(lhs);
+ User urhs = mUsers.get(rhs);
+ return ulhs.getName().compareTo(urhs.getName());
+ }
+ };
+
private JumbleService mService;
private HashMap<Integer, User> mUsers = new HashMap<Integer, User>();
@@ -55,6 +69,14 @@ public class UserHandler extends JumbleMessageHandler.Stub {
mUsers.clear();
}
+ /**
+ * Sorts the users in the provided channel alphabetically.
+ * @param channel The channel containing the users to sort.
+ */
+ private void sortUsers(Channel channel) {
+ Collections.sort(channel.getUsers(), mUserComparator);
+ }
+
@Override
public void messageUserState(Mumble.UserState msg) {
User user = mUsers.get(msg.getSession());
@@ -69,6 +91,7 @@ public class UserHandler extends JumbleMessageHandler.Stub {
// Assume in root channel. TODO FIX ME PLEASE OH GOD WHY DOES THIS WORK
Channel root = mService.getChannelHandler().getChannel(0);
root.addUser(user.getSession());
+ sortUsers(root);
newUser = true;
}
else
@@ -158,6 +181,7 @@ public class UserHandler extends JumbleMessageHandler.Stub {
old.removeUser(user.getSession());
channel.addUser(user.getSession());
+ sortUsers(channel);
if(!newUser) {
mService.notifyObservers(new JumbleService.ObserverRunnable() {
@Override
@@ -200,7 +224,7 @@ public class UserHandler extends JumbleMessageHandler.Stub {
@Override
public void messageUserRemove(Mumble.UserRemove msg) {
- String reason = msg.getReason();
+ final String reason = msg.getReason();
/*
* TODO: logging
@@ -215,7 +239,7 @@ public class UserHandler extends JumbleMessageHandler.Stub {
mService.notifyObservers(new JumbleService.ObserverRunnable() {
@Override
public void run(IJumbleObserver observer) throws RemoteException {
- observer.onUserRemoved(user);
+ observer.onUserRemoved(user, reason);
}
});
}