/* * Copyright 2013 The Skfiy Open Association. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.skfiy.typhon; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializeConfig; import java.nio.charset.StandardCharsets; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.handler.codec.embedder.DecoderEmbedder; import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder; import org.jboss.netty.handler.codec.frame.Delimiters; import org.jboss.netty.handler.logging.LoggingHandler; import org.skfiy.typhon.net.ProtocolHandler; import org.skfiy.typhon.net.NettyEndpointHandler; import org.skfiy.typhon.net.TestProtocolHandler; import org.skfiy.typhon.packet.Auth; import org.skfiy.typhon.packet.Namespaces; import org.skfiy.typhon.packet.Packet; import org.skfiy.typhon.session.AbstractSession; import org.testng.Assert; /** * * @author Kevin Zou <kevinz@skfiy.org> */ public class TestProtocolBase extends TestBase { private final static SerializeConfig SERIALIZE_CONFIG; static { SERIALIZE_CONFIG = new SerializeConfig(); SERIALIZE_CONFIG.setAsmEnable(false); } /** * * @param packet */ public final void offer(Packet packet) { String msg = JSON.toJSONString(packet, SERIALIZE_CONFIG); offer(packet.getNs(), msg); } /** * * @param ns * @param json */ public final void offer(String ns, JSON json) { offer(ns, json.toJSONString()); } /** * * @param ns * @param body */ public final void offer(String ns, String body) { byte[] b0 = ns.getBytes(StandardCharsets.UTF_8); byte[] b1 = body.getBytes(StandardCharsets.UTF_8); int l1 = b0.length + 1; int l2 = l1 + b1.length; byte[] buf = new byte[l2 + 1]; System.arraycopy(b0, 0, buf, 0, b0.length); // 命名空间与消息主体分隔符 buf[b0.length] = AbstractSession.NS_SEPARTOR; System.arraycopy(b1, 0, buf, l1, b1.length); buf[l2] = AbstractSession.MSG_SEPARTOR; // send offer(buf); } /** * * @return */ public final Response poll() { ChannelBuffer buf = (ChannelBuffer) getDecoderEmbedder().poll(); if (buf == null) { return null; } int eol = findEndOfLine(buf); ChannelBuffer frame = buf.factory().getBuffer(eol); frame.writeBytes(buf, buf.readerIndex(), eol); // 获取命名空间 byte[] nsBytes = new byte[frame.indexOf(0, 32, (byte) ':')]; frame.readBytes(nsBytes, 0, nsBytes.length); String ns = new String(nsBytes); // 跳过命名空间与消息的分隔符 frame.skipBytes(1); // 消息长度 byte[] dataBytes = new byte[frame.readableBytes()]; frame.readBytes(dataBytes, 0, dataBytes.length); return (new Response(ns, (JSONObject) JSON.parse(dataBytes))); } /** * Returns the index in the buffer of the end of line found. Returns -1 if no end of line was found in the buffer. */ private int findEndOfLine(final ChannelBuffer buffer) { final int n = buffer.writerIndex(); for (int i = buffer.readerIndex(); i < n; i++) { final byte b = buffer.getByte(i); if (b == '\n') { return i; } else if (b == '\r' && i < n - 1 && buffer.getByte(i + 1) == '\n') { return i; // \r\n } } return -1; // Not found. } /** * */ protected void auth() { String pid = generateId(); Auth auth = new Auth(); auth.setNs(Namespaces.AUTH); auth.setId(pid); auth.setUsername(TestConstants.USERNAME); auth.setPassword(TestConstants.PASSWORD); // 发送认证消息 offer(auth); // 认证成功响应 Response resp = poll(); boolean a = Namespaces.USER_INFO.equals(resp.getNs()) && pid.equals(resp.getData().getString("id")); Assert.assertTrue(a); } /** * */ protected void removalOverMessage() { offer("logout", "{}"); getDecoderEmbedder().pollAll(); testContext.removeAttribute("test.decoderEmbedder"); } /** * * @return */ protected String generateId() { return Integer.toHexString((int) (Math.random() * 1000)); } private void offer(byte[] bytes) { ChannelBuffer buf = ChannelBuffers.buffer(bytes.length); buf.writeBytes(bytes); getDecoderEmbedder().offer(buf); } protected DecoderEmbedder getDecoderEmbedder() { DecoderEmbedder embedder = (DecoderEmbedder) testContext.getAttribute("test.decoderEmbedder"); if (embedder != null) { return embedder; } NettyEndpointHandler handler = new NettyEndpointHandler(); ProtocolHandler protocolHandler = new TestProtocolHandler(); containerWapper.injectMembers(protocolHandler); ((Component) protocolHandler).init(); handler.setProtocolHandler(protocolHandler); embedder = new DecoderEmbedder( new DelimiterBasedFrameDecoder(65535, Delimiters.lineDelimiter()), new LoggingHandler(), handler); testContext.setAttribute("test.decoderEmbedder", embedder); return embedder; } }