RuneHive-Game
Loading...
Searching...
No Matches
com.runehive.net.codec.login.LoginDecoder Class Reference

The class that handles a connection through the login protocol. More...

Inheritance diagram for com.runehive.net.codec.login.LoginDecoder:
Collaboration diagram for com.runehive.net.codec.login.LoginDecoder:

Classes

enum  State

Protected Member Functions

void decode (ChannelHandlerContext ctx, ByteBuf in, List< Object > out) throws Exception

Private Member Functions

void decodeConnectionType (ChannelHandlerContext ctx, ByteBuf in) throws Exception
void decodeHandshake (ChannelHandlerContext ctx, ByteBuf in)
void decodePayload (ChannelHandlerContext ctx, ByteBuf in, List< Object > out)
void sendResponseCode (ChannelHandlerContext ctx, LoginResponse response)

Private Attributes

State state = State.HANDSHAKE

Static Private Attributes

static final Logger logger = LogManager.getLogger(LoginDecoder.class)
static final int LOGIN_BLOCK_HEADER_SIZE = 38
static final int LOGIN_HANDSHAKE = 14
static final int MAGIC_NUMBER = 255
static final int NEW_CONNECTION_OPCODE = 16
static final ThreadLocal< Random > RANDOM = ThreadLocal.withInitial(SecureRandom::new)
static final int RECONNECTION_OPCODE = 18

Detailed Description

The class that handles a connection through the login protocol.

Author
nshusa

Definition at line 26 of file LoginDecoder.java.

Member Function Documentation

◆ decode()

void com.runehive.net.codec.login.LoginDecoder.decode ( ChannelHandlerContext ctx,
ByteBuf in,
List< Object > out ) throws Exception
protected

Definition at line 41 of file LoginDecoder.java.

41 {
42 switch (state) {
43
44 case HANDSHAKE:
45 decodeHandshake(ctx, in);
46 state = State.CONNECTION_TYPE;
47 break;
48
49 case CONNECTION_TYPE:
50 decodeConnectionType(ctx, in);
51 state = State.PAYLOAD;
52 break;
53
54 case PAYLOAD:
55 decodePayload(ctx, in, out);
56 break;
57
58 }
59 }

References com.runehive.net.codec.login.LoginDecoder.State.CONNECTION_TYPE, decodeConnectionType(), decodeHandshake(), decodePayload(), com.runehive.net.codec.login.LoginDecoder.State.PAYLOAD, and state.

Here is the call graph for this function:

◆ decodeConnectionType()

void com.runehive.net.codec.login.LoginDecoder.decodeConnectionType ( ChannelHandlerContext ctx,
ByteBuf in ) throws Exception
private

Definition at line 86 of file LoginDecoder.java.

86 {
87 if (in.isReadable()) {
88 final int connectionType = in.readUnsignedByte();
89
90 if (connectionType != NEW_CONNECTION_OPCODE && connectionType != RECONNECTION_OPCODE) {
91 sendResponseCode(ctx, LoginResponse.LOGIN_SERVER_REJECTED_SESSION);
92 }
93 } else {
94 sendResponseCode(ctx, LoginResponse.LOGIN_SERVER_REJECTED_SESSION);
95 }
96 }

References com.runehive.net.codec.login.LoginResponse.LOGIN_SERVER_REJECTED_SESSION, NEW_CONNECTION_OPCODE, RECONNECTION_OPCODE, and sendResponseCode().

Referenced by decode().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ decodeHandshake()

void com.runehive.net.codec.login.LoginDecoder.decodeHandshake ( ChannelHandlerContext ctx,
ByteBuf in )
private

Definition at line 61 of file LoginDecoder.java.

61 {
62 final Channel channel = ctx.channel();
63 channel.attr(Config.SESSION_KEY).set(new LoginSession(channel));
64
65 if (in.readableBytes() >= 2) {
66 final int handshake = in.readUnsignedByte();
67
68 if (handshake != LOGIN_HANDSHAKE) {
69 sendResponseCode(ctx, LoginResponse.LOGIN_SERVER_REJECTED_SESSION);
70 return;
71 }
72
73 @SuppressWarnings("unused") final int nameHash = in.readUnsignedByte();
74 final long serverSeed = RANDOM.get().nextLong();
75
76 ByteBuf buf = ctx.alloc().buffer(17);
77 buf.writeLong(0);
78 buf.writeByte(0);
79 buf.writeLong(serverSeed);
80 ctx.writeAndFlush(buf, ctx.voidPromise());
81 } else {
82 sendResponseCode(ctx, LoginResponse.LOGIN_SERVER_REJECTED_SESSION);
83 }
84 }

References LOGIN_HANDSHAKE, com.runehive.net.codec.login.LoginResponse.LOGIN_SERVER_REJECTED_SESSION, RANDOM, sendResponseCode(), and com.runehive.Config.SESSION_KEY.

Referenced by decode().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ decodePayload()

void com.runehive.net.codec.login.LoginDecoder.decodePayload ( ChannelHandlerContext ctx,
ByteBuf in,
List< Object > out )
private

Definition at line 98 of file LoginDecoder.java.

98 {
99 final String host = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
100
101 final int loginBlockSize = in.readUnsignedByte();
102 if (in.isReadable(loginBlockSize)) {
103 final int magicId = in.readUnsignedByte();
104
105 if (magicId != MAGIC_NUMBER) {
106 logger.warn(String.format("[%s] wrong magic id: %d", host, magicId));
107 sendResponseCode(ctx, LoginResponse.LOGIN_SERVER_REJECTED_SESSION);
108 return;
109 }
110
111 final int clientVersion = in.readUnsignedByte();
112 if (Config.CLIENT_VERSION != clientVersion) {
113 logger.warn("[{}] outdated client(client version): {} should be: {}", host, clientVersion, Config.CLIENT_VERSION);
114 sendResponseCode(ctx, LoginResponse.GAME_UPDATED);
115 return;
116 }
117
118 final int memoryVersion = in.readUnsignedByte();
119 if (memoryVersion != 0 && memoryVersion != 1) {
120 logger.warn(String.format("[%s] wrong memory version: %d", host, memoryVersion));
121 sendResponseCode(ctx, LoginResponse.LOGIN_SERVER_REJECTED_SESSION);
122 return;
123 }
124
125 final int[] crcs = new int[9];
126
127 for (int index = 0; index < crcs.length; index++) {
128 crcs[index] = in.readInt();
129 }
130
131 final int expectedSize = in.readUnsignedByte(); // rsa header
132
133 if (expectedSize != loginBlockSize - LOGIN_BLOCK_HEADER_SIZE) {
134 logger.warn(String.format("[%s] wrong rsa block size: %d expecting: %d", host, (loginBlockSize - LOGIN_BLOCK_HEADER_SIZE), expectedSize));
135 sendResponseCode(ctx, LoginResponse.LOGIN_SERVER_REJECTED_SESSION);
136 return;
137 }
138
139 final byte[] rsaBytes = new byte[loginBlockSize - LOGIN_BLOCK_HEADER_SIZE];
140 in.readBytes(rsaBytes);
141
142 final byte[] rsaBufBytes = new BigInteger(rsaBytes).modPow(Config.RSA_EXPONENT, Config.RSA_MODULUS).toByteArray();
143 final int rsaBufferSize = rsaBufBytes.length;
144 final ByteBuf rsaBuffer = in.alloc().buffer(rsaBufferSize, rsaBufferSize);
145 try {
146 rsaBuffer.writeBytes(rsaBufBytes);
147
148 final int rsa = rsaBuffer.readUnsignedByte();
149
150 if (rsa != 10) {
151 logger.warn(String.format("[%s] failed decrypt rsa %d", host, rsa));
152 sendResponseCode(ctx, LoginResponse.LOGIN_SERVER_REJECTED_SESSION);
153 return;
154 }
155
156 final long clientHalf = rsaBuffer.readLong();
157 final long serverHalf = rsaBuffer.readLong();
158
159 int[] isaacSeed = {
160 (int) (clientHalf >> 32),
161 (int) clientHalf,
162 (int) (serverHalf >> 32),
163 (int) serverHalf
164 };
165
166 final IsaacCipher decryptor = new IsaacCipher(isaacSeed);
167
168 for (int index = 0; index < isaacSeed.length; index++) {
169 isaacSeed[index] += 50;
170 }
171
172 final IsaacCipher encryptor = new IsaacCipher(isaacSeed);
173
174 @SuppressWarnings("unused") final int uid = rsaBuffer.readInt();
175
176 final String UUID = ByteBufUtil.readString(rsaBuffer);
177 final String macAddress = ByteBufUtil.readString(rsaBuffer);
178 final String username = ByteBufUtil.readString(rsaBuffer);
179 final String password = ByteBufUtil.readString(rsaBuffer);
180
181 out.add(new LoginDetailsPacket(UUID, macAddress, username, password, encryptor, decryptor));
182 } finally {
183 rsaBuffer.release();
184 }
185 } else {
186 sendResponseCode(ctx, LoginResponse.LOGIN_SERVER_REJECTED_SESSION);
187 }
188 }
val index

References com.runehive.Config.CLIENT_VERSION, com.runehive.net.codec.login.LoginResponse.GAME_UPDATED, logger, LOGIN_BLOCK_HEADER_SIZE, com.runehive.net.codec.login.LoginResponse.LOGIN_SERVER_REJECTED_SESSION, MAGIC_NUMBER, com.runehive.Config.RSA_EXPONENT, com.runehive.Config.RSA_MODULUS, and sendResponseCode().

Referenced by decode().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sendResponseCode()

void com.runehive.net.codec.login.LoginDecoder.sendResponseCode ( ChannelHandlerContext ctx,
LoginResponse response )
private

Definition at line 190 of file LoginDecoder.java.

190 {
191 if (response == LoginResponse.LOGIN_SERVER_REJECTED_SESSION) {
192 final String host = ((InetSocketAddress) ctx.channel().remoteAddress()).getHostString();
193 logger.warn(String.format("[%s] session was rejected", host));
194 }
195 ByteBuf buffer = ctx.alloc().buffer(Byte.BYTES);
196 buffer.writeByte(response.getOpcode());
197 ctx.writeAndFlush(buffer)
198 .addListener(ChannelFutureListener.CLOSE);
199 state = State.IGNORE;
200 }

References com.runehive.net.codec.login.LoginResponse.getOpcode(), com.runehive.net.codec.login.LoginDecoder.State.IGNORE, logger, com.runehive.net.codec.login.LoginResponse.LOGIN_SERVER_REJECTED_SESSION, and state.

Referenced by decodeConnectionType(), decodeHandshake(), and decodePayload().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ logger

final Logger com.runehive.net.codec.login.LoginDecoder.logger = LogManager.getLogger(LoginDecoder.class)
staticprivate

Definition at line 28 of file LoginDecoder.java.

Referenced by decodePayload(), and sendResponseCode().

◆ LOGIN_BLOCK_HEADER_SIZE

final int com.runehive.net.codec.login.LoginDecoder.LOGIN_BLOCK_HEADER_SIZE = 38
staticprivate

Definition at line 34 of file LoginDecoder.java.

Referenced by decodePayload().

◆ LOGIN_HANDSHAKE

final int com.runehive.net.codec.login.LoginDecoder.LOGIN_HANDSHAKE = 14
staticprivate

Definition at line 30 of file LoginDecoder.java.

Referenced by decodeHandshake().

◆ MAGIC_NUMBER

final int com.runehive.net.codec.login.LoginDecoder.MAGIC_NUMBER = 255
staticprivate

Definition at line 33 of file LoginDecoder.java.

Referenced by decodePayload().

◆ NEW_CONNECTION_OPCODE

final int com.runehive.net.codec.login.LoginDecoder.NEW_CONNECTION_OPCODE = 16
staticprivate

Definition at line 31 of file LoginDecoder.java.

Referenced by decodeConnectionType().

◆ RANDOM

final ThreadLocal<Random> com.runehive.net.codec.login.LoginDecoder.RANDOM = ThreadLocal.withInitial(SecureRandom::new)
staticprivate

Definition at line 36 of file LoginDecoder.java.

Referenced by decodeHandshake().

◆ RECONNECTION_OPCODE

final int com.runehive.net.codec.login.LoginDecoder.RECONNECTION_OPCODE = 18
staticprivate

Definition at line 32 of file LoginDecoder.java.

Referenced by decodeConnectionType().

◆ state

State com.runehive.net.codec.login.LoginDecoder.state = State.HANDSHAKE
private

Definition at line 38 of file LoginDecoder.java.

Referenced by decode(), and sendResponseCode().


The documentation for this class was generated from the following file: