1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.handler.codec.socksx.v5;
18
19 import io.netty.buffer.ByteBuf;
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.SocksVersion;
25 import io.netty.handler.codec.socksx.v5.Socks5InitialRequestDecoder.State;
26 import io.netty.util.internal.UnstableApi;
27
28 import java.util.List;
29
30
31
32
33
34
35
36 public class Socks5InitialRequestDecoder extends ReplayingDecoder<State> {
37
38 @UnstableApi
39 public enum State {
40 INIT,
41 SUCCESS,
42 FAILURE
43 }
44
45 public Socks5InitialRequestDecoder() {
46 super(State.INIT);
47 }
48
49 @Override
50 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
51 try {
52 switch (state()) {
53 case INIT: {
54 final byte version = in.readByte();
55 if (version != SocksVersion.SOCKS5.byteValue()) {
56 throw new DecoderException(
57 "unsupported version: " + version + " (expected: " + SocksVersion.SOCKS5.byteValue() + ')');
58 }
59
60 final int authMethodCnt = in.readUnsignedByte();
61
62 final Socks5AuthMethod[] authMethods = new Socks5AuthMethod[authMethodCnt];
63 for (int i = 0; i < authMethodCnt; i++) {
64 authMethods[i] = Socks5AuthMethod.valueOf(in.readByte());
65 }
66
67 out.add(new DefaultSocks5InitialRequest(authMethods));
68 checkpoint(State.SUCCESS);
69 }
70 case SUCCESS: {
71 int readableBytes = actualReadableBytes();
72 if (readableBytes > 0) {
73 out.add(in.readRetainedSlice(readableBytes));
74 }
75 break;
76 }
77 case FAILURE: {
78 in.skipBytes(actualReadableBytes());
79 break;
80 }
81 }
82 } catch (Exception e) {
83 fail(out, e);
84 }
85 }
86
87 private void fail(List<Object> out, Exception cause) {
88 if (!(cause instanceof DecoderException)) {
89 cause = new DecoderException(cause);
90 }
91
92 checkpoint(State.FAILURE);
93
94 Socks5Message m = new DefaultSocks5InitialRequest(Socks5AuthMethod.NO_AUTH);
95 m.setDecoderResult(DecoderResult.failure(cause));
96 out.add(m);
97 }
98 }