Search code examples
javaandroidkotlinsocketstcp

Why can I successfully connect to a netcat server from the adb shell and not from the Android app?


I'm trying to send a TCP message to a netcat server running on the machine where an Android device is connected.

In order to do so, I'm executing the following steps on the host:

adb reverse tcp:3000 tcp:3000
nc -l -p 3000

By running the device shell and performing the following command:

adb shell
> nc localhost 3000

I can receive arbitrary bytes from the device successfully.

Now, I'm trying to do the same with the following simple Android activity:

@file:OptIn(kotlin.ExperimentalStdlibApi::class)

package tcp.connection

import android.os.Bundle
import android.util.Log
import kotlinx.coroutines.runBlocking
import androidx.appcompat.app.AppCompatActivity
import java.io.PrintWriter
import java.lang.Exception
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Socket

class MainActivity : AppCompatActivity() {

    private val TAG = "[Main]"
    private val WS_DEFAULT_PORT = 3000
    private val WS_DEFAULT_HOST = "localhost"
    private val WS_DEFAULT_TIMEOUT = 10_000L

    private val INTENT_KEY_WS_HOST = "wsHost"
    private val INTENT_KEY_WS_PORT = "wsPort"
    private val INTENT_KEY_WS_TIMEOUT = "wsTimeout"

    private var wsHost = WS_DEFAULT_HOST
    private var wsPort = WS_DEFAULT_PORT
    private var wsTimeout = WS_DEFAULT_TIMEOUT

    fun tcpPing() {
        Log.d(TAG, "PROBLEM - 1")
        try {
            // Create a socket to connect to the server
            Log.d(TAG, "PROBLEM - 2")
            val socket = Socket()
            Log.d(TAG, "PROBLEM - 3 socket created")
            socket.connect(InetSocketAddress(wsHost, wsPort), wsTimeout.toInt())
            Log.d(TAG, "PROBLEM - 4 socket connection estabilished")
            // Send the message
            val autoflush = true
            val msg = "PING\n"
            PrintWriter(socket.getOutputStream(), autoflush).write(msg)
            // Close the socket
            Log.d(TAG, "PROBLEM - 5 before closing")
            socket.close()
            Log.d(TAG, "PROBLEM - 6 after closing")
        } catch (e: Exception) {
            e.printStackTrace()
            Log.d(TAG, "PROBLEM - 7 failed")
        }
    }

    @OptIn(ExperimentalUnsignedTypes::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Send intent extra by adding --es <param> to the launch.sh
        // script
        if (intent.extras != null) {
            wsHost = intent.extras!!.getString(INTENT_KEY_WS_HOST, WS_DEFAULT_HOST)
            wsPort =
                intent.extras!!.getString(INTENT_KEY_WS_PORT, WS_DEFAULT_PORT.toString()).toInt()
            wsTimeout =
                intent.extras!!.getString(INTENT_KEY_WS_TIMEOUT, WS_DEFAULT_TIMEOUT.toString())
                    .toLong()
        }

        Log.d(TAG, "Host: $wsHost")
        Log.d(TAG, "Port: $wsPort")
        Log.d(TAG, "Timeout: $wsTimeout")

        val t = object : Thread() {
            override fun run() {
                super.run()
                tcpPing()
            }
        }
        
        runBlocking { t.start() }
    }

    override fun onStop() {
        super.onStop()
    }
}

And with these entries in the AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

This is the relevant log shown on logcat:

08-08 11:46:42.817 13722 13722 D [Main]  : Host: localhost
08-08 11:46:42.817 13722 13722 D [Main]  : Port: 3000
08-08 11:46:42.817 13722 13722 D [Main]  : Timeout: 10000
08-08 11:46:42.910 13722 13748 D [Main]  : PROBLEM - 1
08-08 11:46:42.910 13722 13748 D [Main]  : PROBLEM - 2
08-08 11:46:42.911 13722 13748 D [Main]  : PROBLEM - 3 socket created
08-08 11:46:52.936 13722 13748 W System.err: java.net.SocketTimeoutException: failed to connect to localhost/127.0.0.1 (port 3000) from /127.0.0.1 (port 42064) after 10000ms                                                                                                                        
08-08 11:46:52.938 13722 13748 W System.err:    at libcore.io.IoBridge.connectErrno(IoBridge.java:191)                                                                                                                                                                                               
08-08 11:46:52.939 13722 13748 W System.err:    at libcore.io.IoBridge.connect(IoBridge.java:135)                                                 
08-08 11:46:52.939 13722 13748 W System.err:    at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)                                                                                                                                                                                  
08-08 11:46:52.940 13722 13748 W System.err:    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)                                                                                                                                                                      
08-08 11:46:52.940 13722 13748 W System.err:    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)            
08-08 11:46:52.941 13722 13748 W System.err:    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)                                                                                                                                                                        
08-08 11:46:52.941 13722 13748 W System.err:    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
08-08 11:46:52.942 13722 13748 W System.err:    at java.net.Socket.connect(Socket.java:621)                                                                                                                                                                                                          
08-08 11:46:52.943 13722 13748 W System.err:    at tcp.connection.MainActivity.tcpPing(MainActivity.kt:126)                                                                                                                                                                                       
08-08 11:46:52.945 13722 13748 W System.err:    at tcp.connection.MainActivity$onCreate$t$1.run(MainActivity.kt:200)                           
08-08 11:46:52.945 13722 13748 D [Main]  : PROBLEM - 7 failed 

What am I doing wrong?

Thank you in advance.


Solution

  • This was due to the device's display being locked when launching the app: disabling the Power Saving configuration and disabling the lock of the device solved the issue.