Merge branch 'feature/netty-protocol' into dev

This commit is contained in:
Gravit 2019-01-29 22:32:27 +07:00
commit 748b9ac4e7
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
29 changed files with 634 additions and 90 deletions

View file

@ -9,6 +9,8 @@
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import ru.gravit.launcher.hasher.HashedEntry; import ru.gravit.launcher.hasher.HashedEntry;
import ru.gravit.launcher.hasher.HashedEntryAdapter; import ru.gravit.launcher.hasher.HashedEntryAdapter;
import ru.gravit.launcher.request.JsonResultSerializeAdapter;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.json.EchoResponse; import ru.gravit.launchserver.socket.websocket.json.EchoResponse;
@ -17,6 +19,7 @@
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse; import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
import ru.gravit.launchserver.socket.websocket.json.auth.CheckServerResponse; import ru.gravit.launchserver.socket.websocket.json.auth.CheckServerResponse;
import ru.gravit.launchserver.socket.websocket.json.auth.JoinServerResponse; import ru.gravit.launchserver.socket.websocket.json.auth.JoinServerResponse;
import ru.gravit.launchserver.socket.websocket.json.auth.ProfilesResponse;
import ru.gravit.launchserver.socket.websocket.json.update.LauncherResponse; import ru.gravit.launchserver.socket.websocket.json.update.LauncherResponse;
import ru.gravit.launchserver.socket.websocket.json.update.UpdateListResponse; import ru.gravit.launchserver.socket.websocket.json.update.UpdateListResponse;
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
@ -32,6 +35,7 @@ public WebSocketService(ChannelGroup channels, LaunchServer server, GsonBuilder
this.server = server; this.server = server;
this.gsonBuiler = gson; this.gsonBuiler = gson;
this.gsonBuiler.registerTypeAdapter(JsonResponseInterface.class, new JsonResponseAdapter(this)); this.gsonBuiler.registerTypeAdapter(JsonResponseInterface.class, new JsonResponseAdapter(this));
this.gsonBuiler.registerTypeAdapter(ResultInterface.class,new JsonResultSerializeAdapter());
this.gsonBuiler.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter()); this.gsonBuiler.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter());
this.gson = gsonBuiler.create(); this.gson = gsonBuiler.create();
} }
@ -69,6 +73,7 @@ public void registerResponses() {
registerResponse("auth", AuthResponse.class); registerResponse("auth", AuthResponse.class);
registerResponse("checkServer", CheckServerResponse.class); registerResponse("checkServer", CheckServerResponse.class);
registerResponse("joinServer", JoinServerResponse.class); registerResponse("joinServer", JoinServerResponse.class);
registerResponse("profiles", ProfilesResponse.class);
registerResponse("launcherUpdate", LauncherResponse.class); registerResponse("launcherUpdate", LauncherResponse.class);
registerResponse("updateList", UpdateListResponse.class); registerResponse("updateList", UpdateListResponse.class);
registerResponse("cmdExec", UpdateListResponse.class); registerResponse("cmdExec", UpdateListResponse.class);

View file

@ -1,13 +1,15 @@
package ru.gravit.launchserver.socket.websocket.json.auth; package ru.gravit.launchserver.socket.websocket.json.auth;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.HWID; import ru.gravit.launcher.OshiHWID;
import ru.gravit.launcher.events.request.AuthRequestEvent;
import ru.gravit.launcher.profiles.ClientProfile; import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException; import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.auth.hwid.HWIDException; import ru.gravit.launchserver.auth.hwid.HWIDException;
import ru.gravit.launchserver.auth.provider.AuthProvider; import ru.gravit.launchserver.auth.provider.AuthProvider;
import ru.gravit.launchserver.auth.provider.AuthProviderResult; import ru.gravit.launchserver.auth.provider.AuthProviderResult;
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService; import ru.gravit.launchserver.socket.websocket.WebSocketService;
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface; import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
@ -15,6 +17,7 @@
import ru.gravit.utils.helper.VerifyHelper; import ru.gravit.utils.helper.VerifyHelper;
import java.util.Collection; import java.util.Collection;
import java.util.UUID;
public class AuthResponse implements JsonResponseInterface { public class AuthResponse implements JsonResponseInterface {
public String login; public String login;
@ -22,7 +25,7 @@ public class AuthResponse implements JsonResponseInterface {
public String password; public String password;
public AuthResponse(String login, String password, int authid, HWID hwid) { public AuthResponse(String login, String password, int authid, OshiHWID hwid) {
this.login = login; this.login = login;
this.password = password; this.password = password;
this.authid = authid; this.authid = authid;
@ -30,7 +33,12 @@ public AuthResponse(String login, String password, int authid, HWID hwid) {
} }
public int authid; public int authid;
public HWID hwid; public ConnectTypes authType;
public OshiHWID hwid;
public enum ConnectTypes
{
SERVER,CLIENT,BOT
}
@Override @Override
public String getType() { public String getType() {
@ -40,19 +48,31 @@ public String getType() {
@Override @Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client clientData) throws Exception { public void execute(WebSocketService service, ChannelHandlerContext ctx, Client clientData) throws Exception {
try { try {
AuthRequestEvent result = new AuthRequestEvent();
String ip = IOHelper.getIP(ctx.channel().remoteAddress()); String ip = IOHelper.getIP(ctx.channel().remoteAddress());
if (LaunchServer.server.limiter.isLimit(ip)) { if (LaunchServer.server.limiter.isLimit(ip)) {
AuthProvider.authError(LaunchServer.server.config.authRejectString); AuthProvider.authError(LaunchServer.server.config.authRejectString);
return; return;
} }
if (!clientData.checkSign) { if (authType != ConnectTypes.CLIENT &&!clientData.checkSign) {
AuthProvider.authError("Don't skip Launcher Update"); AuthProvider.authError("Don't skip Launcher Update");
return; return;
} }
clientData.permissions = LaunchServer.server.config.permissionsHandler.getPermissions(login);
if(authType == ConnectTypes.BOT && !clientData.permissions.canBot)
{
AuthProvider.authError("authType: BOT not allowed for this account");
}
if(authType == ConnectTypes.SERVER && !clientData.permissions.canServer)
{
AuthProvider.authError("authType: SERVER not allowed for this account");
}
ru.gravit.launchserver.response.auth.AuthResponse.AuthContext context = new ru.gravit.launchserver.response.auth.AuthResponse.AuthContext(0, login, password.length(), client, null, false);
AuthProvider provider = LaunchServer.server.config.authProvider[authid]; AuthProvider provider = LaunchServer.server.config.authProvider[authid];
AuthProviderResult result = provider.auth(login, password, ip); LaunchServer.server.authHookManager.preHook(context, clientData);
if (!VerifyHelper.isValidUsername(result.username)) { AuthProviderResult aresult = provider.auth(login, password, ip);
AuthProvider.authError(String.format("Illegal result: '%s'", result.username)); if (!VerifyHelper.isValidUsername(aresult.username)) {
AuthProvider.authError(String.format("Illegal result: '%s'", aresult.username));
return; return;
} }
Collection<ClientProfile> profiles = LaunchServer.server.getProfiles(); Collection<ClientProfile> profiles = LaunchServer.server.getProfiles();
@ -67,19 +87,19 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
if (clientData.profile == null) { if (clientData.profile == null) {
throw new AuthException("You profile not found"); throw new AuthException("You profile not found");
} }
LaunchServer.server.config.hwidHandler.check(hwid, result.username); UUID uuid = LaunchServer.server.config.authHandler.auth(aresult);
if(authType == ConnectTypes.CLIENT)
LaunchServer.server.config.hwidHandler.check(hwid, aresult.username);
LaunchServer.server.authHookManager.postHook(context, clientData);
clientData.isAuth = true; clientData.isAuth = true;
clientData.permissions = result.permissions; clientData.permissions = aresult.permissions;
service.sendObject(ctx, new WebSocketService.SuccessResult("auth")); result.accessToken = aresult.accessToken;
result.permissions = clientData.permissions;
result.playerProfile = ProfileByUUIDResponse.getProfile(LaunchServer.server,uuid,aresult.username,client);
service.sendObject(ctx, result);
} catch (AuthException | HWIDException e) { } catch (AuthException | HWIDException e) {
service.sendObject(ctx, new WebSocketService.ErrorResult(e.getMessage())); service.sendObject(ctx, new WebSocketService.ErrorResult(e.getMessage()));
} }
} }
public class Result {
public Result() {
}
public String error;
}
} }

View file

@ -1,8 +1,10 @@
package ru.gravit.launchserver.socket.websocket.json.auth; package ru.gravit.launchserver.socket.websocket.json.auth;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.events.request.CheckServerEvent;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException; import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService; import ru.gravit.launchserver.socket.websocket.WebSocketService;
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface; import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
@ -11,6 +13,7 @@
public class CheckServerResponse implements JsonResponseInterface { public class CheckServerResponse implements JsonResponseInterface {
public String serverID; public String serverID;
public String username; public String username;
public String client;
@Override @Override
public String getType() { public String getType() {
@ -18,9 +21,12 @@ public String getType() {
} }
@Override @Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) { public void execute(WebSocketService service, ChannelHandlerContext ctx, Client pClient) {
CheckServerEvent result = new CheckServerEvent();
try { try {
LaunchServer.server.config.authHandler.checkServer(username, serverID); result.uuid = LaunchServer.server.config.authHandler.checkServer(username, serverID);
if(result.uuid != null)
result.playerProfile = ProfileByUUIDResponse.getProfile(LaunchServer.server,result.uuid,username,client);
} catch (AuthException e) { } catch (AuthException e) {
service.sendObject(ctx, new WebSocketService.ErrorResult(e.getMessage())); service.sendObject(ctx, new WebSocketService.ErrorResult(e.getMessage()));
return; return;
@ -29,11 +35,7 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
service.sendObject(ctx, new WebSocketService.ErrorResult("Internal authHandler error")); service.sendObject(ctx, new WebSocketService.ErrorResult("Internal authHandler error"));
return; return;
} }
service.sendObject(ctx, new Result()); service.sendObject(ctx, new CheckServerEvent());
} }
public class Result {
public String type = "success";
public String requesttype = "checkServer";
}
} }

View file

@ -1,6 +1,7 @@
package ru.gravit.launchserver.socket.websocket.json.auth; package ru.gravit.launchserver.socket.websocket.json.auth;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.events.request.JoinServerRequestEvent;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException; import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
@ -31,17 +32,7 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
service.sendObject(ctx, new WebSocketService.ErrorResult("Internal authHandler error")); service.sendObject(ctx, new WebSocketService.ErrorResult("Internal authHandler error"));
return; return;
} }
service.sendObject(ctx, new Result(success)); service.sendObject(ctx, new JoinServerRequestEvent(success));
} }
public class Result {
public String type = "success";
public String requesttype = "checkServer";
public Result(boolean allow) {
this.allow = allow;
}
public boolean allow;
}
} }

View file

@ -0,0 +1,28 @@
package ru.gravit.launchserver.socket.websocket.json.auth;
import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.events.request.ProfilesRequestEvent;
import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService;
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
import java.util.List;
public class ProfilesResponse implements JsonResponseInterface {
@Override
public String getType() {
return "profiles";
}
@Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception {
if(!client.isAuth)
{
service.sendObject(ctx, new WebSocketService.ErrorResult("Access denied"));
return;
}
service.sendObject(ctx, new ProfilesRequestEvent((List<ClientProfile>) LaunchServer.server.getProfiles()));
}
}

View file

@ -0,0 +1,39 @@
package ru.gravit.launchserver.socket.websocket.json.auth;
import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService;
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
import java.util.Collection;
public class SetProfileResponse implements JsonResponseInterface {
@Override
public String getType() {
return "setProfile";
}
@Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception {
if(!client.isAuth)
{
service.sendObject(ctx, new WebSocketService.ErrorResult("Access denied"));
return;
}
Collection<ClientProfile> profiles = LaunchServer.server.getProfiles();
for (ClientProfile p : profiles) {
if (p.getTitle().equals(client)) {
if (!p.isWhitelistContains(client.username)) {
service.sendObject(ctx, new WebSocketService.ErrorResult(LaunchServer.server.config.whitelistRejectString));
return;
}
client.profile = p;
service.sendObject(ctx, new WebSocketService.SuccessResult(getType()));
break;
}
}
service.sendObject(ctx, new WebSocketService.ErrorResult("Profile not found"));
}
}

View file

@ -0,0 +1,36 @@
package ru.gravit.launchserver.socket.websocket.json.profile;
import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.events.request.BatchProfileByUsernameRequestEvent;
import ru.gravit.launcher.profiles.PlayerProfile;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService;
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
import java.util.UUID;
public class BatchProfileByUsername implements JsonResponseInterface {
class Entry
{
String username;
String client;
}
Entry[] list;
@Override
public String getType() {
return "batchProfileByUsername";
}
@Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception {
BatchProfileByUsernameRequestEvent result = new BatchProfileByUsernameRequestEvent();
result.playerProfiles = new PlayerProfile[list.length];
for(int i=0;i<list.length;++i)
{
UUID uuid = LaunchServer.server.config.authHandler.usernameToUUID(list[i].username);
result.playerProfiles[i] = ProfileByUUIDResponse.getProfile(LaunchServer.server,uuid,list[i].username,list[i].client);
}
service.sendObject(ctx, result);
}
}

View file

@ -0,0 +1,52 @@
package ru.gravit.launchserver.socket.websocket.json.profile;
import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.events.request.ProfileByUUIDRequestEvent;
import ru.gravit.launcher.profiles.PlayerProfile;
import ru.gravit.launcher.profiles.Texture;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService;
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
import ru.gravit.utils.helper.LogHelper;
import java.io.IOException;
import java.util.UUID;
public class ProfileByUUIDResponse implements JsonResponseInterface {
public UUID uuid;
public String client;
public static PlayerProfile getProfile(LaunchServer server, UUID uuid, String username, String client) {
// Get skin texture
Texture skin;
try {
skin = server.config.textureProvider.getSkinTexture(uuid, username, client);
} catch (IOException e) {
LogHelper.error(new IOException(String.format("Can't get skin texture: '%s'", username), e));
skin = null;
}
// Get cloak texture
Texture cloak;
try {
cloak = server.config.textureProvider.getCloakTexture(uuid, username, client);
} catch (IOException e) {
LogHelper.error(new IOException(String.format("Can't get cloak texture: '%s'", username), e));
cloak = null;
}
// Return combined profile
return new PlayerProfile(uuid, username, skin, cloak);
}
@Override
public String getType() {
return "profileByUUID";
}
@Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception {
String username = LaunchServer.server.config.authHandler.uuidToUsername(uuid);
service.sendObject(ctx, new ProfileByUUIDRequestEvent(getProfile(LaunchServer.server,uuid,username,this.client)));
}
}

View file

@ -0,0 +1,27 @@
package ru.gravit.launchserver.socket.websocket.json.profile;
import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.events.request.ProfileByUsernameRequestEvent;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService;
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
import java.util.UUID;
import static ru.gravit.launchserver.socket.websocket.json.profile.ProfileByUUIDResponse.getProfile;
public class ProfileByUsername implements JsonResponseInterface {
String username;
String client;
@Override
public String getType() {
return "profileByUsername";
}
@Override
public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception {
UUID uuid = LaunchServer.server.config.authHandler.usernameToUUID(username);
service.sendObject(ctx, new ProfileByUsernameRequestEvent(getProfile(LaunchServer.server,uuid,username,this.client)));
}
}

View file

@ -1,6 +1,7 @@
package ru.gravit.launchserver.socket.websocket.json.update; package ru.gravit.launchserver.socket.websocket.json.update;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.events.request.LauncherRequestEvent;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService; import ru.gravit.launchserver.socket.websocket.WebSocketService;
@ -29,35 +30,25 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
if (launcher_type == 1) // JAR if (launcher_type == 1) // JAR
{ {
byte[] hash = LaunchServer.server.launcherBinary.getBytes().getDigest(); byte[] hash = LaunchServer.server.launcherBinary.getBytes().getDigest();
if (hash == null) service.sendObjectAndClose(ctx, new Result(true, JAR_URL)); if (hash == null) service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, JAR_URL));
if (Arrays.equals(bytes, hash)) { if (Arrays.equals(bytes, hash)) {
service.sendObject(ctx, new Result(false, JAR_URL)); client.checkSign = true;
service.sendObject(ctx, new LauncherRequestEvent(false, JAR_URL));
} else { } else {
service.sendObjectAndClose(ctx, new Result(true, JAR_URL)); service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, JAR_URL));
} }
} else if (launcher_type == 2) //EXE } else if (launcher_type == 2) //EXE
{ {
byte[] hash = LaunchServer.server.launcherEXEBinary.getBytes().getDigest(); byte[] hash = LaunchServer.server.launcherEXEBinary.getBytes().getDigest();
if (hash == null) service.sendObjectAndClose(ctx, new Result(true, EXE_URL)); if (hash == null) service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, EXE_URL));
if (Arrays.equals(bytes, hash)) { if (Arrays.equals(bytes, hash)) {
service.sendObject(ctx, new Result(false, EXE_URL)); client.checkSign = true;
service.sendObject(ctx, new LauncherRequestEvent(false, EXE_URL));
} else { } else {
service.sendObjectAndClose(ctx, new Result(true, EXE_URL)); service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, EXE_URL));
} }
} else service.sendObject(ctx, new WebSocketService.ErrorResult("Request launcher type error")); } else service.sendObject(ctx, new WebSocketService.ErrorResult("Request launcher type error"));
} }
public class Result {
public String type = "success";
public String requesttype = "launcherUpdate";
public String url;
public Result(boolean needUpdate, String url) {
this.needUpdate = needUpdate;
this.url = url;
}
public boolean needUpdate;
}
} }

View file

@ -1,6 +1,7 @@
package ru.gravit.launchserver.socket.websocket.json.update; package ru.gravit.launchserver.socket.websocket.json.update;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import ru.gravit.launcher.events.request.UpdateListRequestEvent;
import ru.gravit.launcher.hasher.HashedDir; import ru.gravit.launcher.hasher.HashedDir;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.socket.Client;
@ -22,18 +23,7 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
return; return;
} }
HashedDir hdir = LaunchServer.server.updatesDirMap.get(dir).object; HashedDir hdir = LaunchServer.server.updatesDirMap.get(dir).object;
service.sendObject(ctx, new Result(hdir)); service.sendObject(ctx, new UpdateListRequestEvent(hdir));
} }
class Result {
public final String type;
public final String requesttype;
public final HashedDir dir;
Result(HashedDir dir) {
this.dir = dir;
type = "success";
requesttype = "updateList";
}
}
} }

View file

@ -25,11 +25,6 @@
@ClientEndpoint @ClientEndpoint
public class ClientJSONPoint { public class ClientJSONPoint {
public Session session = null; public Session session = null;
private ClientWebSocketService service;
public void setService(ClientWebSocketService service) {
this.service = service;
}
@OnOpen @OnOpen
public void onOpen(final Session session_r) { public void onOpen(final Session session_r) {
@ -44,7 +39,7 @@ public void processError(final Throwable t) {
@OnMessage @OnMessage
public void processMessage(Reader message) { public void processMessage(Reader message) {
service.processMessage(message);
} }
public void send(String js) throws IOException { public void send(String js) throws IOException {

View file

@ -4,39 +4,46 @@
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import ru.gravit.launcher.hasher.HashedEntry; import ru.gravit.launcher.hasher.HashedEntry;
import ru.gravit.launcher.hasher.HashedEntryAdapter; import ru.gravit.launcher.hasher.HashedEntryAdapter;
import ru.gravit.launcher.request.ResultInterface;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
public class ClientWebSocketService { public class ClientWebSocketService extends ClientJSONPoint {
public final GsonBuilder gsonBuilder; public final GsonBuilder gsonBuilder;
public final Gson gson; public final Gson gson;
public final ClientJSONPoint point; private HashMap<String, Class<? extends RequestInterface>> requests;
private HashMap<String, Class<RequestInterface>> requests; private HashMap<String, Class<? extends ResultInterface>> results;
private HashMap<String, Class<ResultInterface>> results; private HashSet<EventHandler> handlers;
public ClientWebSocketService(GsonBuilder gsonBuilder, ClientJSONPoint point) { public ClientWebSocketService(GsonBuilder gsonBuilder) {
requests = new HashMap<>(); requests = new HashMap<>();
results = new HashMap<>(); results = new HashMap<>();
handlers = new HashSet<>();
this.gsonBuilder = gsonBuilder; this.gsonBuilder = gsonBuilder;
gsonBuilder.registerTypeAdapter(RequestInterface.class, new JsonRequestAdapter(this)); gsonBuilder.registerTypeAdapter(RequestInterface.class, new JsonRequestAdapter(this));
gsonBuilder.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter()); gsonBuilder.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter());
this.gson = gsonBuilder.create(); this.gson = gsonBuilder.create();
this.point = point;
point.setService(this);
} }
@Override
public void processMessage(Reader reader) { public void processMessage(Reader reader) {
ResultInterface result = gson.fromJson(reader, ResultInterface.class); ResultInterface result = gson.fromJson(reader, ResultInterface.class);
result.process(); for(EventHandler handler : handlers)
{
handler.process(result);
}
} }
public Class<RequestInterface> getRequestClass(String key) { public Class<? extends RequestInterface> getRequestClass(String key) {
return requests.get(key); return requests.get(key);
} }
public Class<? extends ResultInterface> getResultClass(String key) {
return results.get(key);
}
public void registerRequest(String key, Class<RequestInterface> clazz) { public void registerRequest(String key, Class<? extends RequestInterface> clazz) {
requests.put(key, clazz); requests.put(key, clazz);
} }
@ -44,7 +51,7 @@ public void registerRequests() {
} }
public void registerResult(String key, Class<ResultInterface> clazz) { public void registerResult(String key, Class<? extends ResultInterface> clazz) {
results.put(key, clazz); results.put(key, clazz);
} }
@ -52,11 +59,21 @@ public void registerResults() {
} }
public void registerHandler(EventHandler eventHandler)
{
handlers.add(eventHandler);
}
public void sendObjectAsync(Object obj) throws IOException { public void sendObjectAsync(Object obj) throws IOException {
point.sendAsync(gson.toJson(obj)); sendAsync(gson.toJson(obj));
} }
public void sendObject(Object obj) throws IOException { public void sendObject(Object obj) throws IOException {
point.send(gson.toJson(obj)); send(gson.toJson(obj));
}
@FunctionalInterface
public interface EventHandler
{
void process(ResultInterface resultInterface);
} }
} }

View file

@ -15,7 +15,7 @@ public JsonRequestAdapter(ClientWebSocketService service) {
@Override @Override
public RequestInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { public RequestInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
Class<RequestInterface> cls = service.getRequestClass(typename); Class<? extends RequestInterface> cls = service.getRequestClass(typename);
return (RequestInterface) context.deserialize(json, cls); return (RequestInterface) context.deserialize(json, cls);

View file

@ -0,0 +1,35 @@
package ru.gravit.launcher.request.websockets;
import com.google.gson.*;
import ru.gravit.launcher.request.ResultInterface;
import java.lang.reflect.Type;
public class JsonResultAdapter implements JsonSerializer<ResultInterface>, JsonDeserializer<ResultInterface> {
private final ClientWebSocketService service;
private static final String PROP_NAME = "type";
public JsonResultAdapter(ClientWebSocketService service) {
this.service = service;
}
@Override
public ResultInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
Class<? extends ResultInterface> cls = service.getResultClass(typename);
return (ResultInterface) context.deserialize(json, cls);
}
@Override
public JsonElement serialize(ResultInterface src, Type typeOfSrc, JsonSerializationContext context) {
// note : won't work, you must delegate this
JsonObject jo = context.serialize(src).getAsJsonObject();
String classPath = src.getType();
jo.add(PROP_NAME, new JsonPrimitive(classPath));
return jo;
}
}

View file

@ -0,0 +1,26 @@
package ru.gravit.launcher.request.websockets;
import ru.gravit.launcher.request.ResultInterface;
import java.io.IOException;
public class LegacyRequestBridge {
public static WaitEventHandler waitEventHandler = new WaitEventHandler();
public static ClientWebSocketService service;
public static ResultInterface sendRequest(RequestInterface request) throws IOException, InterruptedException {
WaitEventHandler.ResultEvent e = new WaitEventHandler.ResultEvent();
e.type = request.getType();
waitEventHandler.requests.add(e);
service.sendObject(request);
while(!e.ready)
{
synchronized(e)
{
e.wait();
}
}
ResultInterface result = e.result;
waitEventHandler.requests.remove(e);
return result;
}
}

View file

@ -1,5 +0,0 @@
package ru.gravit.launcher.request.websockets;
public interface ResultInterface {
void process();
}

View file

@ -0,0 +1,30 @@
package ru.gravit.launcher.request.websockets;
import ru.gravit.launcher.request.ResultInterface;
import java.util.HashSet;
public class WaitEventHandler implements ClientWebSocketService.EventHandler {
public HashSet<ResultEvent> requests;
@Override
public void process(ResultInterface result) {
for(ResultEvent r : requests)
{
if(r.type.equals(result.getType()))
{
synchronized (r)
{
r.result = result;
r.ready = true;
r.notifyAll();
}
}
}
}
public static class ResultEvent
{
public ResultInterface result;
public String type;
public boolean ready;
}
}

View file

@ -0,0 +1,29 @@
package ru.gravit.launcher.events.request;
import ru.gravit.launcher.ClientPermissions;
import ru.gravit.launcher.profiles.PlayerProfile;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.utils.event.EventInterface;
import java.util.UUID;
public class AuthRequestEvent implements EventInterface, ResultInterface {
private static final UUID uuid = UUID.fromString("77e1bfd7-adf9-4f5d-87d6-a7dd068deb74");
public AuthRequestEvent() {
}
public String error;
public ClientPermissions permissions;
public PlayerProfile playerProfile;
public String accessToken;
@Override
public UUID getUUID() {
return uuid;
}
@Override
public String getType() {
return "auth";
}
}

View file

@ -0,0 +1,23 @@
package ru.gravit.launcher.events.request;
import ru.gravit.launcher.profiles.PlayerProfile;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.utils.event.EventInterface;
import java.util.UUID;
public class BatchProfileByUsernameRequestEvent implements EventInterface, ResultInterface
{
private static final UUID uuid = UUID.fromString("c1d6729e-be2c-48cc-b5ae-af8c012232c3");
public String error;
public PlayerProfile[] playerProfiles;
@Override
public UUID getUUID() {
return uuid;
}
@Override
public String getType() {
return "batchProfileByUsername";
}
}

View file

@ -0,0 +1,23 @@
package ru.gravit.launcher.events.request;
import ru.gravit.launcher.profiles.PlayerProfile;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.utils.event.EventInterface;
import java.util.UUID;
public class CheckServerEvent implements EventInterface, ResultInterface {
private static final UUID _uuid = UUID.fromString("8801d07c-51ba-4059-b61d-fe1f1510b28a");
public String type = "success";
public UUID uuid;
public PlayerProfile playerProfile;
@Override
public UUID getUUID() {
return _uuid;
}
@Override
public String getType() {
return "checkServe";
}
}

View file

@ -0,0 +1,26 @@
package ru.gravit.launcher.events.request;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.utils.event.EventInterface;
import java.util.UUID;
public class JoinServerRequestEvent implements EventInterface, ResultInterface {
private static final UUID uuid = UUID.fromString("2a12e7b5-3f4a-4891-a2f9-ea141c8e1995");
public String type = "success";
public JoinServerRequestEvent(boolean allow) {
this.allow = allow;
}
public boolean allow;
@Override
public UUID getUUID() {
return uuid;
}
@Override
public String getType() {
return "joinServer";
}
}

View file

@ -0,0 +1,28 @@
package ru.gravit.launcher.events.request;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.utils.event.EventInterface;
import java.util.UUID;
public class LauncherRequestEvent implements EventInterface, ResultInterface {
private static final UUID uuid = UUID.fromString("d54cc12a-4f59-4f23-9b10-f527fdd2e38f");
public String type = "success";
public String url;
public LauncherRequestEvent(boolean needUpdate, String url) {
this.needUpdate = needUpdate;
this.url = url;
}
public boolean needUpdate;
@Override
public UUID getUUID() {
return uuid;
}
@Override
public String getType() {
return "launcher";
}
}

View file

@ -0,0 +1,27 @@
package ru.gravit.launcher.events.request;
import ru.gravit.launcher.profiles.PlayerProfile;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.utils.event.EventInterface;
import java.util.UUID;
public class ProfileByUUIDRequestEvent implements EventInterface, ResultInterface
{
private static final UUID uuid = UUID.fromString("b9014cf3-4b95-4d38-8c5f-867f190a18a0");
String error;
PlayerProfile playerProfile;
public ProfileByUUIDRequestEvent(PlayerProfile playerProfile) {
this.playerProfile = playerProfile;
}
@Override
public UUID getUUID() {
return uuid;
}
@Override
public String getType() {
return "profileByUUID";
}
}

View file

@ -0,0 +1,27 @@
package ru.gravit.launcher.events.request;
import ru.gravit.launcher.profiles.PlayerProfile;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.utils.event.EventInterface;
import java.util.UUID;
public class ProfileByUsernameRequestEvent implements EventInterface, ResultInterface
{
private static final UUID uuid = UUID.fromString("06204302-ff6b-4779-b97d-541e3bc39aa1");
String error;
PlayerProfile playerProfile;
public ProfileByUsernameRequestEvent(PlayerProfile playerProfile) {
this.playerProfile = playerProfile;
}
@Override
public UUID getUUID() {
return uuid;
}
@Override
public String getType() {
return "profileByUsername";
}
}

View file

@ -0,0 +1,29 @@
package ru.gravit.launcher.events.request;
import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.utils.event.EventInterface;
import java.util.List;
import java.util.UUID;
public class ProfilesRequestEvent implements EventInterface, ResultInterface
{
private static final UUID uuid = UUID.fromString("2f26fbdf-598a-46dd-92fc-1699c0e173b1");
List<ClientProfile> profiles;
public ProfilesRequestEvent(List<ClientProfile> profiles) {
this.profiles = profiles;
}
String error;
@Override
public UUID getUUID() {
return uuid;
}
@Override
public String getType() {
return "profiles";
}
}

View file

@ -0,0 +1,27 @@
package ru.gravit.launcher.events.request;
import ru.gravit.launcher.hasher.HashedDir;
import ru.gravit.launcher.request.ResultInterface;
import ru.gravit.utils.event.EventInterface;
import java.util.UUID;
public class UpdateListRequestEvent implements EventInterface, ResultInterface {
private static final UUID uuid = UUID.fromString("5fa836ae-6b61-401c-96ac-d8396f07ec6b");
public final String type;
public final HashedDir dir;
public UpdateListRequestEvent(HashedDir dir) {
this.dir = dir;
type = "success";
}
@Override
public UUID getUUID() {
return uuid;
}
@Override
public String getType() {
return "updateList";
}
}

View file

@ -0,0 +1,21 @@
package ru.gravit.launcher.request;
import com.google.gson.*;
import ru.gravit.launcher.request.ResultInterface;
import java.lang.reflect.Type;
public class JsonResultSerializeAdapter implements JsonSerializer<ResultInterface> {
private static final String PROP_NAME = "type";
@Override
public JsonElement serialize(ResultInterface src, Type typeOfSrc, JsonSerializationContext context) {
// note : won't work, you must delegate this
JsonObject jo = context.serialize(src).getAsJsonObject();
String classPath = src.getType();
jo.add(PROP_NAME, new JsonPrimitive(classPath));
return jo;
}
}

View file

@ -0,0 +1,5 @@
package ru.gravit.launcher.request;
public interface ResultInterface {
String getType();
}