View Javadoc

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                 // System.err.println("flushed="+flushed+" filled="+filled+" more="+more+" p.e="+_parser.isBufferEmpty()+" g.e="+_generator.isBufferEmpty());
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                 // TODO - not really the best way
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 }