Skip to content

Instantly share code, notes, and snippets.

@Andoryuuta
Created April 15, 2017 09:03
Show Gist options
  • Save Andoryuuta/903fd6f3b3ed741a8d21e84283924699 to your computer and use it in GitHub Desktop.
Save Andoryuuta/903fd6f3b3ed741a8d21e84283924699 to your computer and use it in GitHub Desktop.
ListRen.java
import java.net.*;
import java.io.*;
import java.util.*;
import java.nio.charset.StandardCharsets;
class HostAddr {
public HostAddr(String ip, int port){
Ip = ip;
Port = port;
}
public String Ip;
public int Port;
}
class InvalidResponseException extends Exception
{
//Parameterless Constructor
public InvalidResponseException() {}
//Constructor that accepts a message
public InvalidResponseException(String message)
{
super(message);
}
}
public class ListRen {
public static final String RENLIST_SERVER = "master-gsa.renlist.n00b.hk";
public static final int RENLIST_PORT = 28900;
private static HashMap<String, String> GetHostStatus(HostAddr host) throws IOException {
HashMap<String, String> gameOptions = new HashMap<String, String>();
DatagramSocket sock = new DatagramSocket();
// Prepare and send the \status\ UDP datagram
byte[] statusBytes = "\\status\\".getBytes();
DatagramPacket packet = new DatagramPacket(statusBytes, statusBytes.length, InetAddress.getByName(host.Ip), host.Port);
sock.send(packet);
// Create and read into big buffer for receiving
packet.setData(new byte[2048]);
sock.setSoTimeout(2000);
sock.receive(packet);
// Convert the data into a string
// (And strip off the first backslash in the process)
String respStr = new String(Arrays.copyOfRange(packet.getData(), 0, packet.getLength()), StandardCharsets.UTF_8);
// Split by single backslash
// escaped once for java and once for regex
// resulting in "\\\\"
String[] fields = respStr.split("\\\\");
for(int i = 0; i < fields.length;){
if(fields[i].equals("final")){
// Final, exit here.
break;
}else if(fields[i].equals("")){
// Empty, skip.
i++;
} else {
// Valid, add to map.
gameOptions.put(fields[i], fields[i+1]);
i+=2;
}
}
sock.close();
return gameOptions;
}
private static List<HostAddr> GetHostAddrs() throws UnknownHostException, IOException, InvalidResponseException {
// Connect to GSA master server
Socket sock = null;
try {
sock = new Socket(RENLIST_SERVER, RENLIST_PORT);
} catch (UnknownHostException e) {
System.err.println("Unknown host: " + RENLIST_SERVER);
throw e;
} catch (IOException e) {
System.err.println("IOException on creating socket to: " + RENLIST_SERVER);
throw e;
}
// Try to get the host list from the GSA master server.
List<HostAddr> hostList = new ArrayList<HostAddr>();
try {
InputStream sin = sock.getInputStream();
OutputStream sout = sock.getOutputStream();
// Allocate and read in buffer for the intial "\basic\\secure\IGNORE" query
// Sent by the n00b.hk GSA master server.
byte[] respData = new byte[21];
sin.read(respData);
String query = new String(respData, StandardCharsets.UTF_8);
if(query.equals("\\basic\\\\secure\\IGNORE")){
System.out.println("Got basic query.");
// Send query to get servers.
sout.write("\\gamename\\ccrenegade\\enctype\\0\\validate\\TVJFLK6J\\final\\\\queryid\\1.1\\list\\cmp\\gamename\\ccrenegade\\where\\\\final\\".getBytes());
// Read in each host
while(true){
// Read in binary host data (int32 ip, int16 port)
byte[] hostData = new byte[6];
sin.read(hostData);
String hostDataAsString = new String(hostData, StandardCharsets.UTF_8);
// Check if it is the end of the server/host list,
// -- HACK
if(hostDataAsString.equals("\\final")){
//System.out.println("Got final query. Done reading server list.");
break;
}
// Parse bytes to ip and port,
// I don't program in Java, this may be a horrible way to do this.
// But it works :)
String ip = String.format("%d.%d.%d.%d", hostData[0]&0xff, hostData[1]&0xff, hostData[2]&0xff, hostData[3]&0xff);
int port = ((hostData[5]&0xff)|(short) ((hostData[4]&0xff)<<8))&0xffff;
hostList.add(new HostAddr(ip, port));
//System.out.printf("%s:%d\n", ip, port);
}
} else {
throw new InvalidResponseException(String.format("Server returned something that wasn't the basic query: %s\n", query));
}
sin.close();
sock.close();
} catch (IOException e) {
throw e;
}
return hostList;
}
public static void main(String[] args) {
try{
List<HostAddr> hosts = GetHostAddrs();
for(HostAddr h : hosts){
HashMap<String, String> options;
try{
options = GetHostStatus(h);
} catch(SocketTimeoutException e){
System.out.printf("GSA Serv: %s:%d timed out.\n", h.Ip, h.Port);
continue;
}
System.out.printf("%s:%s | %s | %s | %s/%s\n", h.Ip, options.get("hostport"), options.get("hostname"), options.get("mapname"), options.get("numplayers"), options.get("maxplayers"));
}
} catch(Exception e){
System.out.println(e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment