1 package org.eclipse.jetty.websocket;
2
3 import java.io.IOException;
4 import java.util.concurrent.ConcurrentLinkedQueue;
5
6 import javax.servlet.http.HttpServletRequest;
7
8 import org.eclipse.jetty.server.Server;
9 import org.eclipse.jetty.server.handler.ResourceHandler;
10 import org.eclipse.jetty.server.nio.SelectChannelConnector;
11 import org.eclipse.jetty.util.StringUtil;
12 import org.eclipse.jetty.util.TypeUtil;
13 import org.eclipse.jetty.util.log.Log;
14
15 public class TestServer extends Server
16 {
17 boolean _verbose;
18
19 WebSocket _websocket;
20 SelectChannelConnector _connector;
21 WebSocketHandler _wsHandler;
22 ResourceHandler _rHandler;
23 ConcurrentLinkedQueue<TestWebSocket> _broadcast = new ConcurrentLinkedQueue<TestWebSocket>();
24
25 public TestServer(int port)
26 {
27 _connector = new SelectChannelConnector();
28 _connector.setPort(port);
29
30 addConnector(_connector);
31 _wsHandler = new WebSocketHandler()
32 {
33 public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol)
34 {
35 if ("org.ietf.websocket.test-echo".equals(protocol) || "echo".equals(protocol) || "lws-mirror-protocol".equals(protocol))
36 {
37 _websocket = new TestEchoWebSocket();
38 }
39 else if ("org.ietf.websocket.test-echo-broadcast".equals(protocol))
40 {
41 _websocket = new TestEchoBroadcastWebSocket();
42
43 }
44 else if ("org.ietf.websocket.test-echo-assemble".equals(protocol))
45 {
46 _websocket = new TestEchoAssembleWebSocket();
47 }
48 else if ("org.ietf.websocket.test-echo-fragment".equals(protocol))
49 {
50 _websocket = new TestEchoFragmentWebSocket();
51 }
52 else if (protocol==null)
53 {
54 _websocket = new TestWebSocket();
55 }
56 return _websocket;
57 }
58 };
59
60 setHandler(_wsHandler);
61
62 _rHandler=new ResourceHandler();
63 _rHandler.setDirectoriesListed(true);
64 _rHandler.setResourceBase("src/test/webapp");
65 _wsHandler.setHandler(_rHandler);
66
67 }
68
69
70 public boolean isVerbose()
71 {
72 return _verbose;
73 }
74
75
76 public void setVerbose(boolean verbose)
77 {
78 _verbose = verbose;
79 }
80
81
82 public void setResourceBase(String dir)
83 {
84 _rHandler.setResourceBase(dir);
85 }
86
87
88 public String getResourceBase()
89 {
90 return _rHandler.getResourceBase();
91 }
92
93
94
95 class TestWebSocket implements WebSocket, WebSocket.OnFrame, WebSocket.OnBinaryMessage, WebSocket.OnTextMessage, WebSocket.OnControl
96 {
97 protected FrameConnection _connection;
98
99 public FrameConnection getConnection()
100 {
101 return _connection;
102 }
103
104 public void onOpen(Connection connection)
105 {
106 if (_verbose)
107 System.err.printf("%s#onOpen %s\n",this.getClass().getSimpleName(),connection);
108 }
109
110 public void onHandshake(FrameConnection connection)
111 {
112 if (_verbose)
113 System.err.printf("%s#onHandshake %s %s\n",this.getClass().getSimpleName(),connection,connection.getClass().getSimpleName());
114 _connection = connection;
115 }
116
117 public void onClose(int code,String message)
118 {
119 if (_verbose)
120 System.err.printf("%s#onDisonnect %d %s\n",this.getClass().getSimpleName(),code,message);
121 }
122
123 public boolean onFrame(byte flags, byte opcode, byte[] data, int offset, int length)
124 {
125 if (_verbose)
126 System.err.printf("%s#onFrame %s|%s %s\n",this.getClass().getSimpleName(),TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),TypeUtil.toHexString(data,offset,length));
127 return false;
128 }
129
130 public boolean onControl(byte controlCode, byte[] data, int offset, int length)
131 {
132 if (_verbose)
133 System.err.printf("%s#onControl %s %s\n",this.getClass().getSimpleName(),TypeUtil.toHexString(controlCode),TypeUtil.toHexString(data,offset,length));
134 return false;
135 }
136
137 public void onMessage(String data)
138 {
139 if (_verbose)
140 System.err.printf("%s#onMessage %s\n",this.getClass().getSimpleName(),data);
141 }
142
143 public void onMessage(byte[] data, int offset, int length)
144 {
145 if (_verbose)
146 System.err.printf("%s#onMessage %s\n",this.getClass().getSimpleName(),TypeUtil.toHexString(data,offset,length));
147 }
148 }
149
150
151
152 class TestEchoWebSocket extends TestWebSocket
153 {
154 @Override
155 public void onOpen(Connection connection)
156 {
157 super.onOpen(connection);
158 connection.setMaxTextMessageSize(-1);
159 connection.setMaxBinaryMessageSize(-1);
160 }
161
162 @Override
163 public boolean onFrame(byte flags, byte opcode, byte[] data, int offset, int length)
164 {
165 super.onFrame(flags,opcode,data,offset,length);
166 try
167 {
168 if (!getConnection().isControl(opcode))
169 getConnection().sendFrame(flags,opcode,data,offset,length); }
170 catch (IOException e)
171 {
172 e.printStackTrace();
173 }
174
175 return false;
176 }
177 }
178
179
180
181 class TestEchoBroadcastWebSocket extends TestWebSocket
182 {
183 @Override
184 public void onOpen(Connection connection)
185 {
186 super.onOpen(connection);
187 _broadcast.add(this);
188 }
189
190 @Override
191 public void onClose(int code,String message)
192 {
193 super.onClose(code,message);
194 _broadcast.remove(this);
195 }
196
197 @Override
198 public void onMessage(byte[] data, int offset, int length)
199 {
200 super.onMessage(data,offset,length);
201 for (TestWebSocket ws : _broadcast)
202 {
203 try
204 {
205 ws.getConnection().sendMessage(data,offset,length);
206 }
207 catch (IOException e)
208 {
209 _broadcast.remove(ws);
210 e.printStackTrace();
211 }
212 }
213 }
214
215 @Override
216 public void onMessage(final String data)
217 {
218 super.onMessage(data);
219 for (TestWebSocket ws : _broadcast)
220 {
221 try
222 {
223 ws.getConnection().sendMessage(data);
224 }
225 catch (IOException e)
226 {
227 _broadcast.remove(ws);
228 e.printStackTrace();
229 }
230 }
231 }
232 }
233
234
235
236 class TestEchoAssembleWebSocket extends TestWebSocket
237 {
238
239 @Override
240 public void onOpen(Connection connection)
241 {
242 super.onOpen(connection);
243 connection.setMaxTextMessageSize(64*1024);
244 connection.setMaxBinaryMessageSize(64*1024);
245 }
246
247 @Override
248 public void onMessage(byte[] data, int offset, int length)
249 {
250 super.onMessage(data,offset,length);
251 try
252 {
253 getConnection().sendMessage(data,offset,length);
254 }
255 catch (IOException e)
256 {
257 e.printStackTrace();
258 }
259 }
260
261 @Override
262 public void onMessage(final String data)
263 {
264 super.onMessage(data);
265 try
266 {
267 getConnection().sendMessage(data);
268 }
269 catch (IOException e)
270 {
271 e.printStackTrace();
272 }
273 }
274 }
275
276
277
278 class TestEchoFragmentWebSocket extends TestWebSocket
279 {
280 @Override
281 public void onOpen(Connection connection)
282 {
283 super.onOpen(connection);
284 connection.setMaxTextMessageSize(64*1024);
285 connection.setMaxBinaryMessageSize(64*1024);
286 }
287
288 @Override
289 public void onMessage(byte[] data, int offset, int length)
290 {
291 super.onMessage(data,offset,length);
292 try
293 {
294 getConnection().sendFrame((byte)0x0,getConnection().binaryOpcode(),data,offset,length/2);
295 getConnection().sendFrame((byte)0x8,getConnection().binaryOpcode(),data,offset+length/2,length-length/2);
296 }
297 catch (IOException e)
298 {
299 e.printStackTrace();
300 }
301 }
302
303 @Override
304 public void onMessage(final String message)
305 {
306 super.onMessage(message);
307 try
308 {
309 byte[] data = message.getBytes(StringUtil.__UTF8);
310 int offset=0;
311 int length=data.length;
312 getConnection().sendFrame((byte)0x0,getConnection().textOpcode(),data,offset,length/2);
313 getConnection().sendFrame((byte)0x8,getConnection().textOpcode(),data,offset+length/2,length-length/2);
314 }
315 catch (IOException e)
316 {
317 e.printStackTrace();
318 }
319 }
320 }
321
322 private static void usage()
323 {
324 System.err.println("java -cp CLASSPATH "+TestServer.class+" [ OPTIONS ]");
325 System.err.println(" -p|--port PORT (default 8080)");
326 System.err.println(" -v|--verbose ");
327 System.err.println(" -d|--docroot file (default 'src/test/webapp')");
328 System.exit(1);
329 }
330
331 public static void main(String... args)
332 {
333 try
334 {
335 int port=8080;
336 boolean verbose=false;
337 String docroot="src/test/webapp";
338
339 for (int i=0;i<args.length;i++)
340 {
341 String a=args[i];
342 if ("-p".equals(a)||"--port".equals(a))
343 port=Integer.parseInt(args[++i]);
344 else if ("-v".equals(a)||"--verbose".equals(a))
345 verbose=true;
346 else if ("-d".equals(a)||"--docroot".equals(a))
347 docroot=args[++i];
348 else if (a.startsWith("-"))
349 usage();
350 }
351
352
353 TestServer server = new TestServer(port);
354 server.setVerbose(verbose);
355 server.setResourceBase(docroot);
356 server.start();
357 server.join();
358 }
359 catch (Exception e)
360 {
361 Log.warn(e);
362 }
363 }
364
365
366 }