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.Socks5InitialResponseDecoder.State;
26 import io.netty.util.internal.UnstableApi;
27
28 import java.util.List;
29
30
31
32
33
34
35
36 public class Socks5InitialResponseDecoder extends ReplayingDecoder<State> {
37
38 @UnstableApi
39 public enum State {
40 INIT,
41 SUCCESS,
42 FAILURE
43 }
44
45 public Socks5InitialResponseDecoder() {
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 Socks5AuthMethod authMethod = Socks5AuthMethod.valueOf(in.readByte());
61 out.add(new DefaultSocks5InitialResponse(authMethod));
62 checkpoint(State.SUCCESS);
63 }
64 case SUCCESS: {
65 int readableBytes = actualReadableBytes();
66 if (readableBytes > 0) {
67 out.add(in.readRetainedSlice(readableBytes));
68 }
69 break;
70 }
71 case FAILURE: {
72 in.skipBytes(actualReadableBytes());
73 break;
74 }
75 }
76 } catch (Exception e) {
77 fail(out, e);
78 }
79 }
80
81 private void fail(List<Object> out, Exception cause) {
82 if (!(cause instanceof DecoderException)) {
83 cause = new DecoderException(cause);
84 }
85
86 checkpoint(State.FAILURE);
87
88 Socks5Message m = new DefaultSocks5InitialResponse(Socks5AuthMethod.UNACCEPTED);
89 m.setDecoderResult(DecoderResult.failure(cause));
90 out.add(m);
91 }
92 }