diff --git a/.classpath b/.classpath
index 7bc01d9a..e5f25532 100644
--- a/.classpath
+++ b/.classpath
@@ -5,5 +5,6 @@
+
diff --git a/gen/com/limelight/R.java b/gen/com/limelight/R.java
index 47c9ea76..3395dcbb 100644
--- a/gen/com/limelight/R.java
+++ b/gen/com/limelight/R.java
@@ -35,15 +35,11 @@ or to a theme attribute in the form "?[package:][type:]na
public static final int ic_launcher=0x7f020000;
}
public static final class id {
-<<<<<<< HEAD
- public static final int mDNSResultView=0x7f080000;
- public static final int surfaceView=0x7f080001;
-=======
- public static final int hostTextView=0x7f080002;
+ public static final int hostTextView=0x7f080003;
+ public static final int mDNSResultView=0x7f080002;
public static final int pairButton=0x7f080000;
public static final int statusButton=0x7f080001;
- public static final int surfaceView=0x7f080003;
->>>>>>> d7062ac2e0b306c42144c84690a3735c5878e11d
+ public static final int surfaceView=0x7f080004;
}
public static final class layout {
public static final int activity_connection=0x7f030000;
diff --git a/libs/dnsjava-2.1.5.jar b/libs/dnsjava-2.1.6.jar
similarity index 81%
rename from libs/dnsjava-2.1.5.jar
rename to libs/dnsjava-2.1.6.jar
index e928fad9..6bd9b2ee 100644
Binary files a/libs/dnsjava-2.1.5.jar and b/libs/dnsjava-2.1.6.jar differ
diff --git a/res/layout/activity_connection.xml b/res/layout/activity_connection.xml
index 4ef82e8f..c7ad9d47 100644
--- a/res/layout/activity_connection.xml
+++ b/res/layout/activity_connection.xml
@@ -16,7 +16,7 @@
android:layout_centerHorizontal="true"
android:text="Pair with PC"/>
-<<<<<<< HEAD
+
-=======
+
->>>>>>> d7062ac2e0b306c42144c84690a3735c5878e11d
+
diff --git a/src/com/limelight/Connection.java b/src/com/limelight/Connection.java
index fd398ad3..5e80d252 100644
--- a/src/com/limelight/Connection.java
+++ b/src/com/limelight/Connection.java
@@ -1,13 +1,8 @@
package com.limelight;
import java.io.IOException;
-<<<<<<< HEAD
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-=======
+
import java.net.SocketException;
->>>>>>> d7062ac2e0b306c42144c84690a3735c5878e11d
import org.xmlpull.v1.XmlPullParserException;
@@ -34,15 +29,13 @@ public class Connection extends Activity {
private static final String DEFAULT_HOST = "192.168.1.240";
public static final String HOST_KEY = "hostText";
-<<<<<<< HEAD
+
@Override
public void onResume() {
super.onResume();
}
-=======
->>>>>>> d7062ac2e0b306c42144c84690a3735c5878e11d
@Override
public void onPause() {
SharedPreferences.Editor editor = prefs.edit();
@@ -64,41 +57,29 @@ public class Connection extends Activity {
Log.v("NvmDNS", "onCreate");
- try {
NvmDNS dns = new NvmDNS();
dns.execute();
- } catch (IOException e2) {
- // TODO Auto-generated catch block
- e2.printStackTrace();
- }
setContentView(R.layout.activity_connection);
-<<<<<<< HEAD
- // this.statusButton = (Button) findViewById(R.id.statusButton);
- // this.hostText = (TextView) findViewById(R.id.hostTextView);
-=======
this.statusButton = (Button) findViewById(R.id.statusButton);
this.pairButton = (Button) findViewById(R.id.pairButton);
this.hostText = (TextView) findViewById(R.id.hostTextView);
->>>>>>> d7062ac2e0b306c42144c84690a3735c5878e11d
+
//prefs = getPreferences(0);
//this.hostText.setText(prefs.getString(Connection.HOST_KEY, Connection.DEFAULT_HOST));
- /*this.statusButton.setOnClickListener(new OnClickListener() {
+ this.statusButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent(Connection.this, Game.class);
intent.putExtra("host", Connection.this.hostText.getText().toString());
Connection.this.startActivity(intent);
}
-<<<<<<< HEAD
- });*/
-=======
});
this.pairButton.setOnClickListener(new OnClickListener() {
@@ -154,7 +135,7 @@ public class Connection extends Activity {
}).start();
}
});
->>>>>>> d7062ac2e0b306c42144c84690a3735c5878e11d
+
}
}
diff --git a/src/com/limelight/nvstream/NvComputer.java b/src/com/limelight/nvstream/NvComputer.java
index 99d77431..e60ff5bf 100644
--- a/src/com/limelight/nvstream/NvComputer.java
+++ b/src/com/limelight/nvstream/NvComputer.java
@@ -1,8 +1,8 @@
package com.limelight.nvstream;
import java.net.InetAddress;
-import java.util.HashSet;
import java.util.Locale;
+import java.util.UUID;
public class NvComputer {
private String mDNSResponse;
@@ -12,15 +12,14 @@ public class NvComputer {
private int numOfApps;
private String gpuType;
private String mac;
- private String uniqueID;
+ private UUID uniqueID;
- private HashSet games;
private int sessionID;
private boolean paired;
private boolean isBusy;
- public NvComputer(String mDNSResponse, InetAddress ipAddress, String ipAddressString, int state, int numOfApps, String gpuType, String mac, String uniqueID) {
+ public NvComputer(String mDNSResponse, InetAddress ipAddress, String ipAddressString, int state, int numOfApps, String gpuType, String mac, UUID uniqueID) {
this.mDNSResponse = mDNSResponse;
this.ipAddress = ipAddress;
this.ipAddressString = ipAddressString;
@@ -29,8 +28,6 @@ public class NvComputer {
this.gpuType = gpuType;
this.mac = mac;
this.uniqueID = uniqueID;
-
- this.games = new HashSet();
}
public String getmDNSResponse() {
@@ -46,7 +43,7 @@ public class NvComputer {
}
public String getIPAddressString() {
- return this.ipAddress.getCanonicalHostName().toLowerCase();
+ return this.ipAddress.getCanonicalHostName().toLowerCase(Locale.getDefault());
}
public int getState() {
@@ -65,18 +62,10 @@ public class NvComputer {
return this.mac;
}
- public String getUniqueID() {
+ public UUID getUniqueID() {
return this.uniqueID;
}
-
- public boolean addGame(NvComputerGame game) {
- return this.games.add(game);
- }
- public HashSet getGames() {
- return this.games;
- }
-
public void updateAfterPairQuery(int sessionID, boolean paired, boolean isBusy) {
this.sessionID = sessionID;
@@ -127,53 +116,10 @@ public class NvComputer {
}
public boolean equals(Object obj) {
- NvComputer otherComputer = (NvComputer)obj;
- if (this.ipAddress == null && otherComputer.getIpAddress() == null) {
- return true;
- } else if (this.ipAddress == null || otherComputer.getIpAddress() == null) {
- return false;
+ if (obj instanceof UUID) {
+ return this.uniqueID.equals(obj);
} else {
- return this.ipAddress.equals(otherComputer.getIpAddress());
- }
- }
-
- public class NvComputerGame {
- private Integer ID;
- private String appTitle;
- private Boolean isRunning;
- private Integer gameSession;
- private Integer winLogon;
-
- public NvComputerGame(int ID, String appTitle, boolean isRunning) {
- this.ID = ID;
- this.appTitle = appTitle;
- this.isRunning = isRunning;
- }
-
- public void launchedGame(int gameSession, int winLogon) {
- this.isRunning = true;
- this.gameSession = gameSession;
- this.winLogon = winLogon;
- }
-
- public Integer getID() {
- return this.ID;
- }
-
- public String getAppTitle() {
- return this.appTitle;
- }
-
- public Boolean getIsRunning() {
- return this.isRunning;
- }
-
- public Integer getGameSession() {
- return this.gameSession;
- }
-
- public Integer winLogon() {
- return this.winLogon;
+ return false;
}
}
}
\ No newline at end of file
diff --git a/src/com/limelight/nvstream/NvmDNS.java b/src/com/limelight/nvstream/NvmDNS.java
index 62892f52..5efd2f55 100644
--- a/src/com/limelight/nvstream/NvmDNS.java
+++ b/src/com/limelight/nvstream/NvmDNS.java
@@ -7,7 +7,11 @@ import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
import org.xbill.DNS.DClass;
import org.xbill.DNS.Header;
@@ -15,214 +19,228 @@ import org.xbill.DNS.Message;
import org.xbill.DNS.Name;
import org.xbill.DNS.Record;
import org.xbill.DNS.Section;
+import org.xbill.DNS.TXTRecord;
+import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
-import android.content.Context;
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdManager.DiscoveryListener;
-import android.net.nsd.NsdManager.ResolveListener;
-import android.net.nsd.NsdServiceInfo;
import android.os.AsyncTask;
import android.util.Log;
-/**
- * NvmDNS implements a clone of the NVidia Shield mDNS service for use on Limelight
- * @author yetanothername
- *
- */
public class NvmDNS extends AsyncTask {
- public static String NVSTREAM_MDNS_QUERY = "_nvstream._tcp.local.";
- public static String NVSTREAM_MDNS_MULTICAST_GROUP = "224.0.0.251";
- public static InetAddress NVSTREAM_MDNS_MULTICAST_ADDRESS;
- public static final short NVSTREAM_MDNS_PORT = 5353;
+ public static String MDNS_QUERY = "_nvstream._tcp.local.";
+ public static String MDNS_MULTICAST_GROUP = "224.0.0.251";
+ public static InetAddress MDNS_MULTICAST_ADDRESS;
+ public static final short MDNS_PORT = 5353;
- private HashSet nvstream_mdns_responses;
-
- private MulticastSocket nvstream_socket;
+ public static final int WAIT_MS = 5000;
+
+ private HashSet responses;
+ private MulticastSocket socket;
static {
try {
- NVSTREAM_MDNS_MULTICAST_ADDRESS = InetAddress.getByName(NvmDNS.NVSTREAM_MDNS_MULTICAST_GROUP);
+ MDNS_MULTICAST_ADDRESS = InetAddress.getByName(NvmDNS.MDNS_MULTICAST_GROUP);
} catch (UnknownHostException e) {
- NVSTREAM_MDNS_MULTICAST_ADDRESS = null;
+ MDNS_MULTICAST_ADDRESS = null;
}
}
-
-
- /**
- * We need to convert the IP Address into an IP Object
- */
- static {
- try {
- NVSTREAM_MDNS_MULTICAST_ADDRESS = InetAddress.getByName(NvmDNS.NVSTREAM_MDNS_MULTICAST_GROUP);
- } catch (UnknownHostException e) {
- NVSTREAM_MDNS_MULTICAST_ADDRESS = null;
- }
- }
-
- /**
- * This sets up the query sockets and the list, as well as sends out the query and listens for responses
- * @throws IOException When shit breaks
- */
- public NvmDNS() throws IOException {
- Log.v("NvmDNS", "Constructor entered");
- this.nvstream_mdns_responses = new HashSet();
- Log.v("NvmDNS", "Constructor exited");
- }
- private void makeFakeData() {
+ public NvmDNS() {
+ this.responses = new HashSet();
+
+ // Create our Socket Connection
try {
- this.nvstream_mdns_responses.add(new NvComputer("127.0.0.1",
- InetAddress.getByName("127.0.0.1"),
- InetAddress.getByName("127.0.0.1").getCanonicalHostName(),
- 0,
- 4,
- "Intel(R) Extreme Graphics 3",
- "DE:AD:BE:EF:CA:FE",
- "foo"));
- this.nvstream_mdns_responses.add(new NvComputer("10.0.2.15",
- InetAddress.getByName("10.0.2.15"),
- InetAddress.getByName("10.0.2.15").getCanonicalHostName(),
- 0,
- 5,
- "Intel(R) Extreme Graphics 2",
- "DE:AD:BE:EF:CA:FE",
- "bar"));
- } catch (Exception e) {
-
+ this.socket = new MulticastSocket(NvmDNS.MDNS_PORT);
+ this.socket.setLoopbackMode(false);
+ this.socket.joinGroup(NvmDNS.MDNS_MULTICAST_ADDRESS);
+ Log.v("NvmDNS Socket Constructor", "Created mDNS listening socket");
+ } catch (IOException e) {
+ Log.e("NvmDNS Socket Constructor", "There was an error creating the DNS socket.");
+ Log.e("NvmDNS Socket Constructor", e.getMessage());
}
}
- public void sendQueryAndWait() {
- this.makeFakeData();
+ public Set getComputers() {
+ return Collections.unmodifiableSet(this.responses);
+ }
+
+ private void sendQuery() {
+ Header queryHeader = new Header();
+
+ // If we set the RA (Recursion Available) flag and our message ID to 0
+ // then the packet matches the real mDNS query packet as displayed in Wireshark
+ queryHeader.setFlag(org.xbill.DNS.Flags.RA);
+ queryHeader.setID(0);
+
+ Record question = null;
try {
- Log.v("NvmDNS UDP Loop", "mDNS Loop Started");
+ // We need to create our "Question" DNS query that is a pointer record to
+ // the mDNS Query "Name"
+ question = Record.newRecord(new Name(NvmDNS.MDNS_QUERY), Type.PTR, DClass.IN);
+ } catch (TextParseException e) {
+ Log.e("NvmDNS Query", e.getMessage());
+ return;
+ }
- this.nvstream_socket = new MulticastSocket(NvmDNS.NVSTREAM_MDNS_PORT);
- this.nvstream_socket.setLoopbackMode(false);
- this.nvstream_socket.joinGroup(NvmDNS.NVSTREAM_MDNS_MULTICAST_ADDRESS);
+ // We combine our header and our question into a single message
+ Message query = new Message();
+ query.setHeader(queryHeader);
+ query.addRecord(question, Section.QUESTION);
- Log.v("NvmDNS UDP Loop", "Multicast Socket Created @" + this.nvstream_socket.getLocalPort());
+ // Convert the message into Network Byte Order
+ byte[] wireQuery = query.toWire();
+ Log.v("NvmDNS Query", query.toString());
+
+ // Convert our byte array into a Packet
+ DatagramPacket transmitPacket = new DatagramPacket(wireQuery, wireQuery.length);
+ transmitPacket.setAddress(NvmDNS.MDNS_MULTICAST_ADDRESS);
+ transmitPacket.setPort(NvmDNS.MDNS_PORT);
- Header queryHeader = new Header();
- queryHeader.setFlag(org.xbill.DNS.Flags.RA);
- queryHeader.setID(0);
+ // And (attempt) to send the packet
+ try {
+ Log.v("NvmDNS Query", "Blocking on this.nvstream_socket.send(transmitPacket)");
+ this.socket.send(transmitPacket);
+ Log.v("NvmDNS Query", "Passed this.nvstream_socket.send(transmitPacket)");
+ } catch (IOException e) {
+ Log.e("NvmDNS Query", "There was an error sending the DNS query.");
+ Log.e("NvmDNS Query", e.getMessage());
+ }
+ }
- Record question = Record.newRecord(new Name(NvmDNS.NVSTREAM_MDNS_QUERY), Type.PTR, DClass.IN);
+ public void waitForResponses() {
+ Log.v("NvmDNS Response", "mDNS Loop Started");
+
+ // We support up to 1500 byte packets
+ byte[] data = new byte[1500];
+ DatagramPacket packet = new DatagramPacket(data, data.length);
+
+ Message message = null;
- Message query = new Message();
- query.setHeader(queryHeader);
- query.addRecord(question, Section.QUESTION);
-
- byte[] wireQuery = query.toWire();
-
- Log.v("NvmDNS UDP Loop", "Query: " + query.toString());
-
- DatagramPacket transmitPacket = new DatagramPacket(wireQuery, wireQuery.length);
- transmitPacket.setAddress(NvmDNS.NVSTREAM_MDNS_MULTICAST_ADDRESS);
- transmitPacket.setPort(NvmDNS.NVSTREAM_MDNS_PORT);
-
-
-
- this.nvstream_socket.send(transmitPacket);
- Log.v("NvmDNS UDP Loop", "Query Sent");
-
- byte[] data = new byte[1500];
- DatagramPacket packet = new DatagramPacket(data, data.length);
- Message message = null;
-
- while (true) {
-
- Log.d("NvmDNS UDP Loop", "Blocking on this.nvstream_query_socket.recieve()");
- this.nvstream_socket.receive(packet);
- Log.d("NvmDNS UDP Loop", "Blocking passed on this.nvstream_query_socket.recieve()");
-
+ while (!this.socket.isClosed()) {
+ // Attempt to receive a packet/response
+ try {
+ Log.d("NvmDNS Response", "Blocking on this.nvstream_query_socket.recieve()");
+ this.socket.receive(packet);
+ Log.d("NvmDNS Response", "Blocking passed on this.nvstream_query_socket.recieve()");
message = new Message(packet.getData());
- Record[] responses = message.getSectionArray(Section.ADDITIONAL);
- if (responses.length != 0 && message.getSectionArray(Section.ANSWER).length != 0 &&
- message.getSectionArray(Section.ANSWER)[0].getName().toString().equals(NvmDNS.NVSTREAM_MDNS_QUERY)) {
-
- Log.v("NvmDNS UDP Reply", "Got a packet from " + packet.getAddress().getCanonicalHostName());
- Log.v("NvmDNS UDP Reply", "Question: " + message.getSectionArray(Section.ANSWER)[0].getName().toString());
- Log.v("NvmDNS UDP Reply", "Response: " + responses[0].getName().toString());
+ } catch (IOException e) {
+ if (this.socket.isClosed()) {
+ Log.e("NvmDNS Response", "The socket was closed on us. The timer must have been reached.");
+ return;
+ } else {
+ Log.e("NvmDNS Response", "There was an error receiving the response.");
+ Log.e("NvmDNS Response", e.getMessage());
+ continue;
+ }
+ }
+
+ // We really only care about the ADDITIONAL section (specifically the text records)
+ Record[] responses = message.getSectionArray(Section.ADDITIONAL);
+
+ // We only want to process records that actually have a length, have an ANSWER
+ // section that has stuff in it and that the ANSWER to our query is what we sent
+ if (responses.length != 0 &&
+ message.getSectionArray(Section.ANSWER).length != 0 &&
+ message.getSectionArray(Section.ANSWER)[0].getName().toString().equals(NvmDNS.MDNS_QUERY)) {
+
+ Log.v("NvmDNS Response", "Got a packet from " + packet.getAddress().getCanonicalHostName());
+ Log.v("NvmDNS Response", "Question: " + message.getSectionArray(Section.ANSWER)[0].getName().toString());
+ Log.v("NvmDNS Response", "Response: " + responses[0].getName().toString());
- String[] txtRecords = responses[0].rdataToString().split("\" \"");
-
- // No, but really, there has to be a better way of doing this...
- txtRecords[0] = txtRecords[0].substring(1);
- txtRecords[txtRecords.length - 1] = txtRecords[txtRecords.length - 1].split("\"")[0];
-
- int state = -1;
- int numOfApps = -1;
- String gpuType = "Intel(R) Extreme Graphics 2";
- String mac = "DE:AD:BE:EF:CA:FE";
- String uniqueID = "4";
-
- for (int i = 0; i < txtRecords.length; i++) {
- if (i == 0) {
- state = Integer.parseInt(txtRecords[i].split("=")[1]);
- } else if (i == 1) {
- numOfApps = Integer.parseInt(txtRecords[i].split("=")[1]);
- } else if (i == 2) {
- gpuType = txtRecords[i].split("=")[1];
- } else if (i == 3) {
- mac = txtRecords[i].split("=")[1];
- } else if (i == 4) {
- uniqueID = txtRecords[i].split("=")[1];
- }
+ // The DNS library we are using does not use inferred generics :(
+
+ TXTRecord txtRecord = null;
+
+
+ for (Record record : responses) {
+ Log.v("NvmDNS Response", "We recieved a DNS repsonse with a " + record.getClass().getName() + " record.");
+ if (record instanceof TXTRecord) {
+ txtRecord = (TXTRecord)record;
}
-
+ }
+
+ if (txtRecord == null) {
+ Log.e("NvmDNS Response", "We recieved a malformed DNS repsonse with no TXTRecord");
+ continue;
+ }
+
+ @SuppressWarnings("unchecked")
+ ArrayList> txtRecordStringList = new ArrayList