View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.websocket.common.extensions.fragment;
20  
21  
22  import java.nio.ByteBuffer;
23  
24  import org.eclipse.jetty.websocket.api.WriteCallback;
25  import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
26  import org.eclipse.jetty.websocket.api.extensions.Frame;
27  import org.eclipse.jetty.websocket.common.OpCode;
28  import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
29  import org.eclipse.jetty.websocket.common.frames.DataFrame;
30  
31  /**
32   * Fragment Extension
33   */
34  public class FragmentExtension extends AbstractExtension
35  {
36      private int maxLength = -1;
37      
38      @Override
39      public String getName()
40      {
41          return "fragment";
42      }
43  
44      @Override
45      public void incomingError(Throwable e)
46      {
47          // Pass thru
48          nextIncomingError(e);
49      }
50  
51      @Override
52      public void incomingFrame(Frame frame)
53      {
54          // Pass thru
55          nextIncomingFrame(frame);
56      }
57  
58      @Override
59      public void outgoingFrame(Frame frame, WriteCallback callback)
60      {
61          if (OpCode.isControlFrame(frame.getOpCode()))
62          {
63              // Cannot fragment Control Frames
64              nextOutgoingFrame(frame,callback);
65              return;
66          }
67  
68          int length = frame.getPayloadLength();
69  
70          ByteBuffer payload = frame.getPayload().slice();
71          int originalLimit = payload.limit();
72          int currentPosition = payload.position();
73  
74          if (maxLength <= 0)
75          {
76              // output original frame
77              nextOutgoingFrame(frame,callback);
78              return;
79          }
80  
81          boolean continuation = false;
82  
83          // break apart payload based on maxLength rules
84          while (length > maxLength)
85          {
86              DataFrame frag = new DataFrame(frame,continuation);
87              frag.setFin(false); // always false here
88              payload.position(currentPosition);
89              payload.limit(Math.min(payload.position() + maxLength,originalLimit));
90              frag.setPayload(payload);
91  
92              // no callback for beginning and middle parts
93              nextOutgoingFrame(frag,null);
94  
95              length -= maxLength;
96              continuation = true;
97              currentPosition = payload.limit();
98          }
99  
100         // write remaining
101         DataFrame frag = new DataFrame(frame,continuation);
102         frag.setFin(frame.isFin()); // use original fin
103         payload.position(currentPosition);
104         payload.limit(originalLimit);
105         frag.setPayload(payload);
106 
107         nextOutgoingFrame(frag,callback);
108     }
109 
110     @Override
111     public void setConfig(ExtensionConfig config)
112     {
113         super.setConfig(config);
114 
115         maxLength = config.getParameter("maxLength",maxLength);
116     }
117 }