private void passTcpFileDescriptor( LocalSocket fdSocket, OutputStream outputStream, String socketId, String dstIp, int dstPort, int connectTimeout) throws Exception { Socket sock = new Socket(); sock.setTcpNoDelay(true); // force file descriptor being created if (protect(sock)) { try { sock.connect(new InetSocketAddress(dstIp, dstPort), connectTimeout); ParcelFileDescriptor fd = ParcelFileDescriptor.fromSocket(sock); tcpSockets.put(socketId, sock); fdSocket.setFileDescriptorsForSend(new FileDescriptor[] {fd.getFileDescriptor()}); outputStream.write('*'); outputStream.flush(); fd.detachFd(); } catch (ConnectException e) { LogUtils.e("connect " + dstIp + ":" + dstPort + " failed"); outputStream.write('!'); sock.close(); } catch (SocketTimeoutException e) { LogUtils.e("connect " + dstIp + ":" + dstPort + " failed"); outputStream.write('!'); sock.close(); } finally { outputStream.flush(); } } else { LogUtils.e("protect tcp socket failed"); } }
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 void passUdpFileDescriptor( LocalSocket fdSocket, OutputStream outputStream, String socketId) throws Exception { DatagramSocket sock = new DatagramSocket(); if (protect(sock)) { ParcelFileDescriptor fd = ParcelFileDescriptor.fromDatagramSocket(sock); udpSockets.put(socketId, sock); fdSocket.setFileDescriptorsForSend(new FileDescriptor[] {fd.getFileDescriptor()}); outputStream.write('*'); outputStream.flush(); fd.detachFd(); } else { LogUtils.e("protect udp socket failed"); } }
public void testLocalConnections() throws IOException { // create client and server socket LocalServerSocket localServerSocket = new LocalServerSocket(mSockAddr); LocalSocket clientSocket = new LocalSocket(); // establish connection between client and server LocalSocketAddress locSockAddr = new LocalSocketAddress(mSockAddr); assertFalse(clientSocket.isConnected()); clientSocket.connect(locSockAddr); assertTrue(clientSocket.isConnected()); LocalSocket serverSocket = localServerSocket.accept(); Credentials credent = clientSocket.getPeerCredentials(); assertTrue(0 != credent.getPid()); // send data from client to server OutputStream clientOutStream = clientSocket.getOutputStream(); clientOutStream.write(12); InputStream serverInStream = serverSocket.getInputStream(); assertEquals(12, serverInStream.read()); // send data from server to client OutputStream serverOutStream = serverSocket.getOutputStream(); serverOutStream.write(3); InputStream clientInStream = clientSocket.getInputStream(); assertEquals(3, clientInStream.read()); // Test sending and receiving file descriptors clientSocket.setFileDescriptorsForSend(new FileDescriptor[] {FileDescriptor.in}); clientOutStream.write(32); assertEquals(32, serverInStream.read()); FileDescriptor[] out = serverSocket.getAncillaryFileDescriptors(); assertEquals(1, out.length); FileDescriptor fd = clientSocket.getFileDescriptor(); assertTrue(fd.valid()); // shutdown input stream of client clientSocket.shutdownInput(); assertEquals(-1, clientInStream.read()); // shutdown output stream of client clientSocket.shutdownOutput(); try { clientOutStream.write(10); fail("testLocalSocket shouldn't come to here"); } catch (IOException e) { // expected } // shutdown input stream of server serverSocket.shutdownInput(); assertEquals(-1, serverInStream.read()); // shutdown output stream of server serverSocket.shutdownOutput(); try { serverOutStream.write(10); fail("testLocalSocket shouldn't come to here"); } catch (IOException e) { // expected } // close client socket clientSocket.close(); try { clientInStream.read(); fail("testLocalSocket shouldn't come to here"); } catch (IOException e) { // expected } // close server socket serverSocket.close(); try { serverInStream.read(); fail("testLocalSocket shouldn't come to here"); } catch (IOException e) { // expected } }