/simple/src/main/java/org/simpleframework/http/socket/service/FrameChannel.java

https://gitlab.com/UnderSampled/aard2-build · Java · 215 lines · 62 code · 20 blank · 133 comment · 0 complexity · 660a1c5b76a4a655d1e390da7b10f8a5 MD5 · raw file

  1. /*
  2. * FrameChannel.java February 2014
  3. *
  4. * Copyright (C) 2014, Niall Gallagher <niallg@users.sf.net>
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  15. * implied. See the License for the specific language governing
  16. * permissions and limitations under the License.
  17. */
  18. package org.simpleframework.http.socket.service;
  19. import static org.simpleframework.http.socket.CloseCode.NORMAL_CLOSURE;
  20. import static org.simpleframework.http.socket.service.ServiceEvent.OPEN_SOCKET;
  21. import java.io.IOException;
  22. import org.simpleframework.http.Request;
  23. import org.simpleframework.http.Response;
  24. import org.simpleframework.http.socket.Frame;
  25. import org.simpleframework.http.socket.FrameListener;
  26. import org.simpleframework.http.socket.Reason;
  27. import org.simpleframework.http.socket.Session;
  28. import org.simpleframework.http.socket.WebSocket;
  29. import org.simpleframework.transport.Channel;
  30. import org.simpleframework.transport.Sender;
  31. import org.simpleframework.transport.reactor.Reactor;
  32. import org.simpleframework.transport.trace.Trace;
  33. /**
  34. * The <code>FrameChannel</code> represents a full duplex communication
  35. * channel as defined by RFC 6455. Any instance of this will provide
  36. * a means to perform asynchronous writes and reads to a remote client
  37. * using a lightweight framing protocol. A frame is a finite length
  38. * sequence of bytes that can hold either text or binary data. Also,
  39. * control frames are used to perform heartbeat monitoring and closure.
  40. * <p>
  41. * For convenience frames can be consumed from the socket via a
  42. * callback to a registered listener. This avoids having to poll each
  43. * socket for data and provides a asynchronous event driven model of
  44. * communication, which greatly reduces overhead and complication.
  45. *
  46. * @author Niall Gallagher
  47. *
  48. * @see org.simpleframework.http.socket.FrameListener
  49. * @see org.simpleframework.http.socket.Frame
  50. */
  51. class FrameChannel implements WebSocket {
  52. /**
  53. * The collector is used to collect frames from the TCP channel.
  54. */
  55. private final FrameCollector operation;
  56. /**
  57. * This encoder is used to encode data as RFC 6455 frames.
  58. */
  59. private final FrameEncoder encoder;
  60. /**
  61. * This is the associated web socket session.
  62. */
  63. private final Session session;
  64. /**
  65. * The reason that is sent if at any time the channel is closed.
  66. */
  67. private final Reason reason;
  68. /**
  69. * This is the sender used to send frames over the channel.
  70. */
  71. private final Sender sender;
  72. /**
  73. * This is used to trace all events that occur on the channel.
  74. */
  75. private final Trace trace;
  76. /**
  77. * Constructor for the <code>FrameChannel</code> object. This is used
  78. * to create a channel that can read and write frames over a TCP
  79. * channel. For asynchronous read and dispatch operations this will
  80. * produce an operation to collect and process RFC 6455 frames.
  81. *
  82. * @param request this is the initiating request for the WebSocket
  83. * @param response this is the initiating response for the WebSocket
  84. * @param channel this is the underlying TCP channel to communicate on
  85. * @param reactor this is the reactor used to process frames
  86. */
  87. public FrameChannel(Request request, Response response, Channel channel, Reactor reactor) {
  88. this.session = new RequestSession(this, request, response);
  89. this.operation = new FrameCollector(session, channel, reactor);
  90. this.encoder = new FrameEncoder(channel);
  91. this.reason = new Reason(NORMAL_CLOSURE);
  92. this.sender = channel.getSender();
  93. this.trace = channel.getTrace();
  94. }
  95. /**
  96. * This is used to open the channel and begin consuming frames. This
  97. * will also return the session that contains the details for the
  98. * created WebSocket such as the initiating request and response as
  99. * well as the <code>WebSocket</code> object.
  100. *
  101. * @return the session associated with the WebSocket
  102. */
  103. public Session open() throws IOException {
  104. trace.trace(OPEN_SOCKET);
  105. operation.run();
  106. return session;
  107. }
  108. /**
  109. * This is used to register a <code>FrameListener</code> to this
  110. * instance. The registered listener will receive all user frames
  111. * and control frames sent from the client. Also, when the frame
  112. * is closed or when an unexpected error occurs the listener is
  113. * notified. Any number of listeners can be registered at any time.
  114. *
  115. * @param listener this is the listener that is to be registered
  116. */
  117. public void register(FrameListener listener) throws IOException {
  118. operation.register(listener);
  119. }
  120. /**
  121. * This is used to remove a <code>FrameListener</code> from this
  122. * instance. After removal the listener will no longer receive
  123. * any user frames or control messages from this specific instance.
  124. *
  125. * @param listener this is the listener to be removed
  126. */
  127. public void remove(FrameListener listener) throws IOException {
  128. operation.remove(listener);
  129. }
  130. /**
  131. * This is used to send data to the connected client. To prevent
  132. * an application code from causing resource issues this will block
  133. * as soon as a configured linked list of mapped memory buffers has
  134. * been exhausted. Caution should be taken when writing a broadcast
  135. * implementation that can write to multiple sockets as a badly
  136. * behaving socket that has filled its output buffering capacity
  137. * can cause congestion.
  138. *
  139. * @param data this is the data that is to be sent
  140. */
  141. public void send(byte[] data) throws IOException {
  142. encoder.encode(data);
  143. sender.flush();
  144. }
  145. /**
  146. * This is used to send text to the connected client. To prevent
  147. * an application code from causing resource issues this will block
  148. * as soon as a configured linked list of mapped memory buffers has
  149. * been exhausted. Caution should be taken when writing a broadcast
  150. * implementation that can write to multiple sockets as a badly
  151. * behaving socket that has filled its output buffering capacity
  152. * can cause congestion.
  153. *
  154. * @param text this is the text that is to be sent
  155. */
  156. public void send(String text) throws IOException {
  157. encoder.encode(text);
  158. sender.flush();
  159. }
  160. /**
  161. * This is used to send data to the connected client. To prevent
  162. * an application code from causing resource issues this will block
  163. * as soon as a configured linked list of mapped memory buffers has
  164. * been exhausted. Caution should be taken when writing a broadcast
  165. * implementation that can write to multiple sockets as a badly
  166. * behaving socket that has filled its output buffering capacity
  167. * can cause congestion.
  168. *
  169. * @param frame this is the frame that is to be sent
  170. */
  171. public void send(Frame frame) throws IOException {
  172. encoder.encode(frame);
  173. sender.flush();
  174. }
  175. /**
  176. * This is used to close the connection with a specific reason.
  177. * The close reason will be sent as a control frame before the
  178. * TCP connection is terminated.
  179. *
  180. * @param reason the reason for closing the connection
  181. */
  182. public void close(Reason reason) throws IOException {
  183. encoder.encode(reason);
  184. sender.close();
  185. }
  186. /**
  187. * This is used to close the connection without a specific reason.
  188. * The close reason will be sent as a control frame before the
  189. * TCP connection is terminated.
  190. */
  191. public void close() throws IOException {
  192. encoder.encode(reason);
  193. sender.close();
  194. }
  195. }