package com.cwa.msg;
import com.cwa.crypto.DigestUtil;
import com.cwa.crypto.RsaKeyHolder;
import com.cwa.crypto.RsaUtil;
import com.cwa.gamecore.action.ActionFactory;
import com.cwa.gamecore.io.ByteArrayGameInput;
import com.cwa.gamecore.io.ByteArrayGameOutput;
import com.cwa.gamecore.io.GameInput;
import com.cwa.gamecore.message.GameMessage;
import com.cwa.gamecore.message.GameRequest;
import com.cwa.gamecore.message.MessageFactory;
import com.cwa.gamecore.session.CatchResponseGameSession;
import com.cwa.gamecore.util.MessageUtil;
import com.cwa.msg.batch.BatchRequest;
import com.cwa.msg.batch.BatchResponse;
import com.cwa.msg.compression.GzipRequest;
import com.cwa.msg.encryption.RsaRequest;
import com.cwa.msg.mac.Md5Request;
import com.cwa.msg.sign.RsaSignedResponse;
import java.util.Arrays;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;
public class SmartActionDispatcherTest {
@BeforeClass
public static void init() throws Exception {
MessageFactory.getInstance().init(Arrays.asList("com.cwa.msg"));
ActionFactory.getInstance().init(Arrays.asList("com.cwa.msg"));
RsaKeyHolder.getInstance().loadKeyAndCert();
}
@Test
public void dispatchRsaAction() {
byte[] msgData = new byte[]{0x23, 0x24, 0, 6, 0, 100, 0, 0, 0, 7};
byte[] secureData = RsaUtil.encrypt(msgData, RsaKeyHolder.getInstance().getCertificate());
ByteArrayGameOutput out = new ByteArrayGameOutput();
out.putBytes(secureData);
GameInput in = new ByteArrayGameInput(out.toByteArray());
RsaRequest rsaMsg = new RsaRequest();
rsaMsg.decodeBody(in);
assertEquals(null, rsaMsg.getPlainRequest());
SmartActionDispatcher dispatcher = new SmartActionDispatcher();
dispatcher.setSecretProvider(new MockSecretProvider());
dispatcher.dispatchAction(new CatchResponseGameSession(), rsaMsg);
assertEquals(7, ((TestMessage) rsaMsg.getPlainRequest()).getId());
}
@Test
public void dispatchMacAction() {
byte[] msgData = new byte[] {0x23, 0x24, 0,6, 0,100, 0, 0, 0, 7};
byte[] msgMac = DigestUtil.md5(msgData);
ByteArrayGameOutput out = new ByteArrayGameOutput();
out.putBytes(msgData);
out.putBytes(msgMac);
ByteArrayGameInput in = new ByteArrayGameInput(out.toByteArray());
Md5Request macMsg = new Md5Request();
macMsg.decodeBody(in);
assertEquals(null, macMsg.getWrappedRequest());
assertTrue(Arrays.equals(msgMac, macMsg.getMsgMac()));
assertTrue(Arrays.equals(msgData, macMsg.getMsgData()));
SmartActionDispatcher dispatcher = new SmartActionDispatcher();
dispatcher.setSecretProvider(new MockSecretProvider());
dispatcher.dispatchAction(new CatchResponseGameSession(), macMsg);
assertEquals(7, ((TestMessage) macMsg.getWrappedRequest()).getId());
}
@Test
public void dispatchMacAction_fail() {
byte[] msgData = new byte[] {0x23, 0x24, 0,6, 0,100, 0, 0, 0, 7};
byte[] msgMac = DigestUtil.md5(msgData, "123".getBytes());
ByteArrayGameOutput out = new ByteArrayGameOutput();
out.putBytes(msgData);
out.putBytes(msgMac);
ByteArrayGameInput in = new ByteArrayGameInput(out.toByteArray());
Md5Request macMsg = new Md5Request();
macMsg.decodeBody(in);
assertEquals(null, macMsg.getWrappedRequest());
assertTrue(Arrays.equals(msgMac, macMsg.getMsgMac()));
assertTrue(Arrays.equals(msgData, macMsg.getMsgData()));
try {
SmartActionDispatcher dispatcher = new SmartActionDispatcher();
dispatcher.setSecretProvider(new MockSecretProvider());
dispatcher.dispatchAction(new CatchResponseGameSession(), macMsg);
fail("应该抛出异常!");
} catch (Exception expected) {
assertEquals("Message has been modified!", expected.getMessage());
}
}
@Test
public void dispatchSafeCommand() {
SmartActionDispatcher dispatcher = new SmartActionDispatcher();
dispatcher.setSecretProvider(new MockSecretProvider());
dispatcher.setSafeCommands(Arrays.asList(new TestMessage().getCommandId()));
dispatcher.dispatchAction(new CatchResponseGameSession(), new TestMessage());
}
@Test
public void dispatchSafeCommand2() {
SmartActionDispatcher dispatcher = new SmartActionDispatcher();
dispatcher.setSecretProvider(new MockSecretProvider());
dispatcher.setUnsafeCommands(Arrays.asList(-1));
dispatcher.dispatchAction(new CatchResponseGameSession(), new TestMessage());
}
@Test
public void dispatchUnsafeAction() {
try {
SmartActionDispatcher dispatcher = new SmartActionDispatcher();
dispatcher.setSecretProvider(new MockSecretProvider());
dispatcher.dispatchAction(new CatchResponseGameSession(), new TestMessage());
fail("应该抛出异常!");
} catch (Exception expected) {
assertEquals("Unsafe message", expected.getMessage().substring(0, 14));
}
}
@Test
public void signedResponse() {
TestMessage resp = new TestMessage();
resp.setId(369);
RsaSignedResponse signedResp = new RsaSignedResponse(resp);
byte[] bytes = MessageUtil.encode(signedResp);
ByteArrayGameInput input = new ByteArrayGameInput(bytes);
// header
assertEquals(0x23, input.get());
assertEquals(0x24, input.get());
assertEquals(144, input.getShort());
assertEquals(GameMessage.CMD_SIGNED_ACTION, input.getShort());
// 验证签名
byte[] respData = input.getBytes();
byte[] respSign = input.getBytes();
assertEquals(0, input.remaining());
assertTrue(RsaUtil.verify(respData, respSign, RsaKeyHolder.getInstance().getCertificate()));
TestMessage resp2 = (TestMessage) MessageUtil.decode(respData);
assertEquals(resp.getId(), resp2.getId());
}
@Test
public void dispatchAction_signResponse() {
SmartActionDispatcher dispatcher = new SmartActionDispatcher();
dispatcher.setSecretProvider(new MockSecretProvider());
dispatcher.setUnsafeCommands(Arrays.asList(-1));
dispatcher.setResponsesNeedToSign(Arrays.asList(new TestMessage().getCommandId()));
CatchResponseGameSession session = new CatchResponseGameSession();
TestMessage req = new TestMessage();
req.setId(123456);
dispatcher.dispatchAction(session, req);
assertNotNull(session.getResponse());
RsaSignedResponse signedResp = (RsaSignedResponse) session.getResponse();
TestMessage resp = (TestMessage) signedResp.getWrappedResponse();
assertEquals(req.getId(), resp.getId());
}
@Test
public void dispatchBatchAction() {
SmartActionDispatcher dispatcher = new SmartActionDispatcher();
dispatcher.setUnsafeCommands(Arrays.asList(-1));
BatchRequest req = new BatchRequest();
req.setRequests(new GameRequest[] {
new TestMessage(),
new TestMessage(),
new TestMessage()
});
CatchResponseGameSession session = new CatchResponseGameSession();
dispatcher.dispatchAction(session, req);
BatchResponse resp = (BatchResponse) session.getResponse();
assertEquals(3, resp.getResponses().length);
}
@Test
public void dispatchGzipAction() {
SmartActionDispatcher dispatcher = new SmartActionDispatcher();
dispatcher.setUnsafeCommands(Arrays.asList(-1));
GzipRequest req = new GzipRequest() {
@Override public GameRequest getWrappedRequest() {
TestMessage req = new TestMessage();
req.setId(987);
return req;
}
};
CatchResponseGameSession session = new CatchResponseGameSession();
dispatcher.dispatchAction(session, req);
TestMessage resp = (TestMessage) session.getResponse();
assertEquals(987, resp.getId());
}
}