1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.websocket;
20
21 import java.io.IOException;
22 import java.math.BigInteger;
23
24 import org.eclipse.jetty.io.Buffer;
25 import org.eclipse.jetty.io.EndPoint;
26 import org.eclipse.jetty.io.EofException;
27
28
29
30
31
32
33
34
35
36 public class WebSocketGeneratorD00 implements WebSocketGenerator
37 {
38 final private WebSocketBuffers _buffers;
39 final private EndPoint _endp;
40 private Buffer _buffer;
41
42 public WebSocketGeneratorD00(WebSocketBuffers buffers, EndPoint endp)
43 {
44 _buffers=buffers;
45 _endp=endp;
46 }
47
48 public synchronized void addFrame(byte flags, byte opcode,byte[] content, int offset, int length) throws IOException
49 {
50 long blockFor=_endp.getMaxIdleTime();
51
52 if (_buffer==null)
53 _buffer=_buffers.getDirectBuffer();
54
55 if (_buffer.space() == 0)
56 expelBuffer(blockFor);
57
58 bufferPut(opcode, blockFor);
59
60 if (isLengthFrame(opcode))
61 {
62
63
64
65
66
67
68
69 int lengthBytes = new BigInteger(String.valueOf(length)).bitLength() / 7 + 1;
70 for (int i = lengthBytes - 1; i > 0; --i)
71 {
72 byte lengthByte = (byte)(0x80 | (0x7F & (length >> 7 * i)));
73 bufferPut(lengthByte, blockFor);
74 }
75 bufferPut((byte)(0x7F & length), blockFor);
76 }
77
78 int remaining = length;
79 while (remaining > 0)
80 {
81 int chunk = remaining < _buffer.space() ? remaining : _buffer.space();
82 _buffer.put(content, offset + (length - remaining), chunk);
83 remaining -= chunk;
84 if (_buffer.space() > 0)
85 {
86 if (!isLengthFrame(opcode))
87 _buffer.put((byte)0xFF);
88
89 flushBuffer();
90 }
91 else
92 {
93
94 expelBuffer(blockFor);
95 if (remaining == 0)
96 {
97 if (!isLengthFrame(opcode))
98 _buffer.put((byte)0xFF);
99
100 flushBuffer();
101 }
102 }
103 }
104 }
105
106 private synchronized boolean isLengthFrame(byte frame)
107 {
108 return (frame & WebSocketConnectionD00.LENGTH_FRAME) == WebSocketConnectionD00.LENGTH_FRAME;
109 }
110
111 private synchronized void bufferPut(byte datum, long blockFor) throws IOException
112 {
113 if (_buffer==null)
114 _buffer=_buffers.getDirectBuffer();
115 _buffer.put(datum);
116 if (_buffer.space() == 0)
117 expelBuffer(blockFor);
118 }
119
120 public synchronized int flush(int blockFor) throws IOException
121 {
122 return expelBuffer(blockFor);
123 }
124
125 public synchronized int flush() throws IOException
126 {
127 int flushed = flushBuffer();
128 if (_buffer!=null && _buffer.length()==0)
129 {
130 _buffers.returnBuffer(_buffer);
131 _buffer=null;
132 }
133 return flushed;
134 }
135
136 private synchronized int flushBuffer() throws IOException
137 {
138 if (!_endp.isOpen())
139 throw new EofException();
140
141 if (_buffer!=null && _buffer.hasContent())
142 return _endp.flush(_buffer);
143
144 return 0;
145 }
146
147 private synchronized int expelBuffer(long blockFor) throws IOException
148 {
149 if (_buffer==null)
150 return 0;
151 int result = flushBuffer();
152 _buffer.compact();
153 if (!_endp.isBlocking())
154 {
155 while (_buffer.space()==0)
156 {
157 boolean ready = _endp.blockWritable(blockFor);
158 if (!ready)
159 throw new IOException("Write timeout");
160
161 result += flushBuffer();
162 _buffer.compact();
163 }
164 }
165 return result;
166 }
167
168 public synchronized boolean isBufferEmpty()
169 {
170 return _buffer==null || _buffer.length()==0;
171 }
172
173 }