1 package org.eclipse.jetty.websocket;
2
3 import java.io.IOException;
4
5 import org.eclipse.jetty.io.Buffer;
6 import org.eclipse.jetty.io.Connection;
7 import org.eclipse.jetty.io.EndPoint;
8 import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
9 import org.eclipse.jetty.util.log.Log;
10
11 public class WebSocketConnection implements Connection, WebSocket.Outbound
12 {
13 final IdleCheck _idle;
14 final EndPoint _endp;
15 final WebSocketParser _parser;
16 final WebSocketGenerator _generator;
17 final long _timestamp;
18 final WebSocket _websocket;
19 final int _maxIdleTimeMs=300000;
20
21 public WebSocketConnection(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, long maxIdleTime)
22 {
23 _endp = endpoint;
24 _timestamp = timestamp;
25 _websocket = websocket;
26 _generator = new WebSocketGenerator(buffers, _endp);
27 _parser = new WebSocketParser(buffers, endpoint, new WebSocketParser.EventHandler()
28 {
29 public void onFrame(byte frame, String data)
30 {
31 try
32 {
33 _websocket.onMessage(frame,data);
34 }
35 catch(ThreadDeath th)
36 {
37 throw th;
38 }
39 catch(Throwable th)
40 {
41 Log.warn(th);
42 }
43 }
44
45 public void onFrame(byte frame, Buffer buffer)
46 {
47 try
48 {
49 byte[] array=buffer.array();
50
51 _websocket.onMessage(frame,array,buffer.getIndex(),buffer.length());
52 }
53 catch(ThreadDeath th)
54 {
55 throw th;
56 }
57 catch(Throwable th)
58 {
59 Log.warn(th);
60 }
61 }
62 });
63
64 if (_endp instanceof SelectChannelEndPoint)
65 {
66 final SelectChannelEndPoint scep=(SelectChannelEndPoint)_endp;
67 scep.cancelIdle();
68 _idle=new IdleCheck()
69 {
70 public void access(EndPoint endp)
71 {
72 scep.getSelectSet().scheduleTimeout(scep.getTimeoutTask(),_maxIdleTimeMs);
73 }
74 };
75 scep.getSelectSet().scheduleTimeout(scep.getTimeoutTask(),_maxIdleTimeMs);
76 }
77 else
78 {
79 _idle = new IdleCheck()
80 {
81 public void access(EndPoint endp)
82 {}
83 };
84 }
85 }
86
87 public Connection handle() throws IOException
88 {
89 boolean more=true;
90
91 try
92 {
93 while (more)
94 {
95 int flushed=_generator.flush();
96 int filled=_parser.parseNext();
97
98 more = flushed>0 || filled>0 || !_parser.isBufferEmpty() || !_generator.isBufferEmpty();
99
100
101
102 if (filled<0 || flushed<0)
103 {
104 _endp.close();
105 break;
106 }
107
108 }
109 }
110 catch(IOException e)
111 {
112 e.printStackTrace();
113 throw e;
114 }
115 finally
116 {
117 if (_endp.isOpen())
118 _idle.access(_endp);
119 else
120
121 _websocket.onDisconnect();
122 }
123 return this;
124 }
125
126 public boolean isOpen()
127 {
128 return _endp!=null&&_endp.isOpen();
129 }
130
131 public boolean isIdle()
132 {
133 return _parser.isBufferEmpty() && _generator.isBufferEmpty();
134 }
135
136 public boolean isSuspended()
137 {
138 return false;
139 }
140
141 public long getTimeStamp()
142 {
143 return _timestamp;
144 }
145
146 public void sendMessage(String content) throws IOException
147 {
148 _generator.addFrame(WebSocket.SENTINEL_FRAME,content,_maxIdleTimeMs);
149 _generator.flush();
150 _idle.access(_endp);
151 }
152
153 public void sendMessage(byte frame, String content) throws IOException
154 {
155 _generator.addFrame(frame,content,_maxIdleTimeMs);
156 _generator.flush();
157 _idle.access(_endp);
158 }
159
160 public void sendMessage(byte frame, byte[] content) throws IOException
161 {
162 _generator.addFrame(frame,content,_maxIdleTimeMs);
163 _generator.flush();
164 _idle.access(_endp);
165 }
166
167 public void sendMessage(byte frame, byte[] content, int offset, int length) throws IOException
168 {
169 _generator.addFrame(frame,content,offset,length,_maxIdleTimeMs);
170 _generator.flush();
171 _idle.access(_endp);
172 }
173
174 public void disconnect()
175 {
176 try
177 {
178 _generator.flush(_maxIdleTimeMs);
179 _endp.close();
180 }
181 catch(IOException e)
182 {
183 Log.ignore(e);
184 }
185 }
186
187 public void fill(Buffer buffer)
188 {
189 _parser.fill(buffer);
190 }
191
192 private interface IdleCheck
193 {
194 void access(EndPoint endp);
195 }
196 }