ClientDataHandler.java
5.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package org.shadowsocks.handler.server;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.shadowsocks.crypto.SSCrypto;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
public class ClientDataHandler extends ChannelInboundHandlerAdapter {
private static Logger logger = LoggerFactory.getLogger(ClientDataHandler.class);
private final SSCrypto ssCrypto;
private final AtomicReference<Channel> remoteChannel = new AtomicReference<>();
private final ByteBuf clientCache;
public ClientDataHandler(String host, int port, ChannelHandlerContext clientCtx, ByteBuf clientCache, SSCrypto ssCrypto) {
this.ssCrypto = ssCrypto;
this.clientCache = clientCache;
init(host, port, clientCtx, clientCache, ssCrypto);
}
private void init(String host, int port, final ChannelHandlerContext clientCtx, final ByteBuf byteBuffer, final SSCrypto ssCrypto) {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(clientCtx.channel().eventLoop())
.channel(NioSocketChannel.class)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5 * 1000)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new RemoteDataHandler(clientCtx, ssCrypto, byteBuffer));
}
});
try {
ChannelFuture channelFuture = bootstrap.connect(InetAddress.getByName(host), port);
channelFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
logger.info("successfully to connect to {}:{}", host, port);
remoteChannel.set(future.channel());
} else {
logger.info("error to connect to {}:{}", host, port);
clientCtx.close();
}
}
});
} catch (Exception e) {
e.printStackTrace();
clientCtx.close();
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buff = (ByteBuf) msg;
if (buff.readableBytes() <= 0) {
return;
}
byte[] bytes = ByteBufUtil.getBytes(buff);
byte[] decrypt = ssCrypto.decrypt(bytes, bytes.length);
if(remoteChannel.get() == null) {
clientCache.writeBytes(decrypt);
} else {
remoteChannel.get().writeAndFlush(Unpooled.copiedBuffer(decrypt));
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ctx.close();
if(remoteChannel.get() != null){
remoteChannel.get().close();
}
}
public static class RemoteDataHandler extends SimpleChannelInboundHandler<ByteBuf> {
private final ChannelHandlerContext clientCtx;
private final SSCrypto ssCrypto;
private final ByteBuf byteBuffer;
public RemoteDataHandler(ChannelHandlerContext clientCtx, SSCrypto ssCrypto, ByteBuf byteBuffer) {
this.clientCtx = clientCtx;
this.ssCrypto = ssCrypto;
this.byteBuffer = byteBuffer;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// System.out.println("!!!!!!!!!!!!!!!!!!!!:"+new String(ByteBufUtil.getBytes(byteBuffer),StandardCharsets.UTF_8));
ctx.writeAndFlush(byteBuffer);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
byte[] bytes = ByteBufUtil.getBytes(msg);
try {
byte[] encrypt = ssCrypto.encrypt(bytes, bytes.length);
System.out.println(ctx.channel()+Arrays.toString(ssCrypto.getIV(true)));
System.out.println("++++++++++++++++:\n"+new String(bytes,StandardCharsets.UTF_8));
clientCtx.writeAndFlush(Unpooled.copiedBuffer(encrypt));
} catch (Exception e) {
ctx.close();
clientCtx.close();
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ctx.close();
clientCtx.close();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
clientCtx.close();
}
}
}