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.v5.Socks5PasswordAuthRequestDecoder.State;
25 import io.netty.util.CharsetUtil;
26 import io.netty.util.internal.UnstableApi;
27
28 import java.util.List;
29
30
31
32
33
34
35
36 public class Socks5PasswordAuthRequestDecoder extends ReplayingDecoder<State> {
37
38 @UnstableApi
39 public enum State {
40 INIT,
41 SUCCESS,
42 FAILURE
43 }
44
45 public Socks5PasswordAuthRequestDecoder() {
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 int startOffset = in.readerIndex();
55 final byte version = in.getByte(startOffset);
56 if (version != 1) {
57 throw new DecoderException("unsupported subnegotiation version: " + version + " (expected: 1)");
58 }
59
60 final int usernameLength = in.getUnsignedByte(startOffset + 1);
61 final int passwordLength = in.getUnsignedByte(startOffset + 2 + usernameLength);
62 final int totalLength = usernameLength + passwordLength + 3;
63
64 in.skipBytes(totalLength);
65 out.add(new DefaultSocks5PasswordAuthRequest(
66 in.toString(startOffset + 2, usernameLength, CharsetUtil.US_ASCII),
67 in.toString(startOffset + 3 + usernameLength, passwordLength, CharsetUtil.US_ASCII)));
68
69 checkpoint(State.SUCCESS);
70 }
71 case SUCCESS: {
72 int readableBytes = actualReadableBytes();
73 if (readableBytes > 0) {
74 out.add(in.readRetainedSlice(readableBytes));
75 }
76 break;
77 }
78 case FAILURE: {
79 in.skipBytes(actualReadableBytes());
80 break;
81 }
82 }
83 } catch (Exception e) {
84 fail(out, e);
85 }
86 }
87
88 private void fail(List<Object> out, Exception cause) {
89 if (!(cause instanceof DecoderException)) {
90 cause = new DecoderException(cause);
91 }
92
93 checkpoint(State.FAILURE);
94
95 Socks5Message m = new DefaultSocks5PasswordAuthRequest("", "");
96 m.setDecoderResult(DecoderResult.failure(cause));
97 out.add(m);
98 }
99 }