1 /*
2 * Copyright 2012 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package org.jboss.netty.handler.codec.rtsp;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.channel.Channel;
20 import org.jboss.netty.channel.ChannelHandlerContext;
21 import org.jboss.netty.handler.codec.embedder.DecoderEmbedder;
22 import org.jboss.netty.handler.codec.frame.TooLongFrameException;
23 import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
24 import org.jboss.netty.handler.codec.http.HttpMessage;
25 import org.jboss.netty.handler.codec.http.HttpMessageDecoder;
26
27 /**
28 * Decodes {@link ChannelBuffer}s into RTSP messages represented in
29 * {@link HttpMessage}s.
30 * <p>
31 * <h3>Parameters that prevents excessive memory consumption</h3>
32 * <table border="1">
33 * <tr>
34 * <th>Name</th><th>Meaning</th>
35 * </tr>
36 * <tr>
37 * <td>{@code maxInitialLineLength}</td>
38 * <td>The maximum length of the initial line
39 * (e.g. {@code "SETUP / RTSP/1.0"} or {@code "RTSP/1.0 200 OK"})
40 * If the length of the initial line exceeds this value, a
41 * {@link TooLongFrameException} will be raised.</td>
42 * </tr>
43 * <tr>
44 * <td>{@code maxHeaderSize}</td>
45 * <td>The maximum length of all headers. If the sum of the length of each
46 * header exceeds this value, a {@link TooLongFrameException} will be raised.</td>
47 * </tr>
48 * <tr>
49 * <td>{@code maxContentLength}</td>
50 * <td>The maximum length of the content. If the content length exceeds this
51 * value, a {@link TooLongFrameException} will be raised.</td>
52 * </tr>
53 * </table>
54 * @apiviz.landmark
55 */
56 public abstract class RtspMessageDecoder extends HttpMessageDecoder {
57
58 private final DecoderEmbedder<HttpMessage> aggregator;
59
60 /**
61 * Creates a new instance with the default
62 * {@code maxInitialLineLength (4096}}, {@code maxHeaderSize (8192)}, and
63 * {@code maxContentLength (8192)}.
64 */
65 protected RtspMessageDecoder() {
66 this(4096, 8192, 8192);
67 }
68
69 /**
70 * Creates a new instance with the specified parameters.
71 */
72 protected RtspMessageDecoder(int maxInitialLineLength, int maxHeaderSize, int maxContentLength) {
73 super(maxInitialLineLength, maxHeaderSize, maxContentLength * 2);
74 aggregator = new DecoderEmbedder<HttpMessage>(new HttpChunkAggregator(maxContentLength));
75 }
76
77 @Override
78 protected Object decode(ChannelHandlerContext ctx, Channel channel,
79 ChannelBuffer buffer, State state) throws Exception {
80 Object o = super.decode(ctx, channel, buffer, state);
81 if (o != null && aggregator.offer(o)) {
82 return aggregator.poll();
83 } else {
84 return null;
85 }
86 }
87
88 @Override
89 protected boolean isContentAlwaysEmpty(HttpMessage msg) {
90 // Unlike HTTP, RTSP always assumes zero-length body if Content-Length
91 // header is absent.
92 boolean empty = super.isContentAlwaysEmpty(msg);
93 if (empty) {
94 return true;
95 }
96 if (!msg.containsHeader(RtspHeaders.Names.CONTENT_LENGTH)) {
97 return true;
98 }
99 return empty;
100 }
101 }