1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.websocket.common.events;
20
21 import java.io.IOException;
22 import java.nio.ByteBuffer;
23
24 import org.eclipse.jetty.util.BufferUtil;
25 import org.eclipse.jetty.util.StringUtil;
26 import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
29 import org.eclipse.jetty.websocket.api.CloseException;
30 import org.eclipse.jetty.websocket.api.StatusCode;
31 import org.eclipse.jetty.websocket.api.WebSocketException;
32 import org.eclipse.jetty.websocket.api.WebSocketPolicy;
33 import org.eclipse.jetty.websocket.api.extensions.Frame;
34 import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
35 import org.eclipse.jetty.websocket.common.CloseInfo;
36 import org.eclipse.jetty.websocket.common.OpCode;
37 import org.eclipse.jetty.websocket.common.WebSocketFrame;
38 import org.eclipse.jetty.websocket.common.WebSocketSession;
39
40
41
42
43 public abstract class EventDriver implements IncomingFrames
44 {
45 private static final Logger LOG = Log.getLogger(EventDriver.class);
46 protected final WebSocketPolicy policy;
47 protected final Object websocket;
48 protected WebSocketSession session;
49
50 public EventDriver(WebSocketPolicy policy, Object websocket)
51 {
52 this.policy = policy;
53 this.websocket = websocket;
54 }
55
56 public WebSocketPolicy getPolicy()
57 {
58 return policy;
59 }
60
61 public WebSocketSession getSession()
62 {
63 return session;
64 }
65
66 @Override
67 public final void incomingError(WebSocketException e)
68 {
69 if (LOG.isDebugEnabled())
70 {
71 LOG.debug("incoming(WebSocketException)",e);
72 }
73
74 if (e instanceof CloseException)
75 {
76 CloseException close = (CloseException)e;
77 terminateConnection(close.getStatusCode(),close.getMessage());
78 }
79
80 onError(e);
81 }
82
83 @Override
84 public void incomingFrame(Frame frame)
85 {
86 if (LOG.isDebugEnabled())
87 {
88 LOG.debug("{}.onFrame({})",websocket.getClass().getSimpleName(),frame);
89 }
90
91 onFrame(frame);
92
93 try
94 {
95 switch (frame.getType().getOpCode())
96 {
97 case OpCode.CLOSE:
98 {
99 boolean validate = true;
100 CloseInfo close = new CloseInfo(frame,validate);
101
102
103 onClose(close);
104
105
106 session.getConnection().getIOState().onCloseRemote(close);
107
108 return;
109 }
110 case OpCode.PING:
111 {
112 byte pongBuf[] = new byte[0];
113 if (frame.hasPayload())
114 {
115 pongBuf = BufferUtil.toArray(frame.getPayload());
116 }
117 session.getRemote().sendPong(ByteBuffer.wrap(pongBuf));
118 break;
119 }
120 case OpCode.BINARY:
121 {
122 onBinaryFrame(frame.getPayload(),frame.isFin());
123 return;
124 }
125 case OpCode.TEXT:
126 {
127 onTextFrame(frame.getPayload(),frame.isFin());
128 return;
129 }
130 }
131 }
132 catch (NotUtf8Exception e)
133 {
134 terminateConnection(StatusCode.BAD_PAYLOAD,e.getMessage());
135 }
136 catch (CloseException e)
137 {
138 terminateConnection(e.getStatusCode(),e.getMessage());
139 }
140 catch (Throwable t)
141 {
142 unhandled(t);
143 }
144 }
145
146 public abstract void onBinaryFrame(ByteBuffer buffer, boolean fin) throws IOException;
147
148 public abstract void onBinaryMessage(byte[] data);
149
150 public abstract void onClose(CloseInfo close);
151
152 public abstract void onConnect();
153
154 public abstract void onError(Throwable t);
155
156 public abstract void onFrame(Frame frame);
157
158 public abstract void onTextFrame(ByteBuffer buffer, boolean fin) throws IOException;
159
160 public abstract void onTextMessage(String message);
161
162 public void openSession(WebSocketSession session)
163 {
164 LOG.debug("openSession({})",session);
165 this.session = session;
166 try
167 {
168 this.onConnect();
169 }
170 catch (Throwable t)
171 {
172 unhandled(t);
173 }
174 }
175
176 protected void terminateConnection(int statusCode, String rawreason)
177 {
178 String reason = rawreason;
179 reason = StringUtil.truncate(reason,(WebSocketFrame.MAX_CONTROL_PAYLOAD - 2));
180 LOG.debug("terminateConnection({},{})",statusCode,rawreason);
181 session.close(statusCode,reason);
182 }
183
184 private void unhandled(Throwable t)
185 {
186 LOG.warn("Unhandled Error (closing connection)",t);
187 onError(t);
188
189
190 switch (policy.getBehavior())
191 {
192 case SERVER:
193 terminateConnection(StatusCode.SERVER_ERROR,t.getClass().getSimpleName());
194 break;
195 case CLIENT:
196 terminateConnection(StatusCode.POLICY_VIOLATION,t.getClass().getSimpleName());
197 break;
198 }
199 }
200 }