Browse Source

added udp support
use MyDatagramSocketFactory

Mihai Plasoianu 10 years ago
parent
commit
e7071a19eb

+ 29 - 12
native/pp.c

@@ -13,6 +13,9 @@
 
 #define UNIX_PATH "hostage"
 
+#define TCP "TCP"
+#define UDP "UDP"
+
 int ipc_sock() {
 	int fd;
 	struct sockaddr_un addr;
@@ -35,12 +38,12 @@ int ipc_sock() {
 	return fd;
 }
 
-int net_sock(int port) {
+int net_sock(int type, int port) {
 	int fd;
-	int reuse = 1;
+	int reuseaddr = 1;
 	struct sockaddr_in addr;
 
-	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+	if ((fd = socket(AF_INET, (type == 1 ? SOCK_STREAM : SOCK_DGRAM), 0)) == -1) {
 		perror("Unable to create net socket");
 		return -1;
 	}
@@ -50,9 +53,12 @@ int net_sock(int port) {
 	addr.sin_addr.s_addr = INADDR_ANY;
 	addr.sin_port = htons(port);
 
-	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
-		perror("Unable to set socket options");
-		return -1;
+	if (type == 1) {
+		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))
+				== -1) {
+			perror("Unable to set socket options");
+			return -1;
+		}
 	}
 
 	if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
@@ -60,9 +66,11 @@ int net_sock(int port) {
 		return -1;
 	}
 
-	if (listen(fd, 5) == -1) {
-		perror("Unable to listen net socket");
-		return -1;
+	if (type == 1) {
+		if (listen(fd, 5) == -1) {
+			perror("Unable to listen net socket");
+			return -1;
+		}
 	}
 
 	return fd;
@@ -98,14 +106,23 @@ int send_fd(int fd, int fd_to_send) {
 }
 
 int main(int argc, char *argv[]) {
+	int type;
 	int port;
 	int ipc_fd, net_fd;
 
-	if (argc < 2) {
+	if (argc < 3) {
+		exit(EXIT_FAILURE);
+	}
+
+	if (strncmp(argv[1], TCP) == 0) {
+		type = 1;
+	} else if (strncmp(argv[1], UDP) == 0) {
+		type = 0;
+	} else {
 		exit(EXIT_FAILURE);
 	}
 
-	if ((port = atoi(argv[1])) < 1 || (port = atoi(argv[1])) > 65535) {
+	if ((port = atoi(argv[2])) < 1 || (port = atoi(argv[2])) > 65535) {
 		exit(EXIT_FAILURE);
 	}
 
@@ -115,7 +132,7 @@ int main(int argc, char *argv[]) {
 	}
 	printf("ipc_fd: %d\n", ipc_fd);
 
-	if ((net_fd = net_sock(port)) == -1) {
+	if ((net_fd = net_sock(type, port)) == -1) {
 		close(ipc_fd);
 		close(net_fd);
 		exit(EXIT_FAILURE);

+ 64 - 0
src/de/tudarmstadt/informatik/hostage/net/MyDatagramSocketFactory.java

@@ -0,0 +1,64 @@
+package de.tudarmstadt.informatik.hostage.net;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.DatagramSocket;
+import java.net.DatagramSocketImpl;
+import java.net.InetSocketAddress;
+
+import de.tudarmstadt.informatik.hostage.system.Device;
+import de.tudarmstadt.informatik.hostage.system.PrivilegedPort;
+import de.tudarmstadt.informatik.hostage.system.PrivilegedPort.TYPE;
+
+public class MyDatagramSocketFactory {
+
+	public DatagramSocket createDatagramSocket(int port) throws IOException {
+		DatagramSocket socket = null;
+		if (port > 1023) {
+			socket = new DatagramSocket();
+			socket.setReuseAddress(true);
+			socket.bind(new InetSocketAddress(port));
+		} else if (Device.isPPInstalled()) {
+			FileDescriptor fd = new PrivilegedPort(TYPE.UDP, port).getFD();
+			socket = new DatagramSocket();
+			try {
+				DatagramSocketImpl impl = getImpl(socket);
+				injectFD(fd, impl);
+				injectImpl(impl, socket);
+				setBound(socket);
+			} catch (NoSuchFieldException e) {
+			} catch (IllegalAccessException e) {
+			} catch (IllegalArgumentException e) {
+			}
+		}
+		return socket;
+	}
+
+	private DatagramSocketImpl getImpl(DatagramSocket socket) throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException {
+		Field implField = socket.getClass().getDeclaredField("impl");
+		implField.setAccessible(true);
+		return (DatagramSocketImpl) implField.get(socket);
+	}
+
+	private void injectFD(FileDescriptor fd, DatagramSocketImpl impl) throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException {
+		Class<?> plainDatagramSocketImplClazz = impl.getClass();
+		Class<?> datagramSocketImplClazz = plainDatagramSocketImplClazz.getSuperclass();
+		Field fdField = datagramSocketImplClazz.getDeclaredField("fd");
+		fdField.setAccessible(true);
+		fdField.set(impl, fd);
+	}
+
+	private void injectImpl(DatagramSocketImpl impl, DatagramSocket socket) throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException {
+		Field implField = socket.getClass().getDeclaredField("impl");
+		implField.setAccessible(true);
+		implField.set(socket, impl);
+	}
+
+	private void setBound(DatagramSocket socket) throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException {
+		Field boundField = socket.getClass().getDeclaredField("isBound");
+		boundField.setAccessible(true);
+		boundField.set(socket, true);
+	}
+
+}

+ 2 - 1
src/de/tudarmstadt/informatik/hostage/net/MyServerSocketFactory.java

@@ -12,6 +12,7 @@ import javax.net.ServerSocketFactory;
 
 import de.tudarmstadt.informatik.hostage.system.Device;
 import de.tudarmstadt.informatik.hostage.system.PrivilegedPort;
+import de.tudarmstadt.informatik.hostage.system.PrivilegedPort.TYPE;
 
 public class MyServerSocketFactory extends ServerSocketFactory {
 
@@ -23,7 +24,7 @@ public class MyServerSocketFactory extends ServerSocketFactory {
 			socket.setReuseAddress(true);
 			socket.bind(new InetSocketAddress(port));
 		} else if (Device.isPPInstalled()) {
-			FileDescriptor fd = new PrivilegedPort(port).getFD();
+			FileDescriptor fd = new PrivilegedPort(TYPE.TCP, port).getFD();
 			socket = new ServerSocket();
 			try {
 				SocketImpl impl = getImpl(socket);

+ 10 - 3
src/de/tudarmstadt/informatik/hostage/system/PrivilegedPort.java

@@ -12,15 +12,22 @@ import android.util.Log;
 
 public class PrivilegedPort implements Runnable {
 
+	public static enum TYPE {
+		TCP, UDP
+	}
+
 	private final static String UNIX_PATH = "hostage";
 
 	private final String LOG_TAG;
 
+	private TYPE type;
 	private int port;
+
 	private FileDescriptor fd;
 
-	public PrivilegedPort(int port) {
-		LOG_TAG = String.format("hostage (pp %d)", port);
+	public PrivilegedPort(TYPE type, int port) {
+		LOG_TAG = String.format("hostage (pp %s %d)", type.toString(), port);
+		this.type = type;
 		this.port = port;
 		try {
 			new Thread(this).start();
@@ -45,7 +52,7 @@ public class PrivilegedPort implements Runnable {
 
 	@Override
 	public void run() {
-		String command = String.format("/data/local/pp %d", port);
+		String command = String.format("/data/local/pp %s %d", type.toString(), port);
 		try {
 			Process p = new ProcessBuilder("su", "-c", command).start();
 			if (p.waitFor() != 0) {