TCP 대응답 기능 추가
This commit is contained in:
+2
-1
@@ -23,8 +23,9 @@ dependencies {
|
||||
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
|
||||
// implementation 'com.github.darrachequesne:spring-data-jpa-datatables:5.1.0'
|
||||
implementation 'org.apache.commons:commons-lang3:3.10'
|
||||
implementation group: 'commons-io', name: 'commons-io', version: '2.6'
|
||||
implementation 'commons-io:commons-io:2.6'
|
||||
implementation 'com.jayway.jsonpath:json-path:2.4.0'
|
||||
implementation 'io.netty:netty-all:4.1.60.Final'
|
||||
runtimeOnly 'com.h2database:h2'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package com.eactive.httpmockserver.socket;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.Lob;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Positive;
|
||||
import javax.validation.constraints.PositiveOrZero;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Entity
|
||||
public class BytesMessageSpec implements Serializable {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
@Column(length = 100, nullable = false)
|
||||
private String specName;
|
||||
|
||||
@Column(length = 1)
|
||||
private String llFieldInclude;
|
||||
|
||||
@Column(length = 1)
|
||||
private String llFieldLengthInclude;
|
||||
|
||||
@Positive
|
||||
private Integer llFieldLength;
|
||||
|
||||
private Integer llFieldLengthAlpha;
|
||||
|
||||
@PositiveOrZero
|
||||
private Integer llFieldOffset;
|
||||
|
||||
@Column(length = 20)
|
||||
private String llFieldType;
|
||||
|
||||
@Column(length = 20)
|
||||
private String encode;
|
||||
|
||||
@Positive
|
||||
private Integer port;
|
||||
|
||||
@Positive
|
||||
private Integer sleepSeconds;
|
||||
|
||||
@Column
|
||||
@Lob
|
||||
private String responseBody;
|
||||
|
||||
@Column(length = 1)
|
||||
private String useYn;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "BYTE_MESSAGE_SPEC_ID")
|
||||
@OrderBy("position")
|
||||
private List<EchoReplaceString> EchoReplaceStringList;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getSpecName() {
|
||||
return specName;
|
||||
}
|
||||
|
||||
public void setSpecName(String specName) {
|
||||
this.specName = specName;
|
||||
}
|
||||
|
||||
public String getLlFieldInclude() {
|
||||
return llFieldInclude;
|
||||
}
|
||||
|
||||
public void setLlFieldInclude(String llFieldInclude) {
|
||||
this.llFieldInclude = llFieldInclude;
|
||||
}
|
||||
|
||||
public String getLlFieldLengthInclude() {
|
||||
return llFieldLengthInclude;
|
||||
}
|
||||
|
||||
public void setLlFieldLengthInclude(String llFieldLengthInclude) {
|
||||
this.llFieldLengthInclude = llFieldLengthInclude;
|
||||
}
|
||||
|
||||
public Integer getLlFieldLength() {
|
||||
return llFieldLength;
|
||||
}
|
||||
|
||||
public void setLlFieldLength(Integer llFieldLength) {
|
||||
this.llFieldLength = llFieldLength;
|
||||
}
|
||||
|
||||
public Integer getLlFieldLengthAlpha() {
|
||||
return llFieldLengthAlpha;
|
||||
}
|
||||
|
||||
public void setLlFieldLengthAlpha(Integer llFieldLengthAlpha) {
|
||||
this.llFieldLengthAlpha = llFieldLengthAlpha;
|
||||
}
|
||||
|
||||
public Integer getLlFieldOffset() {
|
||||
return llFieldOffset;
|
||||
}
|
||||
|
||||
public void setLlFieldOffset(Integer llFieldOffset) {
|
||||
this.llFieldOffset = llFieldOffset;
|
||||
}
|
||||
|
||||
public String getLlFieldType() {
|
||||
return llFieldType;
|
||||
}
|
||||
|
||||
public void setLlFieldType(String llFieldType) {
|
||||
this.llFieldType = llFieldType;
|
||||
}
|
||||
|
||||
public String getEncode() {
|
||||
return encode;
|
||||
}
|
||||
|
||||
public void setEncode(String encode) {
|
||||
this.encode = encode;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public Integer getSleepSeconds() {
|
||||
return sleepSeconds;
|
||||
}
|
||||
|
||||
public void setSleepSeconds(Integer sleepSeconds) {
|
||||
this.sleepSeconds = sleepSeconds;
|
||||
}
|
||||
|
||||
public String getResponseBody() {
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
public void setResponseBody(String responseBody) {
|
||||
this.responseBody = responseBody;
|
||||
}
|
||||
|
||||
public String getUseYn() {
|
||||
return useYn;
|
||||
}
|
||||
|
||||
public void setUseYn(String useYn) {
|
||||
this.useYn = useYn;
|
||||
}
|
||||
|
||||
public List<EchoReplaceString> getEchoReplaceStringList() {
|
||||
return EchoReplaceStringList;
|
||||
}
|
||||
|
||||
public void setEchoReplaceStringList(List<EchoReplaceString> echoReplaceStringList) {
|
||||
EchoReplaceStringList = echoReplaceStringList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BytesMessageSpec [id=" + id + ", specName=" + specName + ", llFieldInclude=" + llFieldInclude
|
||||
+ ", llFieldLengthInclude=" + llFieldLengthInclude + ", llFieldLength=" + llFieldLength
|
||||
+ ", llFieldLengthAlpha=" + llFieldLengthAlpha + ", llFieldOffset=" + llFieldOffset + ", llFieldType="
|
||||
+ llFieldType + ", encode=" + encode + ", port=" + port + ", sleepSeconds=" + sleepSeconds
|
||||
+ ", responseBody=" + responseBody + ", useYn=" + useYn + ", EchoReplaceStringList="
|
||||
+ EchoReplaceStringList + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.eactive.httpmockserver.socket;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface BytesMessageSpecDao extends JpaRepository<BytesMessageSpec, Long> {
|
||||
BytesMessageSpec findFirstByUseYn(String useYn);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.eactive.httpmockserver.socket;
|
||||
|
||||
public interface BytesMessageSpecService {
|
||||
public BytesMessageSpec findActiveBytesMessageSpec();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.eactive.httpmockserver.socket;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public class BytesMessageSpecServiceImpl implements BytesMessageSpecService {
|
||||
@Autowired
|
||||
private BytesMessageSpecDao dao;
|
||||
|
||||
@Override
|
||||
public BytesMessageSpec findActiveBytesMessageSpec() {
|
||||
return dao.findFirstByUseYn("Y");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.eactive.httpmockserver.socket;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.PositiveOrZero;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Entity
|
||||
public class EchoReplaceString implements Serializable {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
@PositiveOrZero
|
||||
@Column(nullable = false)
|
||||
private Integer position;
|
||||
|
||||
@NotBlank
|
||||
@Column(length = 5000, nullable = false)
|
||||
private String replaceString;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(Integer position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public String getReplaceString() {
|
||||
return replaceString;
|
||||
}
|
||||
|
||||
public void setReplaceString(String replaceString) {
|
||||
this.replaceString = replaceString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EchoReplaceString [id=" + id + ", position=" + position + ", replaceString=" + replaceString + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,73 +1,84 @@
|
||||
//package com.eactive.httpmockserver.socket;
|
||||
//
|
||||
//import java.nio.ByteOrder;
|
||||
//
|
||||
//import javax.annotation.PreDestroy;
|
||||
//
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//
|
||||
//import io.netty.bootstrap.ServerBootstrap;
|
||||
//import io.netty.channel.Channel;
|
||||
//import io.netty.channel.ChannelFuture;
|
||||
//import io.netty.channel.ChannelInitializer;
|
||||
//import io.netty.channel.ChannelOption;
|
||||
//import io.netty.channel.ChannelPipeline;
|
||||
//import io.netty.channel.EventLoopGroup;
|
||||
//import io.netty.channel.nio.NioEventLoopGroup;
|
||||
//import io.netty.channel.socket.SocketChannel;
|
||||
//import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
//import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||
//import io.netty.handler.codec.LengthFieldPrepender;
|
||||
//import io.netty.handler.codec.string.StringDecoder;
|
||||
//import io.netty.util.CharsetUtil;
|
||||
//
|
||||
//@Component
|
||||
//public class EchoSocketServer {
|
||||
// private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
//
|
||||
// private Channel channel;
|
||||
//
|
||||
// public void start() {
|
||||
// EventLoopGroup bossGroup = new NioEventLoopGroup();
|
||||
// EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||
// try {
|
||||
// ServerBootstrap server = new ServerBootstrap();
|
||||
// // @formatter:off
|
||||
// server.group(bossGroup, workerGroup)
|
||||
// .channel(NioServerSocketChannel.class)
|
||||
// .childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
// @Override
|
||||
// protected void initChannel(SocketChannel ch) throws Exception {
|
||||
// ChannelPipeline pipeline = ch.pipeline();
|
||||
// //pipeline.addLast(new LengthFieldBasedFrameDecoder (ByteOrder.LITTLE_ENDIAN,Integer.MAX_VALUE,0,8,0,8,true));
|
||||
// //pipeline.addLast(new LengthFieldPrepender(8));
|
||||
// //pipeline.addLast(new LengthFieldBasedFrameDecoder (Integer.MAX_VALUE,0,8,0,8));
|
||||
// //pipeline.addLast(new LengthFieldBasedFrameDecoder (Integer.MAX_VALUE,0,2,0,2));
|
||||
// //pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
|
||||
// pipeline.addLast(new EchoSocketServerHandler());
|
||||
// }
|
||||
// })
|
||||
// .option(ChannelOption.SO_BACKLOG, 128)
|
||||
// .childOption(ChannelOption.SO_KEEPALIVE, false);
|
||||
// // @formatter:on
|
||||
//
|
||||
// ChannelFuture channelFuture = server.bind(28181).sync();
|
||||
// channel = channelFuture.channel().closeFuture().sync().channel();
|
||||
// } catch (Exception e) {
|
||||
// logger.error(e.getMessage());
|
||||
// } finally {
|
||||
// bossGroup.shutdownGracefully();
|
||||
// workerGroup.shutdownGracefully();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @PreDestroy
|
||||
// public void stop() {
|
||||
// if (channel != null) {
|
||||
// channel.close();
|
||||
// channel.parent().closeFuture();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
package com.eactive.httpmockserver.socket;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.persistence.NoResultException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
|
||||
@Component
|
||||
public class EchoSocketServer {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private BytesMessageSpec spec;
|
||||
|
||||
EventLoopGroup bossGroup;
|
||||
EventLoopGroup workerGroup;
|
||||
ChannelFuture channelFuture;
|
||||
|
||||
public EchoSocketServer() {
|
||||
}
|
||||
|
||||
public EchoSocketServer(BytesMessageSpec spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
public void start() throws Exception {
|
||||
if (spec == null) {
|
||||
throw new NoResultException();
|
||||
}
|
||||
|
||||
int port = (spec.getPort() == null ? 38181 : spec.getPort().intValue());
|
||||
bossGroup = new NioEventLoopGroup();
|
||||
workerGroup = new NioEventLoopGroup();
|
||||
try {
|
||||
ServerBootstrap server = new ServerBootstrap();
|
||||
// @formatter:off
|
||||
server.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
pipeline.addLast(new LengthHeaderFrameDecoder(spec));
|
||||
pipeline.addLast(new EchoSocketServerHandler(spec));
|
||||
}
|
||||
})
|
||||
.option(ChannelOption.SO_BACKLOG, 128)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, false);
|
||||
// @formatter:on
|
||||
|
||||
channelFuture = server.bind(port).sync();
|
||||
channelFuture.channel().closeFuture().sync().channel();
|
||||
logger.info(port + " port bounded");
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
throw e;
|
||||
} finally {
|
||||
bossGroup.shutdownGracefully();
|
||||
workerGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void stop() {
|
||||
try {
|
||||
bossGroup.shutdownGracefully().sync();
|
||||
workerGroup.shutdownGracefully().sync();
|
||||
channelFuture.channel().closeFuture().sync();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +1,144 @@
|
||||
//package com.eactive.httpmockserver.socket;
|
||||
//
|
||||
//import java.nio.charset.StandardCharsets;
|
||||
//
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//
|
||||
//import io.netty.buffer.ByteBuf;
|
||||
//import io.netty.channel.ChannelHandler.Sharable;
|
||||
//import io.netty.channel.ChannelHandlerContext;
|
||||
//import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
//
|
||||
//@Component
|
||||
//@Sharable
|
||||
//public class EchoSocketServerHandler extends ChannelInboundHandlerAdapter {
|
||||
// private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
//
|
||||
// private int DATA_LENGTH = 2048;
|
||||
// private ByteBuf buff;
|
||||
//
|
||||
// @Override
|
||||
// public void handlerAdded(ChannelHandlerContext ctx) {
|
||||
// logger.info("EchoSocketServer handlerAdded");
|
||||
// buff = ctx.alloc().buffer(DATA_LENGTH);
|
||||
// }
|
||||
//
|
||||
// @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");
|
||||
//// ByteBuf buf = (ByteBuf) msg;
|
||||
//// byte[] bytes = new byte[buf.readableBytes()];
|
||||
//// buf.readBytes(bytes);
|
||||
//// String data = new String(bytes, StandardCharsets.UTF_8);
|
||||
//
|
||||
//// ByteBuf mBuf = (ByteBuf) msg;
|
||||
//// buff.writeBytes(mBuf); // 클라이언트에서 보내는 데이터가 축적됨
|
||||
//// mBuf.release();
|
||||
////
|
||||
//// //final ChannelFuture f = ctx.writeAndFlush(buff);
|
||||
////
|
||||
//// System.out.println("TcpServer: " + buff.toString());
|
||||
//// ctx.writeAndFlush(buff);
|
||||
//
|
||||
// String message = ((ByteBuf) msg).toString();
|
||||
// System.out.println("message=" + message);
|
||||
// ctx.write(msg);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
|
||||
// logger.info("EchoSocketServer channelReadComplete");
|
||||
// ctx.flush();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void handlerRemoved(ChannelHandlerContext ctx) {
|
||||
// logger.info("EchoSocketServer handlerRemoved");
|
||||
// buff = null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
// ctx.close();
|
||||
// cause.printStackTrace();
|
||||
// }
|
||||
//}
|
||||
package com.eactive.httpmockserver.socket;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
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 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;
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.eactive.httpmockserver.socket;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ReplayingDecoder;
|
||||
|
||||
public class LengthHeaderFrameDecoder extends ReplayingDecoder<Void> {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private boolean readLength;
|
||||
private int length;
|
||||
private BytesMessageSpec spec;
|
||||
|
||||
public LengthHeaderFrameDecoder() {
|
||||
}
|
||||
|
||||
public LengthHeaderFrameDecoder(BytesMessageSpec spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> out) throws Exception {
|
||||
int llFieldLength = (spec.getLlFieldLength() == null ? 8 : spec.getLlFieldLength().intValue());
|
||||
|
||||
if (!readLength) {
|
||||
ByteBuf lengthFrame = buf.readBytes(llFieldLength);
|
||||
length = assignMessageLength(ByteBufUtil.getBytes(lengthFrame));
|
||||
readLength = true;
|
||||
logger.info("MessageLength = " + length);
|
||||
checkpoint();
|
||||
}
|
||||
|
||||
if (readLength) {
|
||||
int contentLength = (BooleanUtils.toBoolean(spec.getLlFieldLengthInclude()) ? length - llFieldLength
|
||||
: length);
|
||||
ByteBuf frame = buf.readBytes(contentLength);
|
||||
readLength = false;
|
||||
checkpoint();
|
||||
out.add(frame);
|
||||
}
|
||||
}
|
||||
|
||||
private int assignMessageLength(byte[] bytes) {
|
||||
String lengthStr = new String(bytes);
|
||||
return NumberUtils.toInt(lengthStr);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,69 @@
|
||||
//package com.eactive.httpmockserver.socket;
|
||||
//
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.stereotype.Controller;
|
||||
//import org.springframework.web.bind.annotation.RequestMapping;
|
||||
//import org.springframework.web.bind.annotation.ResponseBody;
|
||||
//
|
||||
//@Controller
|
||||
//public class SocketServerManageController {
|
||||
// private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
//
|
||||
// @Autowired
|
||||
// private EchoSocketServer echoSocketServer;
|
||||
//
|
||||
// @RequestMapping("/manage/socket/startEchoSocketServer")
|
||||
// @ResponseBody
|
||||
// public String startEchoServer() {
|
||||
// logger.info("starting..");
|
||||
//
|
||||
// new Thread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// try {
|
||||
// echoSocketServer.start();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// }).start();
|
||||
//
|
||||
// logger.info("started");
|
||||
// return "Success";
|
||||
// }
|
||||
//
|
||||
// @RequestMapping("/manage/socket/stopEchoSocketServer")
|
||||
// @ResponseBody
|
||||
// public String stopEchoServer() {
|
||||
// logger.info("stopping..");
|
||||
// echoSocketServer.stop();
|
||||
// logger.info("stopped");
|
||||
// return "Success";
|
||||
// }
|
||||
//}
|
||||
package com.eactive.httpmockserver.socket;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.persistence.NoResultException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@Controller
|
||||
public class SocketServerManageController {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private BytesMessageSpecService specService;
|
||||
|
||||
private EchoSocketServer echoSocketServer;
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
logger.info("EchoSocketServer starting..");
|
||||
|
||||
BytesMessageSpec spec = specService.findActiveBytesMessageSpec();
|
||||
if (spec == null) {
|
||||
logger.info("EchoSocketServer not started(No have rule)");
|
||||
return;
|
||||
}
|
||||
logger.info("BytesMessageSpec=" + spec.toString());
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
echoSocketServer = new EchoSocketServer(spec);
|
||||
echoSocketServer.start();
|
||||
logger.info("EchoSocketServer started");
|
||||
} catch (NoResultException e) {
|
||||
logger.info("EchoSocketServer not started(No have rule)");
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void stop() {
|
||||
logger.info("EchoSocketServer stopping..");
|
||||
|
||||
if (echoSocketServer != null) {
|
||||
echoSocketServer.stop();
|
||||
}
|
||||
|
||||
logger.info("EchoSocketServer stopped");
|
||||
}
|
||||
|
||||
@RequestMapping("/manage/socket/restartEchoSocketServer")
|
||||
@ResponseBody
|
||||
public String restartEchoServer() {
|
||||
stop();
|
||||
start();
|
||||
|
||||
return "Success";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user