1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.socksx.v4;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.ByteBufUtil;
20 import io.netty.channel.ChannelHandlerContext;
21 import io.netty.handler.codec.DecoderException;
22 import io.netty.handler.codec.DecoderResult;
23 import io.netty.handler.codec.ReplayingDecoder;
24 import io.netty.handler.codec.socksx.v4.Socks4ClientDecoder.State;
25 import io.netty.util.NetUtil;
26 import io.netty.util.internal.UnstableApi;
27
28 import java.util.List;
29
30
31
32
33
34
35
36 public class Socks4ClientDecoder extends ReplayingDecoder<State> {
37
38 @UnstableApi
39 public enum State {
40 START,
41 SUCCESS,
42 FAILURE
43 }
44
45 public Socks4ClientDecoder() {
46 super(State.START);
47 setSingleDecode(true);
48 }
49
50 @Override
51 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
52 try {
53 switch (state()) {
54 case START: {
55 final int version = in.readUnsignedByte();
56 if (version != 0) {
57 throw new DecoderException("unsupported reply version: " + version + " (expected: 0)");
58 }
59
60 final Socks4CommandStatus status = Socks4CommandStatus.valueOf(in.readByte());
61 final int dstPort = ByteBufUtil.readUnsignedShortBE(in);
62 final String dstAddr = NetUtil.intToIpAddress(ByteBufUtil.readIntBE(in));
63
64 out.add(new DefaultSocks4CommandResponse(status, dstAddr, dstPort));
65 checkpoint(State.SUCCESS);
66 }
67 case SUCCESS: {
68 int readableBytes = actualReadableBytes();
69 if (readableBytes > 0) {
70 out.add(in.readRetainedSlice(readableBytes));
71 }
72 break;
73 }
74 case FAILURE: {
75 in.skipBytes(actualReadableBytes());
76 break;
77 }
78 }
79 } catch (Exception e) {
80 fail(out, e);
81 }
82 }
83
84 private void fail(List<Object> out, Exception cause) {
85 if (!(cause instanceof DecoderException)) {
86 cause = new DecoderException(cause);
87 }
88
89 Socks4CommandResponse m = new DefaultSocks4CommandResponse(Socks4CommandStatus.REJECTED_OR_FAILED);
90 m.setDecoderResult(DecoderResult.failure(cause));
91 out.add(m);
92
93 checkpoint(State.FAILURE);
94 }
95 }