2019-04-04 15:10:28 +03:00
|
|
|
package ru.gravit.launchserver.websocket;
|
2018-10-01 11:07:47 +03:00
|
|
|
|
|
|
|
import com.google.gson.Gson;
|
2018-10-01 11:55:52 +03:00
|
|
|
import com.google.gson.GsonBuilder;
|
2018-10-01 13:01:10 +03:00
|
|
|
import io.netty.channel.Channel;
|
2018-10-01 14:15:39 +03:00
|
|
|
import io.netty.channel.ChannelFutureListener;
|
2018-10-01 11:07:47 +03:00
|
|
|
import io.netty.channel.ChannelHandlerContext;
|
2018-10-01 13:01:10 +03:00
|
|
|
import io.netty.channel.group.ChannelGroup;
|
2018-10-01 11:07:47 +03:00
|
|
|
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
2019-04-19 23:51:27 +03:00
|
|
|
import ru.gravit.launcher.events.ExceptionEvent;
|
|
|
|
import ru.gravit.launcher.events.RequestEvent;
|
2019-05-03 19:16:00 +03:00
|
|
|
import ru.gravit.launcher.events.request.AuthRequestEvent;
|
2019-04-19 23:51:27 +03:00
|
|
|
import ru.gravit.launcher.events.request.ErrorRequestEvent;
|
2018-10-02 16:25:07 +03:00
|
|
|
import ru.gravit.launcher.hasher.HashedEntry;
|
2018-12-06 05:29:34 +03:00
|
|
|
import ru.gravit.launcher.hasher.HashedEntryAdapter;
|
2019-01-28 19:21:24 +03:00
|
|
|
import ru.gravit.launcher.request.JsonResultSerializeAdapter;
|
2019-05-03 19:07:37 +03:00
|
|
|
import ru.gravit.launcher.request.RequestException;
|
2019-01-28 19:21:24 +03:00
|
|
|
import ru.gravit.launcher.request.ResultInterface;
|
2019-05-03 19:07:37 +03:00
|
|
|
import ru.gravit.launcher.request.admin.ProxyRequest;
|
2018-10-01 11:07:47 +03:00
|
|
|
import ru.gravit.launchserver.LaunchServer;
|
2018-10-01 12:42:42 +03:00
|
|
|
import ru.gravit.launchserver.socket.Client;
|
2019-04-04 15:10:28 +03:00
|
|
|
import ru.gravit.launchserver.websocket.json.JsonResponseAdapter;
|
|
|
|
import ru.gravit.launchserver.websocket.json.JsonResponseInterface;
|
2019-04-19 23:23:54 +03:00
|
|
|
import ru.gravit.launchserver.websocket.json.SimpleResponse;
|
2019-04-04 15:10:28 +03:00
|
|
|
import ru.gravit.launchserver.websocket.json.admin.AddLogListenerResponse;
|
|
|
|
import ru.gravit.launchserver.websocket.json.admin.ExecCommandResponse;
|
2019-05-03 19:07:37 +03:00
|
|
|
import ru.gravit.launchserver.websocket.json.admin.ProxyCommandResponse;
|
2019-04-04 15:10:28 +03:00
|
|
|
import ru.gravit.launchserver.websocket.json.auth.*;
|
|
|
|
import ru.gravit.launchserver.websocket.json.profile.BatchProfileByUsername;
|
|
|
|
import ru.gravit.launchserver.websocket.json.profile.ProfileByUUIDResponse;
|
|
|
|
import ru.gravit.launchserver.websocket.json.profile.ProfileByUsername;
|
2019-04-12 00:58:45 +03:00
|
|
|
import ru.gravit.launchserver.websocket.json.secure.GetSecureTokenResponse;
|
|
|
|
import ru.gravit.launchserver.websocket.json.secure.VerifySecureTokenResponse;
|
2019-04-04 15:10:28 +03:00
|
|
|
import ru.gravit.launchserver.websocket.json.update.LauncherResponse;
|
|
|
|
import ru.gravit.launchserver.websocket.json.update.UpdateListResponse;
|
|
|
|
import ru.gravit.launchserver.websocket.json.update.UpdateResponse;
|
2018-10-01 11:07:47 +03:00
|
|
|
import ru.gravit.utils.helper.LogHelper;
|
|
|
|
|
2019-02-10 11:09:29 +03:00
|
|
|
import java.lang.reflect.Type;
|
2019-01-15 06:35:39 +03:00
|
|
|
import java.util.HashMap;
|
|
|
|
|
2019-04-21 16:01:16 +03:00
|
|
|
@SuppressWarnings("rawtypes")
|
2018-10-01 11:07:47 +03:00
|
|
|
public class WebSocketService {
|
2018-10-01 13:01:10 +03:00
|
|
|
public final ChannelGroup channels;
|
2018-11-08 15:30:16 +03:00
|
|
|
|
2018-10-01 13:01:10 +03:00
|
|
|
public WebSocketService(ChannelGroup channels, LaunchServer server, GsonBuilder gson) {
|
|
|
|
this.channels = channels;
|
2018-10-01 11:07:47 +03:00
|
|
|
this.server = server;
|
2018-10-01 11:55:52 +03:00
|
|
|
this.gsonBuiler = gson;
|
2018-11-11 09:01:19 +03:00
|
|
|
this.gsonBuiler.registerTypeAdapter(JsonResponseInterface.class, new JsonResponseAdapter(this));
|
2019-04-03 16:27:40 +03:00
|
|
|
this.gsonBuiler.registerTypeAdapter(ResultInterface.class, new JsonResultSerializeAdapter());
|
2018-11-11 09:01:19 +03:00
|
|
|
this.gsonBuiler.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter());
|
2018-10-01 11:55:52 +03:00
|
|
|
this.gson = gsonBuiler.create();
|
2018-10-01 11:07:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
private final LaunchServer server;
|
2018-11-08 15:30:16 +03:00
|
|
|
private static final HashMap<String, Class> responses = new HashMap<>();
|
2018-10-01 11:07:47 +03:00
|
|
|
private final Gson gson;
|
2018-10-01 11:55:52 +03:00
|
|
|
private final GsonBuilder gsonBuiler;
|
2018-10-01 11:07:47 +03:00
|
|
|
|
2018-11-08 15:30:16 +03:00
|
|
|
void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client) {
|
2018-10-01 11:07:47 +03:00
|
|
|
String request = frame.text();
|
2018-10-01 11:36:19 +03:00
|
|
|
JsonResponseInterface response = gson.fromJson(request, JsonResponseInterface.class);
|
2019-05-03 19:07:37 +03:00
|
|
|
if(server.config.netty.proxy.enabled)
|
|
|
|
{
|
|
|
|
if(server.config.netty.proxy.requests.contains(response.getType()))
|
|
|
|
{
|
|
|
|
if(response instanceof SimpleResponse)
|
|
|
|
{
|
|
|
|
SimpleResponse simpleResponse = (SimpleResponse) response;
|
|
|
|
simpleResponse.server = server;
|
|
|
|
simpleResponse.service = this;
|
|
|
|
simpleResponse.ctx = ctx;
|
|
|
|
}
|
|
|
|
LogHelper.debug("Proxy %s request", response.getType());
|
|
|
|
ProxyRequest proxyRequest = new ProxyRequest(response, 0);
|
2019-05-03 19:16:00 +03:00
|
|
|
proxyRequest.isCheckSign = client.checkSign;
|
2019-05-03 19:07:37 +03:00
|
|
|
try {
|
|
|
|
ResultInterface result = proxyRequest.request();
|
2019-05-03 19:16:00 +03:00
|
|
|
if(result instanceof AuthRequestEvent)
|
|
|
|
{
|
|
|
|
LogHelper.debug("Client auth params get successful");
|
|
|
|
AuthRequestEvent authRequestEvent = (AuthRequestEvent) result;
|
|
|
|
client.isAuth = true;
|
|
|
|
client.session = authRequestEvent.session;
|
|
|
|
if(authRequestEvent.playerProfile != null) client.username = authRequestEvent.playerProfile.username;
|
|
|
|
}
|
2019-05-03 19:07:37 +03:00
|
|
|
sendObject(ctx, result);
|
|
|
|
} catch (RequestException e)
|
|
|
|
{
|
|
|
|
sendObject(ctx, new ErrorRequestEvent(e.getMessage()));
|
|
|
|
} catch (Exception e) {
|
|
|
|
LogHelper.error(e);
|
|
|
|
RequestEvent event;
|
|
|
|
if(server.config.netty.sendExceptionEnabled)
|
|
|
|
{
|
|
|
|
event = new ExceptionEvent(e);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
event = new ErrorRequestEvent("Fatal server error. Contact administrator");
|
|
|
|
}
|
|
|
|
if(response instanceof SimpleResponse)
|
|
|
|
{
|
|
|
|
event.requestUUID = ((SimpleResponse) response).requestUUID;
|
|
|
|
}
|
|
|
|
sendObject(ctx, event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
process(ctx,response, client);
|
|
|
|
}
|
|
|
|
void process(ChannelHandlerContext ctx, JsonResponseInterface response, Client client)
|
|
|
|
{
|
2019-04-19 23:23:54 +03:00
|
|
|
if(response instanceof SimpleResponse)
|
|
|
|
{
|
|
|
|
SimpleResponse simpleResponse = (SimpleResponse) response;
|
|
|
|
simpleResponse.server = server;
|
|
|
|
simpleResponse.service = this;
|
|
|
|
simpleResponse.ctx = ctx;
|
|
|
|
}
|
2018-10-01 11:07:47 +03:00
|
|
|
try {
|
2019-04-19 23:23:54 +03:00
|
|
|
response.execute(ctx, client);
|
2018-11-08 15:30:16 +03:00
|
|
|
} catch (Exception e) {
|
2018-10-01 11:07:47 +03:00
|
|
|
LogHelper.error(e);
|
2019-04-19 23:51:27 +03:00
|
|
|
RequestEvent event;
|
2019-04-21 00:56:56 +03:00
|
|
|
if(server.config.netty.sendExceptionEnabled)
|
2019-04-19 23:51:27 +03:00
|
|
|
{
|
|
|
|
event = new ExceptionEvent(e);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
event = new ErrorRequestEvent("Fatal server error. Contact administrator");
|
|
|
|
}
|
|
|
|
if(response instanceof SimpleResponse)
|
|
|
|
{
|
|
|
|
event.requestUUID = ((SimpleResponse) response).requestUUID;
|
|
|
|
}
|
|
|
|
sendObject(ctx, event);
|
2018-10-01 11:07:47 +03:00
|
|
|
}
|
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
|
|
|
public Class getResponseClass(String type) {
|
2018-10-01 11:55:52 +03:00
|
|
|
return responses.get(type);
|
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
|
|
|
public void registerResponse(String key, Class responseInterfaceClass) {
|
|
|
|
responses.put(key, responseInterfaceClass);
|
2018-10-01 11:55:52 +03:00
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
|
|
|
public void registerClient(Channel channel) {
|
2018-10-01 13:01:10 +03:00
|
|
|
channels.add(channel);
|
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
|
|
|
public void registerResponses() {
|
2018-10-01 11:55:52 +03:00
|
|
|
registerResponse("auth", AuthResponse.class);
|
2018-10-01 13:39:35 +03:00
|
|
|
registerResponse("checkServer", CheckServerResponse.class);
|
|
|
|
registerResponse("joinServer", JoinServerResponse.class);
|
2019-01-28 16:33:39 +03:00
|
|
|
registerResponse("profiles", ProfilesResponse.class);
|
2019-02-10 12:48:44 +03:00
|
|
|
registerResponse("launcher", LauncherResponse.class);
|
2018-10-05 11:36:50 +03:00
|
|
|
registerResponse("updateList", UpdateListResponse.class);
|
2019-02-17 11:30:03 +03:00
|
|
|
registerResponse("cmdExec", ExecCommandResponse.class);
|
2019-02-10 14:20:52 +03:00
|
|
|
registerResponse("setProfile", SetProfileResponse.class);
|
2019-02-17 10:24:20 +03:00
|
|
|
registerResponse("addLogListener", AddLogListenerResponse.class);
|
2019-02-20 12:55:21 +03:00
|
|
|
registerResponse("update", UpdateResponse.class);
|
2019-04-04 09:50:04 +03:00
|
|
|
registerResponse("restoreSession", RestoreSessionResponse.class);
|
2019-04-04 10:02:42 +03:00
|
|
|
registerResponse("batchProfileByUsername", BatchProfileByUsername.class);
|
|
|
|
registerResponse("profileByUsername", ProfileByUsername.class);
|
|
|
|
registerResponse("profileByUUID", ProfileByUUIDResponse.class);
|
2019-04-12 00:58:45 +03:00
|
|
|
registerResponse("getSecureToken", GetSecureTokenResponse.class);
|
|
|
|
registerResponse("verifySecureToken", VerifySecureTokenResponse.class);
|
2019-04-13 20:55:01 +03:00
|
|
|
registerResponse("getAvailabilityAuth", GetAvailabilityAuthResponse.class);
|
2019-05-03 19:07:37 +03:00
|
|
|
registerResponse("proxy", ProxyCommandResponse.class);
|
2018-10-01 11:55:52 +03:00
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
|
|
|
public void sendObject(ChannelHandlerContext ctx, Object obj) {
|
2019-02-10 11:09:29 +03:00
|
|
|
ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, ResultInterface.class)));
|
|
|
|
}
|
2019-04-03 16:27:40 +03:00
|
|
|
|
2019-02-10 11:09:29 +03:00
|
|
|
public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
|
|
|
|
ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)));
|
2018-10-01 11:07:47 +03:00
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
2019-05-03 16:49:00 +03:00
|
|
|
public void sendObjectAll(Object obj) {
|
|
|
|
for(Channel ch : channels)
|
|
|
|
{
|
|
|
|
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, ResultInterface.class)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void sendObjectAll(Object obj, Type type) {
|
|
|
|
for(Channel ch : channels)
|
|
|
|
{
|
|
|
|
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-08 15:30:16 +03:00
|
|
|
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) {
|
2019-02-10 11:09:29 +03:00
|
|
|
ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, ResultInterface.class))).addListener(ChannelFutureListener.CLOSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type) {
|
|
|
|
ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type))).addListener(ChannelFutureListener.CLOSE);
|
2018-10-01 14:15:39 +03:00
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
|
|
|
public void sendEvent(EventResult obj) {
|
2018-10-01 13:01:10 +03:00
|
|
|
channels.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj)));
|
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
2019-02-10 12:48:44 +03:00
|
|
|
public static class EventResult implements ResultInterface {
|
2018-10-01 13:01:10 +03:00
|
|
|
public EventResult() {
|
2019-02-10 12:48:44 +03:00
|
|
|
|
2018-10-01 13:01:10 +03:00
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
2019-02-10 12:48:44 +03:00
|
|
|
@Override
|
|
|
|
public String getType() {
|
|
|
|
return "event";
|
|
|
|
}
|
2018-10-01 13:01:10 +03:00
|
|
|
}
|
2018-11-08 15:30:16 +03:00
|
|
|
|
2018-10-01 11:07:47 +03:00
|
|
|
}
|