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.ByteArrayOutputStream2;
12  import org.eclipse.jetty.util.log.Log;
13  
14  public class DeflateFrameExtension extends AbstractExtension
15  {
16      private int _minLength=64;
17      private Deflater _deflater;
18      private Inflater _inflater;
19      
20      public DeflateFrameExtension()
21      {
22          super("x-deflate-frame",0,0,1);
23      }
24  
25      @Override
26      public boolean init(Map<String, String> parameters)
27      {
28          if (!parameters.containsKey("minLength"))
29              parameters.put("minLength",Integer.toString(_minLength));
30          if(super.init(parameters))
31          {
32              _minLength=getInitParameter("minLength",_minLength);
33              
34              _deflater=new Deflater();
35              _inflater=new Inflater();
36              
37              return true;
38          }
39          return false;
40      }
41  
42      /* (non-Javadoc)
43       * @see org.eclipse.jetty.websocket.AbstractExtension#onFrame(byte, byte, org.eclipse.jetty.io.Buffer)
44       */
45      @Override
46      public void onFrame(byte flags, byte opcode, Buffer buffer)
47      {        
48          if (getConnection().isControl(opcode) || !isFlag(flags,0))
49          {
50              super.onFrame(flags,opcode,buffer);
51              return;
52          }
53          
54          if (buffer.array()==null)
55              buffer=buffer.asMutableBuffer();
56          
57          int length=0xff&buffer.get();
58          if (length>=0x7e)
59          {
60              int b=(length==0x7f)?8:2;
61              length=0;
62              while(b-->0)
63                  length=0x100*length+(0xff&buffer.get());
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,0),opcode,buf);
80          }
81          catch(DataFormatException e)
82          {
83              Log.warn(e);
84              getConnection().close(WebSocketConnectionD07.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,0),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,0),opcode,out,0,l+out_offset);
137         else
138             super.addFrame(clearFlag(flags,0),opcode,content,offset,length);
139     }
140 }