I need to calculate the total bandwidth retrieving a webpage takes through Tor in android. In my android app, I create a Tor circuit using the Tor library and retrieves the webpage and then close the Tor circuit. How can I get the total bandwidth (Tor circuit creation + request sent + response received)?
Is it possible to calculate the total bandwidth theoretically, if we know the bandwidth without Tor?
int port = onionProxyManager.getIPv4LocalHostSocksPort();
int proxyPort = port;
String proxyHost = "127.0.0.1";
String remoteHost = "google.com";
int remotePort = 80;
Socks5Proxy socks5Proxy = new Socks5Proxy(proxyHost, proxyPort);
socks5Proxy.resolveAddrLocally(false);
Socket socket = new SocksSocket(socks5Proxy, remoteHost, remotePort);
BufferedReader dIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream dOut = new PrintStream(socket.getOutputStream());
String str = null;
do {
str = dIn.readLine();
response = response + str;
} while (str != null);
onionProxyManager.stop();
Tried Network profiler as suggested by JensV below. I couldn't find total data usage using the network profiler. Is there anything I'm missing? I have added the screenshot below.
I don't think this will be possible. I'm assuming that you're using this library (inferred from your code). I looked at the source of the library and to create tor proxy, it actually spawns a separate process which launches the tor binary.
So while technically somehow possible, the library offers no way of intercepting/inspecting the packets (or packet size) itself.
If you just want to do inspections, you can use the Network Profiler in Android Studio. There you should be able to see how much traffic is being done. You could also collect data this way and approximate how much overhead you have from basic network requests and show an estimate to the user.
You could create a wifi hotspot on your laptop and connect to it via the android phone. From the laptop, you install wireshark to analyze the TOR traffic. If you type in google "setup wifi hotspot Ubuntu", you find a lot of example to set this up. And the same for Wireshark and tor traffic.
Related
All the questions here point to classes of the same app or different apps in separate processes yet in the same device. I would like to send data to and from two separate apps in two separate devices. I tried using broadcastreceiver but it didn't work. Here is my snippet to send the data.
addressstring = String.valueOf(acrilocation.getText());
if (addressstring != null && addressstring.length() > 0){
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Constants.LOCATION_DATA_EXTRA, addressstring);
intent.setType("text/plain");
sendBroadcast(intent);
} else{
Toast.makeText(getApplicationContext(), "Enter valid location address", Toast.LENGTH_SHORT).show();
}
but when I receive the data in my other app using the following code snippet, It fails. When I debug the app I get null exception.
Intent intent = getIntent();
String action = intent.getAction();
String data = intent.getStringExtra(Intent.EXTRA_INTENT);
String type = intent.getType();
useraddress.setText(data);
startActivity(intent);
Is there another way to achieve this? I mean to send data to and from another app which is installed in another device?
Connecting over networks that accept incoming socket connections
The usual way to do this between Android devices (or between any peer devices) is to use sockets.
You set up one or both devices to 'listen' for connections on a socket and then accept a connection from the other when they want to communicate (or you can have a dedicated client and server and the client always initiates the connections).
Once the connection is established you can send messages back and forth.
There are many examples of Android client server socket applications, but one I found useful was:
Android Server/Client example - client side using Socket (and its companion server side blog article - link included in the client blog)
Note that you may have to add your own 'protocol' on top of this - for example if you are sending a file of unknown length without any special 'end' character, you may want to add a byte (or several byte to represent an int, long etc) at the start to indicate the length of the transmission so the receiving side knows when it has received everything (or that it has not received everything in case of an error).
Connecting over networks which do not allow incoming connections (e.g. most 3G/4G)
In these scenarios, while there is nothing theoretically stopping sockets working, in practice many mobile operators will not allow incoming socket connections. In addition you would need to find the public IP address of the Mobile, which is possible but is extra complexity. If your solution will only ever run on a single operators network you can experiment and see if it works, but if not you may find it better and easier to use a server in the 'middle':
Device A connectes to server
Device B connectes to server
Device A asks server for addresses of connected devices and 'discovers' device B
Device A send a message for device B. It actually sends the messages to the server with an indication that it is to be sent to device B
The server notifies device B that a message is available for it (using some sort of message notification like Google Cloud Messaging for example, or simply by the devices polling regularly to see if they have any messages).
Device B retrieves the messages from the server
The above will work on pretty much any network that allows connectivity to the internet. It does have the disadvantage of requiring a server but it is likely a necessary approach over most mobile networks.
If you want the two instances of your Android app on two different devices located on the different parts of the world to communicate with each other directly without the server, then the best way to do it is to use Tor Hidden Services. Tor Hidden Services allow the apps to bypass the firewall or NAT (if Tor is not blocked, of course), and the devices can easily communicate with each other without the need for a central server. Here, I will try to give some code examples that you can try. The best library suitable to this stuff is this.
Step 1: Add dependencies to your gradle.build in app module:
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
dependencies {
compile 'com.github.jehy:Tor-Onion-Proxy-Library:0.0.7'
compile 'org.slf4j:slf4j-api:1.7.7'
compile 'org.slf4j:slf4j-android:1.7.7'
}
Step 2: Add permissions (Internet permissions or whatever) to your manifest file.
Step 3(i): Now we will just write the classic Client-Server programs in Java but with added Android and Tor flavor. To test this properly, try creating two different apps. One app will be the server and the other app will be a client. Preferably, you can even install the two apps on different phones.
In this example, we will try to send "Hello from Tor client" string from client app to server app.
For the server side: You can try this function inside any Activity and AsyncTask.
void server(Context context){
//For comments and documentation, visit the original repo
//https://github.com/thaliproject/Tor_Onion_Proxy_Library
String fileStorageLocation = "hiddenservicemanager";;
com.msopentech.thali.toronionproxy.OnionProxyManager onionProxyManager =
new com.msopentech.thali.android.toronionproxy.AndroidOnionProxyManager(context, fileStorageLocation);
int totalSecondsPerTorStartup = 4 * 60;
int totalTriesPerTorStartup = 5;
try {
boolean ok = onionProxyManager.startWithRepeat(totalSecondsPerTorStartup, totalTriesPerTorStartup);
if (!ok)
System.out.println("Couldn't start tor");
while (!onionProxyManager.isRunning())
Thread.sleep(90);
System.out.println("Tor initialized on port " + onionProxyManager.getIPv4LocalHostSocksPort());
int hiddenServicePort = 8080;
int localPort = 9343;
String onionAddress = onionProxyManager.publishHiddenService(hiddenServicePort, localPort);
System.out.println("Tor onion address of the server is: "+onionAddress);
ServerSocket serverSocket = new ServerSocket(localPort);
while(true) {
System.out.println("Waiting for client request");
Socket receivedSocket = serverSocket.accept();
ObjectInputStream ois = new ObjectInputStream(receivedSocket.getInputStream());
String message = (String) ois.readObject();
//Here we will print the message received from the client to the console.
/*You may want to modify this function to display the received
string in your View.*/
System.out.println("Message Received: " + message);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
Step 3(ii): For the client side try this function
//Inputs:
//'String onionAddress' should be the one obtained in server() function.
//It will be printed in the console and it will possibly remain the same
//even if the app restarts, because all the data/cache will be stored locally.
//Also, when you run the code for the first time, Tor will take about 1 or 2 mins
//to bootstrap. In the subsequent runs, Tor will start relatively faster as the
//data will be cached. 'int hiddenServicePort' is the port at which the hidden
//service has started on the server. In our example code, it is 8080. So, pass that here
void client(Context context, String onionAddress, int hiddenServicePort){
String fileStorageLocation = "clientmanager";
com.msopentech.thali.toronionproxy.OnionProxyManager onionProxyManager =
new com.msopentech.thali.android.toronionproxy.AndroidOnionProxyManager(context, fileStorageLocation);
int totalSecondsPerTorStartup = 4 * 60;
int totalTriesPerTorStartup = 5;
try {
boolean ok = onionProxyManager.startWithRepeat(totalSecondsPerTorStartup, totalTriesPerTorStartup);
int socksPort=onionProxyManager.getIPv4LocalHostSocksPort();
if (!ok)
System.out.println("Couldn't start tor in client");
while (!onionProxyManager.isRunning())
Thread.sleep(90);
System.out.println("Client Tor initialized on port " + socksPort);
System.out.println("Client is waiting for the server to get ready");
Thread.sleep(2000);
Socket clientSocket =
Utilities.socks4aSocketConnection(onionAddress, hiddenServicePort, "127.0.0.1", socksPort);
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream());
oos.writeObject("Hello from Tor client\n");
System.out.println("Client has sent the message");
oos.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
It's done. Run your apps and test it. If you get stuck, try consulting here.
So, now your apps can communicate without any central server. Tor Hidden Services are so awesome in these use cases.
You can also use IP6, then you can do a direct socket connection from one phone to the another. I got latency as low as 60ms between two phones on different 4G operators (in the same country though). Note that you have to send some data to avoid getting down switch to lower speed to get such low latency. 10 concurrent ping was enough for me.
The listen side doesn't need any change at all, the client side just has to use an IP6-address:
s = new Socket("2a10:811:21c:22a1:7683:ae1:18c7:9827", 9343);
IP6 seems to be supported by many operators. If not, tor can be a good fallback, if latency isn't a problem.
I am new to android and is trying to develop an application. I have a local server that has the address like http://abc:9070/
i.e: the server is running only on port number 9070 in my laptop.
Now i want to debug my program using a android device and i have to make sure that the android device listens to port number 9070, So that i can make the post http request call to the url and fetch some information.
Can someone tell me how can i make my device to listen to port number 9070?
Also can someone tell me whether changing default port number of adb solve this.
I have tried a lot to search for a solution. But i am not able to come up with any good answers.
Thanks in advance.
Nobody has expressed an opinion yet. May be the question is not clear, at least I found it very difficult to understand what you are trying to do.
You say you have a server (laptop) listening on port 9070 and you want a device to connect to this server thru this port? Is that right?
Have you try, from your device, launch the navigator and connect to that address? http://abc:9070
Anyway, the java code to make a socket connection is something similar to this:
try
{
Socket clientSocket = new Socket("YOUR_LAPTOP_IP", 9070);
// 1024 is an arbitrary number, could be 512, 65535, etc
byte[] buffer = new byte[1024];
int ret=0;
while ((ret=clientSocket.getInputStream().read(buffer)) > 0)
{
// from now on it's up to you what to do with the data you read
}
clientSocket.close();
}
catch (Exception e)
{
e.printStackTrace();
}
I am new to android. I am just trying to connect my Android device to PC and pass a string to PC using Bluetooth. I have no idea on how to do it. Android side I read about the Bluetooth API. Please suggest me some ways to do it. Thanks in advance.
For Android, my code is slightly different from yours:
BluetoothSocket socket = Device.createRfcommSocketToServiceRecord(device_UUID);
socket.connect();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeChar('x'); // for example
socket.close();
I used DataOutputStream to send data to PC. But surely this doesn't matter, just for your reference.
For PC,
LocalDevice localDevice = LocalDevice.getLocalDevice();
localDevice.setDiscoverable(DiscoveryAgent.GIAC); // Advertising the service
String url = "btspp://localhost:" + device_UUID + ";name=BlueToothServer";
StreamConnectionNotifier server = (StreamConnectionNotifier) Connector.open(url);
StreamConnection connection = server.acceptAndOpen(); // Wait until client connects
//=== At this point, two devices should be connected ===//
DataInputStream dis = connection.openDataInputStream();
char c;
while (true) {
c = dis.readChar();
if (c == 'x')
break;
}
connection.close();
I am not sure if the above codes still work today, as this was done 2 years ago. The BlueCove API may have changed a lot. But anyway, these codes work for me. Hope this may help you.
One more note is that, I had to uninstall the Toshiba Bluetooth Driver in my PC and reinstall the Microsoft one in order to make use of BlueCove. Otherwise, it won't work. (However, latest version of BlueCove may have already supported different drivers, please correct me if I said anything wrong.)
(Author: Victor Wong)
For clarification: on the PC side, you usually have a bluetooth device that comes with a virtual COM port. For testing purposes, you can use any terminal program (e.g. http://realterm.sourceforge.net/). When you start it on your virtual bluetooth serial port and connect your Android device, it will show the received data.
I am currently working on an Android app to be linked into an existing product for my employer. The system is a device running firmware that is controllable via serial, ethernet, or wi-fi using a .NET Windows program, direct serial communication, or a control webpage. The Android app is meant to auto-connect control webpage so that the device is controllable from a phone without anyone having to manually find IP addresses. In order to do that, I need to be able to find IP addresses and determine whether or not the address corresponds to one of these firmware devices.
Essentially what I want to do is run through all IP addresses that the Android sees and send each one to the method above. This thing should ping the address with a firmware command and see what is sent back to determine whether the address corresponds to a firmware device. I’ve been doing that at the moment by sending a command like "HOME" or "GETINFO" (correctly formatted for the firmware, of course) and comparing what, if anything is sent back with the expected response. Commands like home also have the benefit of causing a physical response, so we know without a microchip debugger if the command has at least been received.
As it stands I have the correct address hardcoded and sent in to this method. I know that the app can load the webpage controls successfully using the same address as a URL, so it must be correct and the connection must be good, but direct communication to the device is not working. No physical response is observed and no information is sent back—the Input stream just times out and returns -1. What’s stumping me so badly about this is that as far as I can tell, I’m sending information exactly the same way as the .NET Windows controls, and yet it isn’t working.
One further note: I’m aware that sending the IP Address string to the socket constructor as a hostname probably should not work, but since no UnknownHostException is thrown, I know that the socket can resolve it to an IP Address. Correct?
My code is as follows:
private class NetworkTask extends AsyncTask<String, Boolean, Boolean> {
protected Boolean doInBackground(String... addr){
try {
String message = "<FHGETHUBINFO>";
byte[] input = new byte[8];
//addr is an array of string parameters containing a single IP address string. E.g. addr[0]=”192.168.199.108”
Socket s = new Socket(addr[0],80);
//outgoing stream redirect to socket
OutputStream out = s.getOutputStream();
out.write(message.getBytes());
Log.v(TAG, "output sent. Waiting for input.");
InputStream in = s.getInputStream();
//Skip the exclamation mark and newline. Verified that nothing is received even without a skip.
in.skip(2);
int numBytes = in.read(input,0,8);
Log.v(TAG, "Input received: "+numBytes);
String st = input.toString();
//Close connection
s.close();
if(st != "HUB INFO"){
return true;
}
else{
return false;
}
}
catch (UnknownHostException e) {
Log.v(TAG,"UnknownHostException: "+e.getMessage());
e.printStackTrace();
}
catch (IOException e) {
Log.v(TAG,"IOException: "+e.getMessage());
e.printStackTrace();
}
return false;
Thanks for any help you can give, I really appreciate it!
Agreed that I should be calling isReachable on the socket just for verification purposes, so thanks for the tip! However, it turned out the problem was that the device is not communicating on port 80, so the fact that I have the wrong port is definitely the source of the problem. Thank you for the advice, regardless.
I have read this Bluetooth Chat post, and this Transfer file post.And I have two real android devices ,not AVDs, my
intent is to set IP address and port in one device which acts as a Client while the other acts as a Server.
They are using WIFI,and I have connected both of them to PC respectively.Get into adb shell ,and ping each other.It works.
I have written client code like this:
Socket socket = new Socket("192.168.1.142",8888);
InputStream in = socket.getInputStream();
byte[] buffer = new byte[in.available()];
Toast.makeText(this, String.valueOf(in.available()), Toast.LENGTH_LONG).show();
in.read(buffer);
String msg = new String(buffer);
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
and the Server:
ServerSocket server = new ServerSocket(8888);
while(true) {
Socket client = server.accept();
OutputStream out = client.getOutputStream();
String msg = "Hello Android!";
out.write(msg.getBytes());
client.close();
}
I have add this
<uses-permission android:name="android.permission.INTERNET" /> to manifest.
But no response. I have two questions:
1.Why there is no response in my client?
2.How to handle with sqlite3 database ,there must be something different with ordinary text files,but what is the difference?
Any suggestions will be very appreciated.
It would be unwise to transfer a sqlite3 .db between devices that may be differing make/model/manufacturer/etc. Rather, you should dump the schema and content of database to csv or sql and transfer that. You may want to compress the file too before transfer.
As for networking with Android. If you're using an AVD (emulator) then you're going to find it impossible or near impossible. Your proxy also plays a role in networking so you need to be warey of what it allows, how it's currently configured, and how it behaves (bugs, quirks, features). You should use a tool such as wireshark to inspect network comms and make sure that your App is even sending something out before worrying whether that something gets recieved.