mirror of
https://github.com/Leahnaya/UBFunkeysServer.git
synced 2026-04-21 07:57:30 -05:00
Implemented u_gbl and Added ConnectionIds for each Connection
- Needs lots of testing
This commit is contained in:
parent
1dae89176d
commit
2fe09b3116
|
|
@ -3,7 +3,10 @@ package com.icedberries.UBFunkeysServer.ArkOne;
|
|||
import com.icedberries.UBFunkeysServer.ArkOne.Plugins.BasePlugin;
|
||||
import com.icedberries.UBFunkeysServer.ArkOne.Plugins.GalaxyPlugin;
|
||||
import com.icedberries.UBFunkeysServer.ArkOne.Plugins.UserPlugin;
|
||||
import com.icedberries.UBFunkeysServer.domain.User;
|
||||
import com.icedberries.UBFunkeysServer.service.UserService;
|
||||
import javagrinko.spring.tcp.Connection;
|
||||
import javagrinko.spring.tcp.Server;
|
||||
import javagrinko.spring.tcp.TcpController;
|
||||
import javagrinko.spring.tcp.TcpHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -19,6 +22,13 @@ public class ArkOneController implements TcpHandler {
|
|||
|
||||
public static final String IP_ADDRESS = "127.0.0.1";
|
||||
|
||||
// Services
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private ArkOneSender arkOneSender;
|
||||
|
||||
// Plugins
|
||||
@Autowired
|
||||
BasePlugin basePlugin;
|
||||
|
|
@ -57,13 +67,16 @@ public class ArkOneController implements TcpHandler {
|
|||
responses.add(basePlugin.GetServiceDetails(commandInfo.getAttribute("s")));
|
||||
break;
|
||||
case "a_lru":
|
||||
responses.add(basePlugin.LoginRegisteredUser(commandInfo));
|
||||
responses.add(basePlugin.LoginRegisteredUser(commandInfo, connection.getClientIdentifier()));
|
||||
break;
|
||||
|
||||
// Plugin 1 (User)
|
||||
case "u_reg":
|
||||
responses.add(userPlugin.RegisterUser(commandInfo));
|
||||
break;
|
||||
case "u_gbl":
|
||||
responses.add(userPlugin.GetBuddyList(commandInfo));
|
||||
break;
|
||||
case "p":
|
||||
responses.add(userPlugin.Ping());
|
||||
break;
|
||||
|
|
@ -113,6 +126,24 @@ public class ArkOneController implements TcpHandler {
|
|||
|
||||
@Override
|
||||
public void disconnectEvent(Connection connection) {
|
||||
// No need to log anything
|
||||
//TODO: WRITE DISCONNECT LOGIC for u_cos
|
||||
// SOME HOW STORE THE USER ID HERE SO WE CAN SET THEIR isOnline status to offline
|
||||
User user = userService.findByConnectionId(connection.getClientIdentifier()).orElse(null);
|
||||
|
||||
if (user != null) {
|
||||
// Update the online status to offline and clear the connection ID
|
||||
user.setIsOnline(0);
|
||||
user.setConnectionId(null);
|
||||
|
||||
// Update the user in the DB
|
||||
userService.save(user);
|
||||
|
||||
// Notify other users that they went offline
|
||||
try {
|
||||
arkOneSender.SendStatusUpdate("u_cos", "o", "0", user.getUUID());
|
||||
} catch(Exception e) {
|
||||
// Do nothing since the client is disconnecting anyway
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.icedberries.UBFunkeysServer.ArkOne;
|
||||
|
||||
import com.icedberries.UBFunkeysServer.domain.User;
|
||||
import com.icedberries.UBFunkeysServer.service.UserService;
|
||||
import javagrinko.spring.tcp.Connection;
|
||||
import javagrinko.spring.tcp.Server;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class ArkOneSender {
|
||||
|
||||
@Autowired
|
||||
Server server;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
public void SendStatusUpdate(String statusHeader, String shortHeader, String status, Integer userUUID)
|
||||
throws ParserConfigurationException, TransformerException {
|
||||
ArrayList<String> buddyList = new ArrayList<>(Arrays.asList(userService.getBuddyList(userUUID).split(",")));
|
||||
|
||||
for (String buddy : buddyList) {
|
||||
if (!buddy.equals("")) {
|
||||
int isOnline = 0;
|
||||
UUID connectionId = null;
|
||||
|
||||
User buddyUser = userService.findByUUID(Integer.valueOf(buddy)).orElse(null);
|
||||
|
||||
if (buddyUser != null) {
|
||||
isOnline = buddyUser.getIsOnline();
|
||||
if (isOnline == 1) {
|
||||
connectionId = buddyUser.getConnectionId();
|
||||
|
||||
// Build announcement
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
Document doc = dBuilder.newDocument();
|
||||
Element rootElement = doc.createElement(statusHeader);
|
||||
rootElement.setAttribute(shortHeader, status);
|
||||
rootElement.setAttribute("id", String.valueOf(userUUID));
|
||||
doc.appendChild(rootElement);
|
||||
|
||||
// Send announcement to user
|
||||
SendToUser(connectionId, ArkOneParser.RemoveXMLTag(doc));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SendToUser(UUID clientId, String message) {
|
||||
Connection connection = null;
|
||||
|
||||
for (Connection conn : server.getConnections()) {
|
||||
if (conn.getClientIdentifier() == clientId) {
|
||||
connection = conn;
|
||||
}
|
||||
}
|
||||
|
||||
if (connection != null) {
|
||||
try {
|
||||
// Append a 0x00 to the end of the response
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
outputStream.write(message.getBytes());
|
||||
outputStream.write((byte)0x00);
|
||||
|
||||
connection.send(outputStream.toByteArray());
|
||||
} catch (IOException e) {
|
||||
System.out.println("[ArkOne][ERROR] Failed to send message to user [" + clientId + "]: " + message);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import javax.xml.parsers.DocumentBuilder;
|
|||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class BasePlugin {
|
||||
|
|
@ -151,7 +152,7 @@ public class BasePlugin {
|
|||
return ArkOneParser.RemoveXMLTag(doc);
|
||||
}
|
||||
|
||||
public String LoginRegisteredUser(Element element) throws ParserConfigurationException, TransformerException {
|
||||
public String LoginRegisteredUser(Element element, UUID connectionId) throws ParserConfigurationException, TransformerException {
|
||||
// Response r codes:
|
||||
// 0 - Accepted Login
|
||||
// 1 - Already exist in Terrapinia
|
||||
|
|
@ -179,6 +180,10 @@ public class BasePlugin {
|
|||
} else {
|
||||
// Login success
|
||||
uuid = String.valueOf(user.getUUID());
|
||||
|
||||
// Store the UUID for our connection to the server to the DB
|
||||
user.setConnectionId(connectionId);
|
||||
userService.save(user);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.icedberries.UBFunkeysServer.ArkOne.Plugins;
|
||||
|
||||
import com.icedberries.UBFunkeysServer.ArkOne.ArkOneParser;
|
||||
import com.icedberries.UBFunkeysServer.ArkOne.ArkOneSender;
|
||||
import com.icedberries.UBFunkeysServer.domain.User;
|
||||
import com.icedberries.UBFunkeysServer.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -13,6 +14,9 @@ import javax.xml.parsers.DocumentBuilder;
|
|||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class UserPlugin {
|
||||
|
|
@ -23,6 +27,9 @@ public class UserPlugin {
|
|||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private ArkOneSender arkOneSender;
|
||||
|
||||
public String RegisterUser(Element element) throws ParserConfigurationException, TransformerException {
|
||||
String username = element.getAttribute("l");
|
||||
String password = element.getAttribute("p");
|
||||
|
|
@ -71,6 +78,64 @@ public class UserPlugin {
|
|||
return ArkOneParser.RemoveXMLTag(doc);
|
||||
}
|
||||
|
||||
public String GetBuddyList(Element element) throws ParserConfigurationException, TransformerException {
|
||||
//TODO: VERIFY THE ATTRIBUTE NAME
|
||||
User user = userService.findByUUID(Integer.valueOf(element.getAttribute("id"))).orElse(null);
|
||||
|
||||
// Start of response
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
Document doc = dBuilder.newDocument();
|
||||
Element rootElement = doc.createElement("u_gbl");
|
||||
rootElement.setAttribute("r", "0");
|
||||
doc.appendChild(rootElement);
|
||||
|
||||
// User should never be null here but check just in case
|
||||
if (user == null) {
|
||||
return ArkOneParser.RemoveXMLTag(doc);
|
||||
}
|
||||
|
||||
ArrayList<String> buddyList = new ArrayList<>(Arrays.asList(user.getRawBuddyList().split(",")));
|
||||
|
||||
// Skip NULL or blank buddy lists
|
||||
if (buddyList.size() > 0) {
|
||||
for (String buddy : buddyList) {
|
||||
if (buddy.equals("")) { continue; }
|
||||
|
||||
Integer buddyUUID = Integer.valueOf(buddy);
|
||||
|
||||
// Get the buddy's information
|
||||
User buddyUser = userService.findByUUID(buddyUUID).orElse(null);
|
||||
|
||||
// Make sure they aren't null
|
||||
if (buddyUser == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get information off their data to build a xml tag
|
||||
Element buddyElement = doc.createElement("buddy");
|
||||
buddyElement.setAttribute("id", String.valueOf(buddyUser.getUUID()));
|
||||
buddyElement.setAttribute("n", buddyUser.getUsername());
|
||||
buddyElement.setAttribute("s", String.valueOf(buddyUser.getChatStatus()));
|
||||
buddyElement.setAttribute("o", String.valueOf(buddyUser.getIsOnline()));
|
||||
buddyElement.setAttribute("ph", String.valueOf(buddyUser.getPhoneStatus()));
|
||||
|
||||
rootElement.appendChild(buddyElement);
|
||||
}
|
||||
}
|
||||
|
||||
// The client doesn't set online status. So the server sets it when it gets all the user's buddies
|
||||
user.setIsOnline(1);
|
||||
userService.save(user);
|
||||
|
||||
if (buddyList.size() > 0) {
|
||||
arkOneSender.SendStatusUpdate("u_cos", "o",
|
||||
String.valueOf(user.getIsOnline()), user.getUUID());
|
||||
}
|
||||
|
||||
return ArkOneParser.RemoveXMLTag(doc);
|
||||
}
|
||||
|
||||
public String Ping() {
|
||||
return "<p t=\"30\" />";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import javax.persistence.Id;
|
|||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
|
|
@ -64,9 +65,6 @@ public class User {
|
|||
@Column(name = "buddyList")
|
||||
private String rawBuddyList;
|
||||
|
||||
@Transient
|
||||
private ArrayList<User> buddyList;
|
||||
|
||||
// Connection ID to send data to from other Users
|
||||
private String connectionId;
|
||||
private java.util.UUID connectionId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import org.springframework.data.repository.query.Param;
|
|||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends CrudRepository<User, Integer> {
|
||||
|
|
@ -20,4 +21,10 @@ public interface UserRepository extends CrudRepository<User, Integer> {
|
|||
|
||||
@Query("select user from User user where user.username = :username")
|
||||
Optional<User> findByUsername(@Param("username") String username);
|
||||
|
||||
@Query("select user.rawBuddyList from User user where user.UUID = :uuid")
|
||||
String getBuddyList(@Param("uuid") Integer uuid);
|
||||
|
||||
@Query("select user from User user where user.connectionId = :connectionId")
|
||||
Optional<User> findByConnectionId(@Param("connectionId") UUID connectionId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.icedberries.UBFunkeysServer.service;
|
|||
import com.icedberries.UBFunkeysServer.domain.User;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface UserService {
|
||||
|
||||
|
|
@ -15,4 +16,8 @@ public interface UserService {
|
|||
Boolean existsByUsername(String username);
|
||||
|
||||
Optional<User> findByUsername(String username);
|
||||
|
||||
String getBuddyList(Integer uuid);
|
||||
|
||||
Optional<User> findByConnectionId(UUID connectionId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor;
|
|||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
|
|
@ -39,4 +40,14 @@ public class UserServiceImpl implements UserService {
|
|||
public Optional<User> findByUsername(String username) {
|
||||
return userRepository.findByUsername(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBuddyList(Integer uuid) {
|
||||
return userRepository.getBuddyList(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> findByConnectionId(UUID connectionId) {
|
||||
return userRepository.findByConnectionId(connectionId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package javagrinko.spring.tcp;
|
|||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Connection {
|
||||
InetAddress getAddress();
|
||||
|
|
@ -10,6 +11,8 @@ public interface Connection {
|
|||
void addListener(Listener listener);
|
||||
void start();
|
||||
void close() throws IOException;
|
||||
UUID getClientIdentifier();
|
||||
void setClientIdentifier(UUID newId);
|
||||
interface Listener {
|
||||
void messageReceived(Connection connection, byte[] bytes)
|
||||
throws InvocationTargetException, IllegalAccessException;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import java.net.InetAddress;
|
|||
import java.net.Socket;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class TcpConnection implements Connection {
|
||||
|
|
@ -20,6 +21,8 @@ public class TcpConnection implements Connection {
|
|||
private Socket socket;
|
||||
private List<Listener> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
private UUID clientIdentifier = null;
|
||||
|
||||
TcpConnection(Socket socket) {
|
||||
this.socket = socket;
|
||||
try {
|
||||
|
|
@ -93,4 +96,14 @@ public class TcpConnection implements Connection {
|
|||
public void close() throws IOException {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getClientIdentifier() {
|
||||
return clientIdentifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientIdentifier(UUID newId) {
|
||||
this.clientIdentifier = newId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@Component
|
||||
|
|
@ -89,6 +90,10 @@ public class TcpServer implements Server, Connection.Listener {
|
|||
throws InvocationTargetException, IllegalAccessException {
|
||||
logger.info("New connection! Ip: " + connection.getAddress().getCanonicalHostName() + ".");
|
||||
connections.add(connection);
|
||||
|
||||
// Generate a UUID for this connection
|
||||
connection.setClientIdentifier(UUID.randomUUID());
|
||||
|
||||
logger.info("Current connections count: " + connections.size());
|
||||
for (Connection.Listener listener : listeners) {
|
||||
listener.connected(connection);
|
||||
|
|
@ -100,6 +105,10 @@ public class TcpServer implements Server, Connection.Listener {
|
|||
throws InvocationTargetException, IllegalAccessException {
|
||||
logger.info("Disconnect! Ip: " + connection.getAddress().getCanonicalHostName() + ".");
|
||||
connections.remove(connection);
|
||||
|
||||
// Remove the UUID
|
||||
connection.setClientIdentifier(null);
|
||||
|
||||
logger.info("Current connections count: " + connections.size());
|
||||
for (Connection.Listener listener : listeners) {
|
||||
listener.disconnected(connection);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user