View Javadoc

1   package org.eclipse.jetty.websocket;
2   
3   import java.io.IOException;
4   import java.util.Map;
5   import java.util.zip.DataFormatException;
6   import java.util.zip.Deflater;
7   import java.util.zip.Inflater;
8   
9   import org.eclipse.jetty.io.Buffer;
10  import org.eclipse.jetty.io.ByteArrayBuffer;
11  import org.eclipse.jetty.util.log.Log;
12  
13  public class DeflateFrameExtension extends AbstractExtension
14  {
15      private int _minLength=8;
16      private Deflater _deflater;
17      private Inflater _inflater;
18      
19      public DeflateFrameExtension()
20      {
21          super("x-deflate-frame");
22      }
23  
24      @Override
25      public boolean init(Map<String, String> parameters)
26      {
27          if (!parameters.containsKey("minLength"))
28              parameters.put("minLength",Integer.toString(_minLength));
29          if(super.init(parameters))
30          {
31              _minLength=getInitParameter("minLength",_minLength);
32              
33              _deflater=new Deflater();
34              _inflater=new Inflater();
35              
36              return true;
37          }
38          return false;
39      }
40  
41      /* (non-Javadoc)
42       * @see org.eclipse.jetty.websocket.AbstractExtension#onFrame(byte, byte, org.eclipse.jetty.io.Buffer)
43       */
44      @Override
45      public void onFrame(byte flags, byte opcode, Buffer buffer)
46      {        
47          if (getConnection().isControl(opcode) || !isFlag(flags,1))
48          {
49              super.onFrame(flags,opcode,buffer);
50              return;
51          }
52  
53          if (buffer.array()==null)
54              buffer=buffer.asMutableBuffer();
55          
56          int length=0xff&buffer.get();
57          if (length>=0x7e)
58          {
59              int b=(length==0x7f)?8:2;
60              length=0;
61              while(b-->0)
62                  length=0x100*length+(0xff&buffer.get());
63          }    
64          
65          // TODO check a max framesize
66          
67          _inflater.setInput(buffer.array(),buffer.getIndex(),buffer.length());
68          ByteArrayBuffer buf = new ByteArrayBuffer(length);
69          try
70          {
71              while(_inflater.getRemaining()>0)
72              {
73                  int inflated=_inflater.inflate(buf.array(),buf.putIndex(),buf.space());
74                  if (inflated==0)
75                      throw new DataFormatException("insufficient data");
76                  buf.setPutIndex(buf.putIndex()+inflated);
77              }
78  
79              super.onFrame(clearFlag(flags,1),opcode,buf);
80          }
81          catch(DataFormatException e)
82          {
83              Log.warn(e);
84              getConnection().close(WebSocketConnectionD10.CLOSE_PROTOCOL,e.toString());
85          }
86      }
87  
88      /* (non-Javadoc)
89       * @see org.eclipse.jetty.websocket.AbstractExtension#addFrame(byte, byte, byte[], int, int)
90       */
91      @Override
92      public void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException
93      {
94          if (getConnection().isControl(opcode) || length<_minLength)
95          {
96              super.addFrame(clearFlag(flags,1),opcode,content,offset,length);
97              return;
98          }
99          
100         // prepare the uncompressed input
101         _deflater.reset();
102         _deflater.setInput(content,offset,length);
103         _deflater.finish();
104         
105         // prepare the output buffer
106         byte[] out= new byte[length];
107         int out_offset=0;
108 
109         // write the uncompressed length
110         if (length>0xffff)
111         {
112             out[out_offset++]=0x7f;
113             out[out_offset++]=(byte)((length>>56)&0x7f);
114             out[out_offset++]=(byte)((length>>48)&0xff);
115             out[out_offset++]=(byte)((length>>40)&0xff);
116             out[out_offset++]=(byte)((length>>32)&0xff);
117             out[out_offset++]=(byte)((length>>24)&0xff);
118             out[out_offset++]=(byte)((length>>16)&0xff);
119             out[out_offset++]=(byte)((length>>8)&0xff);
120             out[out_offset++]=(byte)(length&0xff);
121         }
122         else if (length >=0x7e)
123         {
124             out[out_offset++]=0x7e;
125             out[out_offset++]=(byte)(byte)(length>>8);
126             out[out_offset++]=(byte)(length&0xff);
127         }
128         else
129         {
130             out[out_offset++]=(byte)(length&0x7f);
131         }
132 
133         int l = _deflater.deflate(out,out_offset,length-out_offset);
134         
135         if (_deflater.finished())
136             super.addFrame(setFlag(flags,1),opcode,out,0,l+out_offset);
137         else
138             super.addFrame(clearFlag(flags,1),opcode,content,offset,length);
139     }
140 }