Show list of running tunnels

This commit is contained in:
str4d
2014-01-27 06:02:12 +00:00
parent 2d8529e691
commit 124b1499b4
5 changed files with 173 additions and 14 deletions

2
TODO
View File

@ -1,7 +1,5 @@
# Required for release # Required for release
- Main status
- Show tunnel list with status
- NetDB tablet view fixes - NetDB tablet view fixes
- Refresh detail fragment when changing tab - Refresh detail fragment when changing tab
- Move list to correct item when changing tab - Move list to correct item when changing tab

View File

@ -37,7 +37,6 @@
android:scrollbarStyle="outsideInset" > android:scrollbarStyle="outsideInset" >
<LinearLayout <LinearLayout
android:id="@+id/main_status"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" > android:orientation="vertical" >
@ -45,13 +44,31 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/label_status" android:text="@string/label_tunnels"
android:textAppearance="?android:attr/textAppearanceLarge" /> android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView <TableLayout
android:id="@+id/main_status_text" android:id="@+id/main_tunnels"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/main_status"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_status"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/main_status_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>

View File

@ -28,7 +28,6 @@
android:scrollbarStyle="outsideInset" > android:scrollbarStyle="outsideInset" >
<LinearLayout <LinearLayout
android:id="@+id/main_status"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" > android:orientation="vertical" >
@ -36,13 +35,31 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/label_status" android:text="@string/label_tunnels"
android:textAppearance="?android:attr/textAppearanceLarge" /> android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView <TableLayout
android:id="@+id/main_status_text" android:id="@+id/main_tunnels"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/main_status"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_status"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/main_status_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>

View File

@ -7,6 +7,7 @@
<string name="welcome_new_version">New version installed. Please read the release notes. Version:</string> <string name="welcome_new_version">New version installed. Please read the release notes. Version:</string>
<string name="label_home">Controls and Status</string> <string name="label_home">Controls and Status</string>
<string name="label_tunnels">Tunnels</string>
<string name="label_status">Status</string> <string name="label_status">Status</string>
<string name="label_addressbook">Addressbook</string> <string name="label_addressbook">Addressbook</string>
<string name="label_i2ptunnel">I2PTunnel</string> <string name="label_i2ptunnel">I2PTunnel</string>

View File

@ -7,17 +7,31 @@ import android.preference.PreferenceManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.ToggleButton; import android.widget.ToggleButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import java.text.Collator;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import net.i2p.android.router.R; import net.i2p.android.router.R;
import net.i2p.android.router.util.Util; import net.i2p.android.router.util.Util;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.LeaseSet;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.router.TunnelPoolSettings;
import net.i2p.util.Translate;
public class MainFragment extends I2PFragmentBase { public class MainFragment extends I2PFragmentBase {
@ -242,17 +256,22 @@ public class MainFragment extends I2PFragmentBase {
RouterContext ctx = getRouterContext(); RouterContext ctx = getRouterContext();
ScrollView sv = (ScrollView) getActivity().findViewById(R.id.main_scrollview); ScrollView sv = (ScrollView) getActivity().findViewById(R.id.main_scrollview);
LinearLayout vStatus = (LinearLayout) getActivity().findViewById(R.id.main_status); LinearLayout vStatus = (LinearLayout) getActivity().findViewById(R.id.main_status);
TextView tv = (TextView) getActivity().findViewById(R.id.main_status_text); TextView vStatusText = (TextView) getActivity().findViewById(R.id.main_status_text);
if(!Util.isConnected(getActivity())) { if(!Util.isConnected(getActivity())) {
// Manually set state, RouterService won't be running // Manually set state, RouterService won't be running
updateState("WAITING"); updateState("WAITING");
tv.setText("No Internet connection is available"); vStatusText.setText("No Internet connection is available");
vStatus.setVisibility(View.VISIBLE);
sv.setVisibility(View.VISIBLE); sv.setVisibility(View.VISIBLE);
} else if(ctx != null) { } else if(ctx != null) {
if(_startPressed) { if(_startPressed) {
_startPressed = false; _startPressed = false;
} }
// Load running tunnels
loadDestinations(ctx);
if (PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean(PREF_SHOW_STATS, false)) { if (PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean(PREF_SHOW_STATS, false)) {
short reach = ctx.commSystem().getReachabilityStatus(); short reach = ctx.commSystem().getReachabilityStatus();
int active = ctx.commSystem().countActivePeers(); int active = ctx.commSystem().countActivePeers();
@ -330,14 +349,14 @@ public class MainFragment extends I2PFragmentBase {
+ "\nUptime: " + uptime; + "\nUptime: " + uptime;
_savedStatus = status + participate + details; _savedStatus = status + participate + details;
tv.setText(_savedStatus); vStatusText.setText(_savedStatus);
vStatus.setVisibility(View.VISIBLE); vStatus.setVisibility(View.VISIBLE);
} else } else
vStatus.setVisibility(View.INVISIBLE); vStatus.setVisibility(View.INVISIBLE);
sv.setVisibility(View.VISIBLE); sv.setVisibility(View.VISIBLE);
} else { } else {
// network but no router context // network but no router context
tv.setText("Not running"); vStatusText.setText("Not running");
sv.setVisibility(View.INVISIBLE); sv.setVisibility(View.INVISIBLE);
/** /**
* ** * **
@ -357,6 +376,113 @@ public class MainFragment extends I2PFragmentBase {
} }
} }
/**
* Based on net.i2p.router.web.SummaryHelper.getDestinations()
* @param ctx The RouterContext
*/
private void loadDestinations(RouterContext ctx) {
TableLayout dests = (TableLayout) getView().findViewById(R.id.main_tunnels);
dests.removeAllViews();
List<Destination> clients = new ArrayList<Destination>(ctx.clientManager().listClients());
if (!clients.isEmpty()) {
Collections.sort(clients, new AlphaComparator(ctx));
for (Destination client : clients) {
String name = getName(ctx, client);
Hash h = client.calculateHash();
TableRow dest = new TableRow(getActivity());
//dest.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
// Client or server
ImageView type = new ImageView(getActivity());
if (ctx.clientManager().shouldPublishLeaseSet(h))
type.setImageDrawable(getActivity().getResources()
.getDrawable(R.drawable.server));
else
type.setImageDrawable(getActivity().getResources()
.getDrawable(R.drawable.client));
dest.addView(type);
// Name
TextView destName = new TextView(getActivity());
destName.setText(name);
//destName.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
dest.addView(destName);
// Status
ImageView status = new ImageView(getActivity());
LeaseSet ls = ctx.netDb().lookupLeaseSetLocally(h);
if (ls != null && ctx.tunnelManager().getOutboundClientTunnelCount(h) > 0) {
long timeToExpire = ls.getEarliestLeaseDate() - ctx.clock().now();
if (timeToExpire < 0) {
// red or yellow light
status.setImageDrawable(getActivity().getResources()
.getDrawable(R.drawable.local_inprogress));
} else {
// green light
status.setImageDrawable(getActivity().getResources()
.getDrawable(R.drawable.local_up));
}
} else {
// yellow light
status.setImageDrawable(getActivity().getResources()
.getDrawable(R.drawable.local_inprogress));
}
dest.addView(status);
dests.addView(dest);
}
} else {
TableRow empty = new TableRow(getActivity());
TextView emptyText = new TextView(getActivity());
emptyText.setText("No client tunnels are running yet.");
empty.addView(emptyText);
dests.addView(empty);
}
}
/** compare translated nicknames - put "shared clients" first in the sort */
private class AlphaComparator implements Comparator<Destination> {
private String xsc;
private RouterContext _ctx;
public AlphaComparator(RouterContext ctx) {
_ctx = ctx;
xsc = _(ctx, "shared clients");
}
public int compare(Destination lhs, Destination rhs) {
String lname = getName(_ctx, lhs);
String rname = getName(_ctx, rhs);
if (lname.equals(xsc))
return -1;
if (rname.equals(xsc))
return 1;
return Collator.getInstance().compare(lname, rname);
}
}
/** translate here so collation works above */
private String getName(RouterContext ctx, Destination d) {
TunnelPoolSettings in = ctx.tunnelManager().getInboundSettings(d.calculateHash());
String name = (in != null ? in.getDestinationNickname() : null);
if (name == null) {
TunnelPoolSettings out = ctx.tunnelManager().getOutboundSettings(d.calculateHash());
name = (out != null ? out.getDestinationNickname() : null);
if (name == null)
name = d.calculateHash().toBase64().substring(0,6);
else
name = _(ctx, name);
} else {
name = _(ctx, name);
}
return name;
}
private String _(RouterContext ctx, String s) {
return Translate.getString(s, ctx, "net.i2p.router.web.messages");
}
private void checkDialog() { private void checkDialog() {
VersionDialog dialog = new VersionDialog(); VersionDialog dialog = new VersionDialog();
String oldVersion = ((I2PActivityBase) getActivity()).getPref(PREF_INSTALLED_VERSION, "??"); String oldVersion = ((I2PActivityBase) getActivity()).getPref(PREF_INSTALLED_VERSION, "??");