/src/main/java/org/nodex/java/core/http/Websocket.java

https://github.com/gautric/node.x · Java · 179 lines · 72 code · 22 blank · 85 comment · 6 complexity · c8b023bfd1ace9259af6057b05766908 MD5 · raw file

  1. /*
  2. * Copyright 2011 VMware, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.nodex.java.core.http;
  17. import org.jboss.netty.handler.codec.http.websocket.DefaultWebSocketFrame;
  18. import org.jboss.netty.handler.codec.http.websocket.WebSocketFrame;
  19. import org.nodex.java.core.Handler;
  20. import org.nodex.java.core.buffer.Buffer;
  21. import org.nodex.java.core.streams.ReadStream;
  22. import org.nodex.java.core.streams.WriteStream;
  23. /**
  24. * <p>Encapsulation of an HTML 5 Websocket</p>
  25. *
  26. * <p>Instances of this class are either created by an {@link HttpServer}
  27. * instance when a websocket handshake is accepted on the server, or are create by an {@link HttpClient}
  28. * instance when a client succeeds in a websocket handshake with a server. Once an instance has been obtained it can
  29. * be used to send or receive buffers of data from the connection, a bit like a TCP socket.</p>
  30. *
  31. * <p>Instances of this class can only be used from the event loop thread which created it.</p>
  32. *
  33. * @author <a href="http://tfox.org">Tim Fox</a>
  34. */
  35. public class Websocket implements ReadStream, WriteStream {
  36. private final AbstractConnection conn;
  37. private Handler<Buffer> dataHandler;
  38. private Handler<Void> drainHandler;
  39. private Handler<Exception> exceptionHandler;
  40. private Handler<Void> endHandler;
  41. Websocket(String uri, AbstractConnection conn) {
  42. this.uri = uri;
  43. this.conn = conn;
  44. }
  45. /**
  46. * The uri the websocket was created on. When a websocket is first received on the server, the uri can be checked and
  47. * the websocket can be closed if you want to restrict which uris you wish to accept websockets on.
  48. */
  49. public final String uri;
  50. /**
  51. * Write {@code data} to the websocket as binary frame
  52. */
  53. public void writeBinaryFrame(Buffer data) {
  54. WebSocketFrame frame = new DefaultWebSocketFrame(0x80, data.getChannelBuffer());
  55. conn.write(frame);
  56. }
  57. /**
  58. * Write {@code str} to the websocket as text frame
  59. */
  60. public void writeTextFrame(String str) {
  61. WebSocketFrame frame = new DefaultWebSocketFrame(str);
  62. conn.write(frame);
  63. }
  64. /**
  65. * Specify a data handler for the websocket. As data is received on the websocket the handler will be called, passing
  66. * in a Buffer of data
  67. */
  68. public void dataHandler(Handler<Buffer> handler) {
  69. this.dataHandler = handler;
  70. }
  71. /**
  72. * Specify an end handler for the websocket. The {@code endHandler} is called once there is no more data to be read.
  73. */
  74. public void endHandler(Handler<Void> handler) {
  75. this.endHandler = handler;
  76. }
  77. /**
  78. * Specify an exception handler for the websocket. The {@code exceptionHandler} is called if an exception occurs.
  79. */
  80. public void exceptionHandler(Handler<Exception> handler) {
  81. this.exceptionHandler = handler;
  82. }
  83. /**
  84. * Pause the websocket. Once the websocket has been paused, the system will stop reading any more chunks of data
  85. * from the wire, thus pushing back to the server.
  86. * Pause is often used in conjunction with a {@link org.nodex.java.core.streams.Pump} to pump data between streams and implement flow control.
  87. */
  88. public void pause() {
  89. conn.pause();
  90. }
  91. /**
  92. * Resume a paused websocket. The websocket will resume receiving chunks of data from the wire.<p>
  93. * Resume is often used in conjunction with a {@link org.nodex.java.core.streams.Pump} to pump data between streams and implement flow control.
  94. */
  95. public void resume() {
  96. conn.resume();
  97. }
  98. /**
  99. * Data is queued until it is actually sent. To set the point at which the queue is considered "full" call this method
  100. * specifying the {@code maxSize} in bytes.<p>
  101. * This method is used by the {@link org.nodex.java.core.streams.Pump} class to pump data
  102. * between different streams and perform flow control.
  103. */
  104. public void setWriteQueueMaxSize(int maxSize) {
  105. conn.setWriteQueueMaxSize(maxSize);
  106. }
  107. /**
  108. * If the amount of data that is currently queued is greater than the write queue max size see {@link #setWriteQueueMaxSize(int)}
  109. * then the write queue is considered full.<p>
  110. * Data can still be written to the websocket even if the write queue is deemed full, however it should be used as indicator
  111. * to stop writing and push back on the source of the data, otherwise you risk running out of available RAM.<p>
  112. * This method is used by the {@link org.nodex.java.core.streams.Pump} class to pump data
  113. * between different streams and perform flow control.
  114. * @return {@code true} if the write queue is full, {@code false} otherwise
  115. */
  116. public boolean writeQueueFull() {
  117. return conn.writeQueueFull();
  118. }
  119. /**
  120. * Write a {@link Buffer} to the websocket.
  121. */
  122. public void writeBuffer(Buffer data) {
  123. writeBinaryFrame(data);
  124. }
  125. /**
  126. * This method sets a drain handler {@code handler} on the websocket. The drain handler will be called when write queue is no longer
  127. * full and it is safe to write to it again.<p>
  128. * The drain handler is actually called when the write queue size reaches <b>half</b> the write queue max size to prevent thrashing.
  129. * This method is used as part of a flow control strategy, e.g. it is used by the {@link org.nodex.java.core.streams.Pump} class to pump data
  130. * between different streams.
  131. * @param handler
  132. */
  133. public void drainHandler(Handler<Void> handler) {
  134. this.drainHandler = handler;
  135. }
  136. /**
  137. * Close the websocket
  138. */
  139. public void close() {
  140. conn.close();
  141. }
  142. void handleFrame(WebSocketFrame frame) {
  143. if (dataHandler != null) {
  144. dataHandler.handle(new Buffer(frame.getBinaryData()));
  145. }
  146. }
  147. void writable() {
  148. if (drainHandler != null) {
  149. drainHandler.handle(null);
  150. }
  151. }
  152. void handleException(Exception e) {
  153. if (exceptionHandler != null) {
  154. exceptionHandler.handle(e);
  155. }
  156. }
  157. }