mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
Implemented server to manage a list of available servers on the internet.
- Implemented a server manager that keeps track of servers & room codes, and removes old servers - Implemented queries to find a server with a specific room code - Implemented protocol to register servers #story[1281]
This commit is contained in:
@@ -10,11 +10,13 @@ import org.apache.commons.cli.Options;
|
|||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import seng302.serverRepository.ServerRepository;
|
||||||
import seng302.visualiser.controllers.ViewManager;
|
import seng302.visualiser.controllers.ViewManager;
|
||||||
|
|
||||||
public class App extends Application {
|
public class App extends Application {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(App.class);
|
private static Logger logger = LoggerFactory.getLogger(App.class);
|
||||||
|
private static boolean isRunningAsCache = false;
|
||||||
|
|
||||||
public static void parseArgs(String[] args) throws ParseException {
|
public static void parseArgs(String[] args) throws ParseException {
|
||||||
Options options = new Options();
|
Options options = new Options();
|
||||||
@@ -25,9 +27,14 @@ public class App extends Application {
|
|||||||
.getLogger(Logger.ROOT_LOGGER_NAME);
|
.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||||
|
|
||||||
options.addOption("debugLevel", true, "Set the application debug level");
|
options.addOption("debugLevel", true, "Set the application debug level");
|
||||||
|
options.addOption("runAsCache", false, "Run as a server cache for server discovery");
|
||||||
|
|
||||||
cmd = parser.parse(options, args);
|
cmd = parser.parse(options, args);
|
||||||
|
|
||||||
|
if (cmd.hasOption("runAsCache")){
|
||||||
|
isRunningAsCache = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd.hasOption("debugLevel")) {
|
if (cmd.hasOption("debugLevel")) {
|
||||||
|
|
||||||
switch (cmd.getOptionValue("debugLevel")) {
|
switch (cmd.getOptionValue("debugLevel")) {
|
||||||
@@ -67,14 +74,19 @@ public class App extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) throws Exception {
|
||||||
try {
|
try {
|
||||||
parseArgs(args);
|
parseArgs(args);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
logger.error("Could not parse command line arguments");
|
logger.error("Could not parse command line arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
launch(args);
|
if (!isRunningAsCache){
|
||||||
|
launch(args);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ServerRepository serverRepository = new ServerRepository();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package seng302.gameServer;
|
package seng302.gameServer;
|
||||||
|
|
||||||
|
import com.sun.org.apache.xpath.internal.operations.Bool;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.jmdns.JmDNS;
|
import javax.jmdns.JmDNS;
|
||||||
import javax.jmdns.ServiceInfo;
|
import javax.jmdns.ServiceInfo;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -27,7 +31,7 @@ public class ServerAdvertiser {
|
|||||||
*/
|
*/
|
||||||
private static String SERVICE = "_partyatsea";
|
private static String SERVICE = "_partyatsea";
|
||||||
private static String PROTOCOL = "_tcp";
|
private static String PROTOCOL = "_tcp";
|
||||||
public static String SERVICE_TYPE = SERVICE + "." + PROTOCOL + ".local.";
|
public static String SERVICE_TYPE = SERVICE + "." + PROTOCOL + ".homekit.bonjour.michaelrausch.nz.";
|
||||||
|
|
||||||
private static ServerAdvertiser instance = null;
|
private static ServerAdvertiser instance = null;
|
||||||
private static JmDNS jmdnsInstance = null;
|
private static JmDNS jmdnsInstance = null;
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ public class ServerDescription {
|
|||||||
private String serverName;
|
private String serverName;
|
||||||
private String mapName;
|
private String mapName;
|
||||||
private Integer numPlayers;
|
private Integer numPlayers;
|
||||||
|
private Long lastUpdated;
|
||||||
|
private Long lastRefreshed;
|
||||||
|
|
||||||
|
private static Long EXPIRY_INTERVAL = 5000L;
|
||||||
|
|
||||||
public ServerDescription(String serverName, String mapName, Integer numPlayers, Integer capacity, String address, Integer portNum){
|
public ServerDescription(String serverName, String mapName, Integer numPlayers, Integer capacity, String address, Integer portNum){
|
||||||
this.serverName = serverName;
|
this.serverName = serverName;
|
||||||
@@ -15,6 +19,7 @@ public class ServerDescription {
|
|||||||
this.address = address;
|
this.address = address;
|
||||||
this.portNum = portNum;
|
this.portNum = portNum;
|
||||||
this.capacity = capacity;
|
this.capacity = capacity;
|
||||||
|
lastUpdated = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,4 +85,20 @@ public class ServerDescription {
|
|||||||
return this.getName().hashCode() + this.getAddress().hashCode() +
|
return this.getName().hashCode() + this.getAddress().hashCode() +
|
||||||
this.portNumber().hashCode() + this.getMapName().hashCode();
|
this.portNumber().hashCode() + this.getMapName().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean hasExpired(){
|
||||||
|
return System.currentTimeMillis() - lastUpdated > EXPIRY_INTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean serverShouldBeRemoved() {
|
||||||
|
if (lastRefreshed == null) return false;
|
||||||
|
|
||||||
|
System.out.println("SBR" + (System.currentTimeMillis() - lastRefreshed > EXPIRY_INTERVAL));
|
||||||
|
return System.currentTimeMillis() - lastRefreshed > EXPIRY_INTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hasBeenRefreshed(){
|
||||||
|
System.out.println("Was refreshed");
|
||||||
|
lastRefreshed = System.currentTimeMillis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ public enum MessageType {
|
|||||||
REGISTRATION_REQUEST(101),
|
REGISTRATION_REQUEST(101),
|
||||||
REGISTRATION_RESPONSE(102),
|
REGISTRATION_RESPONSE(102),
|
||||||
CUSTOMIZATION_REQUEST(103),
|
CUSTOMIZATION_REQUEST(103),
|
||||||
CUSTOMIZATION_RESPONSE(104);
|
CUSTOMIZATION_RESPONSE(104),
|
||||||
|
REPO_REGISTRATION_REQUEST(201),
|
||||||
|
ROOM_CODE_REQUEST(202),
|
||||||
|
LOBBY_REQUEST(203);
|
||||||
|
|
||||||
|
|
||||||
private int code;
|
private int code;
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package seng302.gameServer.messages;
|
||||||
|
|
||||||
|
public class RoomCodeRequest extends Message{
|
||||||
|
private int size = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoomCodeRequest(String roomCode){
|
||||||
|
size = roomCode.length() + 6;
|
||||||
|
|
||||||
|
setHeader(new Header(MessageType.ROOM_CODE_REQUEST, 0x01, (short)getSize()));
|
||||||
|
allocateBuffer();
|
||||||
|
writeHeaderToBuffer();
|
||||||
|
|
||||||
|
putInt(roomCode.length(), 6);
|
||||||
|
putBytes(roomCode.getBytes());
|
||||||
|
|
||||||
|
writeCRC();
|
||||||
|
rewind();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package seng302.gameServer.messages;
|
||||||
|
|
||||||
|
public class ServerRegistrationMessage extends Message {
|
||||||
|
private int size;
|
||||||
|
@Override
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerRegistrationMessage(String serverName, String mapName, String address, int port, int players, int capacity, String roomCode){
|
||||||
|
size = serverName.getBytes().length + mapName.length() + address.length() + roomCode.length() + 36;
|
||||||
|
|
||||||
|
setHeader(new Header(MessageType.REPO_REGISTRATION_REQUEST, 0x01, (short) getSize()));
|
||||||
|
allocateBuffer();
|
||||||
|
writeHeaderToBuffer();
|
||||||
|
|
||||||
|
int nameLength = serverName.length();
|
||||||
|
int mapNameLength = mapName.length();
|
||||||
|
int addressLength = address.length();
|
||||||
|
int roomCodeLength = roomCode.length();
|
||||||
|
|
||||||
|
// Put fields here
|
||||||
|
putInt(nameLength, 6);
|
||||||
|
putInt(mapNameLength, 6);
|
||||||
|
putInt(addressLength, 6);
|
||||||
|
putInt(roomCodeLength, 6);
|
||||||
|
|
||||||
|
putInt(port, 4);
|
||||||
|
putInt(players, 4);
|
||||||
|
putInt(capacity, 4);
|
||||||
|
|
||||||
|
putBytes(serverName.getBytes());
|
||||||
|
putBytes(mapName.getBytes());
|
||||||
|
putBytes(address.getBytes());
|
||||||
|
putBytes(roomCode.getBytes());
|
||||||
|
|
||||||
|
writeCRC();
|
||||||
|
rewind();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,9 @@ public enum PacketType {
|
|||||||
RACE_REGISTRATION_REQUEST,
|
RACE_REGISTRATION_REQUEST,
|
||||||
RACE_REGISTRATION_RESPONSE,
|
RACE_REGISTRATION_RESPONSE,
|
||||||
RACE_CUSTOMIZATION_REQUEST,
|
RACE_CUSTOMIZATION_REQUEST,
|
||||||
RACE_CUSTOMIZATION_RESPONSE;
|
RACE_CUSTOMIZATION_RESPONSE,
|
||||||
|
|
||||||
|
SERVER_REGISTRATION, ROOM_CODE_REQUEST, LOBBY_REQUEST;
|
||||||
|
|
||||||
public static PacketType assignPacketType(int packetType, byte[] payload){
|
public static PacketType assignPacketType(int packetType, byte[] payload){
|
||||||
switch(packetType){
|
switch(packetType){
|
||||||
@@ -65,6 +67,10 @@ public enum PacketType {
|
|||||||
return RACE_CUSTOMIZATION_REQUEST;
|
return RACE_CUSTOMIZATION_REQUEST;
|
||||||
case 104:
|
case 104:
|
||||||
return RACE_CUSTOMIZATION_RESPONSE;
|
return RACE_CUSTOMIZATION_RESPONSE;
|
||||||
|
case 201:
|
||||||
|
return SERVER_REGISTRATION;
|
||||||
|
case 202:
|
||||||
|
return ROOM_CODE_REQUEST;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
return OTHER;
|
return OTHER;
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package seng302.serverRepository;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class ReadableByteInputStream {
|
||||||
|
private InputStream is;
|
||||||
|
|
||||||
|
public ReadableByteInputStream(InputStream is){
|
||||||
|
this.is = is;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getBytes(int n) throws Exception {
|
||||||
|
byte[] bytes = new byte[n];
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
bytes[i] = (byte) readByte();
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void skipBytes(long n) throws Exception {
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
readByte();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readByte() throws Exception {
|
||||||
|
int currentByte = is.read();
|
||||||
|
|
||||||
|
if (currentByte == -1) {
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
return currentByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package seng302.serverRepository;
|
||||||
|
|
||||||
|
public class ServerListing {
|
||||||
|
private static final int SERVER_TTL_DEFAULT = 10;
|
||||||
|
|
||||||
|
private String serverName = "";
|
||||||
|
private String mapName = "";
|
||||||
|
private String address = "";
|
||||||
|
private int portNumber = 0;
|
||||||
|
private int capacity = 0;
|
||||||
|
private int players = 0;
|
||||||
|
private String roomCode = "";
|
||||||
|
private int ttl = SERVER_TTL_DEFAULT;
|
||||||
|
|
||||||
|
|
||||||
|
public ServerListing(String serverName, String mapName, String address, int portNumber, int capacity){
|
||||||
|
this.serverName = serverName;
|
||||||
|
this.mapName = mapName;
|
||||||
|
this.address = address;
|
||||||
|
this.portNumber = portNumber;
|
||||||
|
this.capacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerListing setNumberOfPlayers(int players){
|
||||||
|
this.players = players;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerListing setRoomCode(String roomCode){
|
||||||
|
this.roomCode = roomCode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshTtl(){
|
||||||
|
ttl = SERVER_TTL_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decrementTtl(){
|
||||||
|
ttl--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasTtlExpired(){
|
||||||
|
return ttl < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ServerListing.class.isAssignableFrom(obj.getClass())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ServerListing other = (ServerListing) obj;
|
||||||
|
|
||||||
|
if (this.getPortNumber() != other.getPortNumber()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.getMapName().equals(other.getMapName())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.getServerName().equals(other.getServerName())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getCapacity() != other.getCapacity()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.getAddress().equals(other.getAddress())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.getServerName().hashCode() +
|
||||||
|
this.getAddress().hashCode() + this.getMapName().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRoomCode() {
|
||||||
|
return roomCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPortNumber() {
|
||||||
|
return portNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMapName() {
|
||||||
|
return mapName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServerName() {
|
||||||
|
return serverName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCapacity() {
|
||||||
|
return capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package seng302.serverRepository;
|
||||||
|
|
||||||
|
|
||||||
|
import seng302.gameServer.messages.Message;
|
||||||
|
import seng302.model.stream.packets.PacketType;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class ServerRepoStreamParser {
|
||||||
|
private ReadableByteInputStream inputStream;
|
||||||
|
|
||||||
|
private String roomCode;
|
||||||
|
private String mapName;
|
||||||
|
private ServerListing serverListing;
|
||||||
|
|
||||||
|
public ServerRepoStreamParser(InputStream is){
|
||||||
|
inputStream = new ReadableByteInputStream(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketType parse() throws Exception {
|
||||||
|
int sync1 = inputStream.readByte();
|
||||||
|
int sync2 = inputStream.readByte();
|
||||||
|
|
||||||
|
PacketType packetType = null;
|
||||||
|
|
||||||
|
if (sync1 == 0x47 && sync2 == 0x83) {
|
||||||
|
int type = inputStream.readByte();
|
||||||
|
inputStream.skipBytes(10);
|
||||||
|
long payloadLength = Message.bytesToLong(inputStream.getBytes(2));
|
||||||
|
byte[] payload = inputStream.getBytes((int) payloadLength);
|
||||||
|
inputStream.skipBytes(4);
|
||||||
|
|
||||||
|
packetType = PacketType.assignPacketType(type, payload);
|
||||||
|
|
||||||
|
switch (packetType) {
|
||||||
|
case ROOM_CODE_REQUEST:
|
||||||
|
roomCode = parseRoomCodeRequest(payload);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOBBY_REQUEST:
|
||||||
|
mapName = parseLobbyRequest(payload);
|
||||||
|
|
||||||
|
case SERVER_REGISTRATION:
|
||||||
|
serverListing = parseServerRegistration(payload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return packetType;
|
||||||
|
}
|
||||||
|
private String parseLobbyRequest(byte[] payload) {
|
||||||
|
int mapNameLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 0 ,4));
|
||||||
|
|
||||||
|
return new String(Arrays.copyOfRange(payload, 4, 4+mapNameLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseRoomCodeRequest(byte[] payload) {
|
||||||
|
int roomCodeLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 0 ,4));
|
||||||
|
|
||||||
|
return new String(Arrays.copyOfRange(payload, 4, 4+roomCodeLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerListing parseServerRegistration(byte[] payload) {
|
||||||
|
int nameLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 0, 6));
|
||||||
|
int mapNameLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 6, 12));
|
||||||
|
int addressLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 12, 18));
|
||||||
|
int roomCodeLength = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 18, 24));
|
||||||
|
|
||||||
|
int portNumber = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 24, 28));
|
||||||
|
int players = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 28, 32));
|
||||||
|
int capacity = (int) Message.bytesToLong(Arrays.copyOfRange(payload, 32, 36));
|
||||||
|
|
||||||
|
int currentPos = 36;
|
||||||
|
int nextPos = currentPos + nameLength;
|
||||||
|
String serverName = new String(Arrays.copyOfRange(payload, currentPos, nextPos));
|
||||||
|
|
||||||
|
currentPos = nextPos;
|
||||||
|
nextPos = currentPos + mapNameLength;
|
||||||
|
String mapName = new String(Arrays.copyOfRange(payload, currentPos, nextPos));
|
||||||
|
|
||||||
|
currentPos = nextPos;
|
||||||
|
nextPos = currentPos + addressLength;
|
||||||
|
String address = new String(Arrays.copyOfRange(payload, currentPos, nextPos));
|
||||||
|
|
||||||
|
currentPos = nextPos;
|
||||||
|
nextPos = currentPos + roomCodeLength;
|
||||||
|
String roomCode = new String(Arrays.copyOfRange(payload, currentPos, nextPos));
|
||||||
|
|
||||||
|
ServerListing serverListing = new ServerListing(serverName, mapName, address, portNumber, capacity);
|
||||||
|
serverListing.setNumberOfPlayers(players);
|
||||||
|
serverListing.setRoomCode(roomCode);
|
||||||
|
|
||||||
|
return serverListing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRoomCode() {
|
||||||
|
return roomCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMapName() {
|
||||||
|
return mapName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerListing getServerListing() {
|
||||||
|
return serverListing;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package seng302.serverRepository;
|
||||||
|
|
||||||
|
import seng302.gameServer.messages.Message;
|
||||||
|
import seng302.gameServer.messages.RoomCodeRequest;
|
||||||
|
import seng302.gameServer.messages.ServerRegistrationMessage;
|
||||||
|
import seng302.model.stream.packets.PacketType;
|
||||||
|
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
public class ServerRepository {
|
||||||
|
private ServerTable serverTable;
|
||||||
|
|
||||||
|
public ServerRepository() throws Exception {
|
||||||
|
System.out.println(" -- Starting Server Repository -- ");
|
||||||
|
serverTable = new ServerTable();
|
||||||
|
|
||||||
|
ServerSocket serverSocket = new ServerSocket(9999);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO Remove later, this is for testing
|
||||||
|
new Timer().schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
new ServerRepositoryClient();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
while (true){
|
||||||
|
Socket clientSocket = serverSocket.accept();
|
||||||
|
|
||||||
|
parseRequest(clientSocket);
|
||||||
|
|
||||||
|
clientSocket.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void parseRequest(Socket clientSocket) throws Exception {
|
||||||
|
ServerRepoStreamParser parser = new ServerRepoStreamParser(clientSocket.getInputStream());
|
||||||
|
|
||||||
|
if (clientSocket.isConnected() && !clientSocket.isClosed()){
|
||||||
|
PacketType parsePacketResult = parser.parse();
|
||||||
|
|
||||||
|
switch (parsePacketResult){
|
||||||
|
case SERVER_REGISTRATION:
|
||||||
|
ServerListing listing = parser.getServerListing();
|
||||||
|
|
||||||
|
if (!serverTable.getAllServers().contains(listing)){
|
||||||
|
listing.setRoomCode(serverTable.getNextRoomCode().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
serverTable.addServer(listing);
|
||||||
|
|
||||||
|
Message serverRegMessage = new RoomCodeRequest(listing.getRoomCode());
|
||||||
|
clientSocket.getOutputStream().write(serverRegMessage.getBuffer());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ROOM_CODE_REQUEST:
|
||||||
|
String desiredRoomCode = parser.getRoomCode();
|
||||||
|
|
||||||
|
ServerListing serverListing = serverTable.getServerByRoomCode(desiredRoomCode);
|
||||||
|
Message response;
|
||||||
|
|
||||||
|
if (serverListing != null){
|
||||||
|
response = new ServerRegistrationMessage(serverListing.getServerName(), serverListing.getMapName(), serverListing.getAddress(), serverListing.getPortNumber(), 0, 0, desiredRoomCode);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
response = new ServerRegistrationMessage("", "", "", 0, 0, 0, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
clientSocket.getOutputStream().write(response.getBuffer());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package seng302.serverRepository;
|
||||||
|
|
||||||
|
import com.sun.xml.internal.ws.api.message.Packet;
|
||||||
|
import seng302.gameServer.messages.Message;
|
||||||
|
import seng302.gameServer.messages.ServerRegistrationMessage;
|
||||||
|
import seng302.model.stream.packets.PacketType;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
public class ServerRepositoryClient {
|
||||||
|
|
||||||
|
private String roomCode = "0";
|
||||||
|
|
||||||
|
public ServerRepositoryClient() throws Exception {
|
||||||
|
new Timer().schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
sendUpdate();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 0, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendUpdate() throws Exception {
|
||||||
|
Socket socket = new Socket("localhost", 9999);
|
||||||
|
ServerRepoStreamParser parser = new ServerRepoStreamParser(socket.getInputStream());
|
||||||
|
Message req = new ServerRegistrationMessage("asdf", "Asdf", "asdf", 6969, 1, 20, "4949");
|
||||||
|
|
||||||
|
socket.getOutputStream().write(req.getBuffer());
|
||||||
|
|
||||||
|
PacketType packetType = parser.parse();
|
||||||
|
|
||||||
|
if (packetType != PacketType.ROOM_CODE_REQUEST){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String roomCode = parser.getRoomCode();
|
||||||
|
|
||||||
|
if (roomCode.equals("0")){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.roomCode = roomCode;
|
||||||
|
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package seng302.serverRepository;
|
||||||
|
|
||||||
|
import com.sun.corba.se.spi.activation.Server;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class ServerTable {
|
||||||
|
private List<ServerListing> servers;
|
||||||
|
private int lastRoomCode = 4020;
|
||||||
|
|
||||||
|
public ServerTable(){
|
||||||
|
servers = new ArrayList<>();
|
||||||
|
|
||||||
|
new Timer().schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateServers();
|
||||||
|
}
|
||||||
|
}, 0, 1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateServers() {
|
||||||
|
List<ServerListing> serversToRemove = new ArrayList<>();
|
||||||
|
|
||||||
|
for (ServerListing server : servers){
|
||||||
|
server.decrementTtl();
|
||||||
|
|
||||||
|
if (server.hasTtlExpired()){
|
||||||
|
serversToRemove.add(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ServerListing server : serversToRemove){
|
||||||
|
System.out.println("Removing " + server.getServerName());
|
||||||
|
servers.remove(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addServer(ServerListing server){
|
||||||
|
if (servers.contains(server)){
|
||||||
|
updateTtlForServer(server);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
servers.add(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTtlForServer(ServerListing server) {
|
||||||
|
for (ServerListing serverListing : servers){
|
||||||
|
if (server.equals(serverListing)){
|
||||||
|
System.out.println("Refreshing TTL For " + server.getServerName());
|
||||||
|
serverListing.refreshTtl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ServerListing> getAllServers(){
|
||||||
|
return Collections.unmodifiableList(servers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerListing getServerByRoomCode(String roomCode){
|
||||||
|
for (ServerListing serverListing : servers){
|
||||||
|
if (serverListing.getRoomCode().equals(roomCode)){
|
||||||
|
return serverListing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getNextRoomCode(){
|
||||||
|
System.out.println(lastRoomCode);
|
||||||
|
lastRoomCode += 1;
|
||||||
|
return lastRoomCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,11 +6,10 @@ import seng302.gameServer.ServerDescription;
|
|||||||
import javax.jmdns.JmDNS;
|
import javax.jmdns.JmDNS;
|
||||||
import javax.jmdns.ServiceEvent;
|
import javax.jmdns.ServiceEvent;
|
||||||
import javax.jmdns.ServiceListener;
|
import javax.jmdns.ServiceListener;
|
||||||
|
import javax.jmdns.impl.JmDNSImpl;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
||||||
|
|
||||||
@@ -18,6 +17,7 @@ import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
|||||||
* Listens for servers on the local network
|
* Listens for servers on the local network
|
||||||
*/
|
*/
|
||||||
public class ServerListener{
|
public class ServerListener{
|
||||||
|
private static Integer SERVICE_REFRESH_INTERVAL = 5 * 1000;
|
||||||
private static ServerListener instance;
|
private static ServerListener instance;
|
||||||
private ServerListenerDelegate delegate;
|
private ServerListenerDelegate delegate;
|
||||||
private JmDNS jmdns = null;
|
private JmDNS jmdns = null;
|
||||||
@@ -91,8 +91,16 @@ public class ServerListener{
|
|||||||
|
|
||||||
private ServerListener() throws IOException {
|
private ServerListener() throws IOException {
|
||||||
jmdns = JmDNS.create(InetAddress.getByName(getLocalHostIp()));
|
jmdns = JmDNS.create(InetAddress.getByName(getLocalHostIp()));
|
||||||
|
|
||||||
listener = new GameServeMonitor();
|
listener = new GameServeMonitor();
|
||||||
jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, listener);
|
jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, listener);
|
||||||
|
|
||||||
|
/*new Timer().schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}, 50, SERVICE_REFRESH_INTERVAL);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ServerListener getInstance() throws IOException {
|
public static ServerListener getInstance() throws IOException {
|
||||||
@@ -110,4 +118,25 @@ public class ServerListener{
|
|||||||
public void setDelegate(ServerListenerDelegate delegate){
|
public void setDelegate(ServerListenerDelegate delegate){
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refresh(){
|
||||||
|
ArrayList<ServerDescription> servers = new ArrayList<>(listener.servers);
|
||||||
|
|
||||||
|
for (ServerDescription serverDescription : servers){
|
||||||
|
if (serverDescription.hasExpired()){
|
||||||
|
jmdns.requestServiceInfo(ServerAdvertiser.SERVICE_TYPE, serverDescription.getName());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
serverDescription.hasBeenRefreshed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ServerDescription server : servers){
|
||||||
|
if (server.serverShouldBeRemoved()){
|
||||||
|
listener.servers.remove(server);
|
||||||
|
delegate.serverRemoved(new ArrayList<ServerDescription>(listener.servers));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user