@Override protected void onHandleIntent(Intent intent) { LogUtils.i("ver: " + getMyVersion(this)); LogUtils.i("rooted: " + ShellUtils.checkRooted()); if (isVpnRunning()) { LogUtils.i("manager is already running in vpn mode"); sendBroadcast(new LaunchedIntent(true)); return; } if (ping(false)) { LogUtils.i("manager is already running in root mode"); sendBroadcast(new LaunchedIntent(false)); return; } if (ping(true)) { LogUtils.i("Restart manager"); try { ManagerProcess.kill(); Thread.sleep(1000); if (ManagerProcess.exists()) { LogUtils.e("failed to restart manager", null); } else { LaunchService.execute(this); } } catch (Exception e) { handleFatalError(LogUtils.e("failed to stop exiting process", e)); } return; } deployAndLaunch(); }
private void passFileDescriptor(LocalSocket fdSocket, FileDescriptor tunFD) throws Exception { OutputStream outputStream = fdSocket.getOutputStream(); InputStream inputStream = fdSocket.getInputStream(); try { BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream), 1); String request = reader.readLine(); String[] parts = request.split(","); LogUtils.i("current open tcp sockets: " + tcpSockets.size()); LogUtils.i("current open udp sockets: " + udpSockets.size()); if ("TUN".equals(parts[0])) { fdSocket.setFileDescriptorsForSend(new FileDescriptor[] {tunFD}); outputStream.write('*'); } else if ("OPEN UDP".equals(parts[0])) { String socketId = parts[1]; passUdpFileDescriptor(fdSocket, outputStream, socketId); } else if ("OPEN TCP".equals(parts[0])) { String socketId = parts[1]; String dstIp = parts[2]; int dstPort = Integer.parseInt(parts[3]); int connectTimeout = Integer.parseInt(parts[4]); passTcpFileDescriptor(fdSocket, outputStream, socketId, dstIp, dstPort, connectTimeout); } else if ("CLOSE UDP".equals(parts[0])) { String socketId = parts[1]; DatagramSocket sock = udpSockets.get(socketId); if (sock != null) { udpSockets.remove(socketId); sock.close(); } } else if ("CLOSE TCP".equals(parts[0])) { String socketId = parts[1]; Socket sock = tcpSockets.get(socketId); if (sock != null) { tcpSockets.remove(socketId); sock.close(); } } else { throw new UnsupportedOperationException("fdsock unable to handle: " + request); } } finally { try { inputStream.close(); } catch (Exception e) { LogUtils.e("failed to close input stream", e); } try { outputStream.close(); } catch (Exception e) { LogUtils.e("failed to close output stream", e); } fdSocket.close(); } }
private Process executeManager(boolean isVpnMode) throws Exception { Map<String, String> env = new HashMap<String, String>() { { put("FQROUTER_VERSION", getMyVersion(LaunchService.this)); } }; env.putAll(ShellUtils.pythonEnv()); if (isVpnMode) { Process process = ShellUtils.executeNoWait(env, ShellUtils.BUSYBOX_FILE.getCanonicalPath(), "sh"); OutputStreamWriter stdin = new OutputStreamWriter(process.getOutputStream()); try { String command = Deployer.PYTHON_LAUNCHER + " " + Deployer.MANAGER_VPN_PY.getAbsolutePath() + " > /data/data/fq.router/log/current-python.log 2>&1"; LogUtils.i("write to stdin: " + command); stdin.write(command); stdin.write("\nexit\n"); } finally { stdin.close(); } return process; } else { try { LogUtils.i( ShellUtils.sudo( env, Deployer.PYTHON_LAUNCHER + " -c \"import os; print 'current user id: %s' % os.getuid()\"") .trim()); } catch (Exception e) { LogUtils.e("log current user id failed", e); } return ShellUtils.sudoNoWait( env, Deployer.PYTHON_LAUNCHER + " " + Deployer.MANAGER_MAIN_PY.getAbsolutePath() + " > /data/data/fq.router/log/current-python.log 2>&1"); } }
private void deployAndLaunch() { try { LogUtils.i("Kill existing manager process"); LogUtils.i("try to kill manager process before launch"); ManagerProcess.kill(); } catch (Exception e) { LogUtils.e("failed to kill manager process before launch", e); LogUtils.i("failed to kill manager process before launch"); } Deployer deployer = new Deployer(this); String fatalError = deployer.deploy(); if (!fatalError.isEmpty()) { handleFatalError(fatalError); return; } updateConfigFile(this); LogUtils.i("Launching..."); if (ShellUtils.checkRooted()) { fatalError = launch(false); if (fatalError.isEmpty()) { sendBroadcast(new LaunchedIntent(false)); } else { handleFatalError(fatalError); } } else { if (Build.VERSION.SDK_INT < 14) { handleFatalError("[ROOT] is required"); return; } fatalError = launch(true); if (fatalError.isEmpty()) { sendBroadcast(new LaunchedIntent(true)); } else { handleFatalError(fatalError); } } }
private void startVpn() { try { if (tunPFD != null) { throw new RuntimeException("another VPN is still running"); } tunPFD = new Builder() .setSession("fqrouter") .addAddress("10.25.1.1", 24) .addRoute("0.0.0.0", 0) .addDnsServer("8.8.8.8") .establish(); if (tunPFD == null) { stopSelf(); return; } final int tunFD = tunPFD.getFd(); LogUtils.i("tunFD is " + tunFD); new Thread( new Runnable() { @Override public void run() { try { listenFdServerSocket(tunPFD); } catch (Exception e) { LogUtils.e("fdsock failed " + e, e); } } }) .start(); updateStatus("Started in VPN mode"); sendBroadcast(new LaunchedIntent(true)); } catch (Exception e) { LogUtils.e("establish failed", e); } }
@Override public void onStart(Intent intent, int startId) { startVpn(); LogUtils.i("on start"); }