1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.mimo.netty.handler.codec.icap;
15
16 import org.jboss.netty.buffer.ChannelBuffer;
17
18
19
20
21
22
23
24
25
26 public class ReadChunkSizeState extends State<ReadChunkSizeState.DecisionState> {
27
28
29
30
31
32
33
34 public static enum DecisionState {
35 READ_CHUNK(StateEnum.READ_CHUNK_STATE),
36 READ_HUGE_CHUNK_IN_SMALER_CHUNKS(StateEnum.READ_CHUNKED_CONTENT_AS_CHUNKS_STATE),
37 READ_TRAILING_HEADERS(StateEnum.READ_TRAILING_HEADERS_STATE),
38 IS_LAST_PREVIEW_CHUNK(StateEnum.READ_CHUNK_SIZE_STATE),
39 IS_LAST_CHUNK(StateEnum.SKIP_CONTROL_CHARS),
40 RESET(null);
41
42 private StateEnum state;
43
44 DecisionState(StateEnum nextState) {
45 state = nextState;
46 }
47
48 public StateEnum getNextState() {
49 return state;
50 }
51 }
52
53 public ReadChunkSizeState(String name) {
54 super(name);
55 }
56
57 @Override
58 public void onEntry(ChannelBuffer buffer, IcapMessageDecoder icapMessageDecoder) throws DecodingException {
59 }
60
61 @Override
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 public StateReturnValue execute(ChannelBuffer buffer, IcapMessageDecoder icapMessageDecoder) throws DecodingException {
81 int chunkSize = 0;
82 String previewLine = IcapDecoderUtil.previewLine(buffer,icapMessageDecoder.maxInitialLineLength);
83 try {
84 chunkSize = IcapDecoderUtil.getChunkSize(previewLine);
85 IcapDecoderUtil.readLine(buffer,icapMessageDecoder.maxInitialLineLength);
86 } catch(DecodingException de) {
87 return StateReturnValue.createIrrelevantResultWithDecisionInformation(DecisionState.RESET);
88 }
89 icapMessageDecoder.currentChunkSize = chunkSize;
90 if(chunkSize > 0) {
91 if(chunkSize >= icapMessageDecoder.maxChunkSize) {
92 return StateReturnValue.createIrrelevantResultWithDecisionInformation(DecisionState.READ_HUGE_CHUNK_IN_SMALER_CHUNKS);
93 } else {
94 return StateReturnValue.createIrrelevantResultWithDecisionInformation(DecisionState.READ_CHUNK);
95 }
96 } else if(chunkSize == -1) {
97 icapMessageDecoder.currentChunkSize = 0;
98 IcapDecoderUtil.readLine(buffer,Integer.MAX_VALUE);
99 return StateReturnValue.createRelevantResultWithDecisionInformation(new DefaultIcapChunkTrailer(true,true),DecisionState.IS_LAST_PREVIEW_CHUNK);
100 } else if(chunkSize == 0) {
101 if(!checkForLineBreak(buffer)) {
102 return StateReturnValue.createIrrelevantResultWithDecisionInformation(DecisionState.READ_TRAILING_HEADERS);
103 }
104 IcapDecoderUtil.readLine(buffer,10);
105 if(icapMessageDecoder.message.isPreviewMessage()) {
106 return StateReturnValue.createRelevantResultWithDecisionInformation(new DefaultIcapChunkTrailer(true,false),DecisionState.IS_LAST_PREVIEW_CHUNK);
107 } else {
108 return StateReturnValue.createRelevantResultWithDecisionInformation(new DefaultIcapChunkTrailer(icapMessageDecoder.message.isPreviewMessage(),false),DecisionState.IS_LAST_CHUNK);
109 }
110 } else {
111 return StateReturnValue.createIrrelevantResultWithDecisionInformation(DecisionState.RESET);
112 }
113 }
114
115 @Override
116 public StateEnum onExit(ChannelBuffer buffer, IcapMessageDecoder icapMessageDecoder, DecisionState decisionInformation) throws DecodingException {
117 return decisionInformation.getNextState();
118 }
119
120 private boolean checkForLineBreak(ChannelBuffer buffer) {
121 byte previewByte = buffer.getByte(buffer.readerIndex() + 1);
122 return previewByte == IcapCodecUtil.CR | previewByte == IcapCodecUtil.LF;
123 }
124 }