package com.eactive.httpmockserver.socket; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.io.UnsupportedEncodingException; @Component @Sharable public class EchoSocketServerHandler extends ChannelInboundHandlerAdapter { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private BytesMessageSpec spec; public EchoSocketServerHandler() { } public EchoSocketServerHandler(BytesMessageSpec spec) { this.spec = spec; } @Override public void handlerAdded(ChannelHandlerContext ctx) { logger.info("EchoSocketServer handlerAdded"); } @Override public void channelActive(ChannelHandlerContext ctx) { logger.info("Remote Address: " + ctx.channel().remoteAddress().toString()); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { logger.info("EchoSocketServer channelRead"); try { spec.setEncode(StringUtils.defaultIfBlank(spec.getEncode(), "euc-kr")); String message = new String(ByteBufUtil.getBytes((ByteBuf) msg), spec.getEncode()); logger.info("=================================================="); logger.info("Received Message=" + message); logger.info("=================================================="); // length + content String responseMsg = assignResponseMessage(message); logger.info("=================================================="); logger.info("Response Message=" + responseMsg); logger.info("=================================================="); // sleep if (spec.getSleepSeconds() != null) { int sleepSeconds = spec.getSleepSeconds().intValue(); if (sleepSeconds > 0) { logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); logger.info("Start Sleep {} Seconds.", sleepSeconds); logger.info("..."); Thread.sleep(sleepSeconds * 1000l); logger.info("......"); logger.info("Finished Sleep {} Seconds.", sleepSeconds); logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); } } ctx.write(Unpooled.wrappedBuffer(responseMsg.getBytes(spec.getEncode()))); } catch (Exception e) { logger.error(e.getMessage()); } } private String assignResponseMessage(String body) throws UnsupportedEncodingException { int llFieldLength = (spec.getLlFieldLength() == null ? 8 : spec.getLlFieldLength().intValue()); if (StringUtils.isNotBlank(spec.getResponseBody())) { return appendLengthField(StringUtils.substring(spec.getResponseBody(), llFieldLength), spec); } if (spec.getEchoReplaceStringList() != null) { byte[] bytes = body.getBytes(spec.getEncode()); for (EchoReplaceString echoReplaceString : spec.getEchoReplaceStringList()) { bytes = replaceString(bytes, echoReplaceString.getPosition().intValue(), echoReplaceString.getReplaceString().getBytes(spec.getEncode()), llFieldLength); } body = new String(bytes, spec.getEncode()); } return appendLengthField(body, spec); } private byte[] replaceString(byte[] bytes, int position, byte[] replaceBytes, int llFieldLength) { int idx = position - llFieldLength; if (idx < 0 || bytes.length < idx) { logger.warn("//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**"); logger.warn("//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**"); logger.warn("invalid postion(MessageSize={}, postion={})", bytes.length + llFieldLength, position); return bytes; } if (bytes.length < idx + replaceBytes.length) { byte[] newBytes = new byte[idx + replaceBytes.length]; System.arraycopy(bytes, 0, newBytes, 0, idx); System.arraycopy(replaceBytes, 0, newBytes, idx, replaceBytes.length); return newBytes; } System.arraycopy(replaceBytes, 0, bytes, idx, replaceBytes.length); return bytes; } public static String appendLengthField(String body, BytesMessageSpec spec) throws UnsupportedEncodingException { int llFieldLength = (spec.getLlFieldLength() == null ? 8 : spec.getLlFieldLength().intValue()); int length = body.getBytes(spec.getEncode()).length; if (BooleanUtils.toBoolean(spec.getLlFieldLengthInclude())) { length += llFieldLength; } return String.format("%0" + llFieldLength + "d%s", length, body); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { logger.info("EchoSocketServer channelReadComplete"); ctx.flush(); } @Override public void handlerRemoved(ChannelHandlerContext ctx) { logger.info("EchoSocketServer handlerRemoved"); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.close(); cause.printStackTrace(); } }