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