/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
- /*
- * FrameChannel.java February 2014
- *
- * Copyright (C) 2014, Niall Gallagher <niallg@users.sf.net>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
- package org.simpleframework.http.socket.service;
-
- import static org.simpleframework.http.socket.CloseCode.NORMAL_CLOSURE;
- import static org.simpleframework.http.socket.service.ServiceEvent.OPEN_SOCKET;
-
- import java.io.IOException;
-
- import org.simpleframework.http.Request;
- import org.simpleframework.http.Response;
- import org.simpleframework.http.socket.Frame;
- import org.simpleframework.http.socket.FrameListener;
- import org.simpleframework.http.socket.Reason;
- import org.simpleframework.http.socket.Session;
- import org.simpleframework.http.socket.WebSocket;
- import org.simpleframework.transport.Channel;
- import org.simpleframework.transport.Sender;
- import org.simpleframework.transport.reactor.Reactor;
- import org.simpleframework.transport.trace.Trace;
-
- /**
- * The <code>FrameChannel</code> represents a full duplex communication
- * channel as defined by RFC 6455. Any instance of this will provide
- * a means to perform asynchronous writes and reads to a remote client
- * using a lightweight framing protocol. A frame is a finite length
- * sequence of bytes that can hold either text or binary data. Also,
- * control frames are used to perform heartbeat monitoring and closure.
- * <p>
- * For convenience frames can be consumed from the socket via a
- * callback to a registered listener. This avoids having to poll each
- * socket for data and provides a asynchronous event driven model of
- * communication, which greatly reduces overhead and complication.
- *
- * @author Niall Gallagher
- *
- * @see org.simpleframework.http.socket.FrameListener
- * @see org.simpleframework.http.socket.Frame
- */
- class FrameChannel implements WebSocket {
-
- /**
- * The collector is used to collect frames from the TCP channel.
- */
- private final FrameCollector operation;
-
- /**
- * This encoder is used to encode data as RFC 6455 frames.
- */
- private final FrameEncoder encoder;
-
- /**
- * This is the associated web socket session.
- */
- private final Session session;
-
- /**
- * The reason that is sent if at any time the channel is closed.
- */
- private final Reason reason;
-
- /**
- * This is the sender used to send frames over the channel.
- */
- private final Sender sender;
-
- /**
- * This is used to trace all events that occur on the channel.
- */
- private final Trace trace;
-
- /**
- * Constructor for the <code>FrameChannel</code> object. This is used
- * to create a channel that can read and write frames over a TCP
- * channel. For asynchronous read and dispatch operations this will
- * produce an operation to collect and process RFC 6455 frames.
- *
- * @param request this is the initiating request for the WebSocket
- * @param response this is the initiating response for the WebSocket
- * @param channel this is the underlying TCP channel to communicate on
- * @param reactor this is the reactor used to process frames
- */
- public FrameChannel(Request request, Response response, Channel channel, Reactor reactor) {
- this.session = new RequestSession(this, request, response);
- this.operation = new FrameCollector(session, channel, reactor);
- this.encoder = new FrameEncoder(channel);
- this.reason = new Reason(NORMAL_CLOSURE);
- this.sender = channel.getSender();
- this.trace = channel.getTrace();
- }
-
- /**
- * This is used to open the channel and begin consuming frames. This
- * will also return the session that contains the details for the
- * created WebSocket such as the initiating request and response as
- * well as the <code>WebSocket</code> object.
- *
- * @return the session associated with the WebSocket
- */
- public Session open() throws IOException {
- trace.trace(OPEN_SOCKET);
- operation.run();
- return session;
- }
-
- /**
- * This is used to register a <code>FrameListener</code> to this
- * instance. The registered listener will receive all user frames
- * and control frames sent from the client. Also, when the frame
- * is closed or when an unexpected error occurs the listener is
- * notified. Any number of listeners can be registered at any time.
- *
- * @param listener this is the listener that is to be registered
- */
- public void register(FrameListener listener) throws IOException {
- operation.register(listener);
- }
-
- /**
- * This is used to remove a <code>FrameListener</code> from this
- * instance. After removal the listener will no longer receive
- * any user frames or control messages from this specific instance.
- *
- * @param listener this is the listener to be removed
- */
- public void remove(FrameListener listener) throws IOException {
- operation.remove(listener);
- }
-
- /**
- * This is used to send data to the connected client. To prevent
- * an application code from causing resource issues this will block
- * as soon as a configured linked list of mapped memory buffers has
- * been exhausted. Caution should be taken when writing a broadcast
- * implementation that can write to multiple sockets as a badly
- * behaving socket that has filled its output buffering capacity
- * can cause congestion.
- *
- * @param data this is the data that is to be sent
- */
- public void send(byte[] data) throws IOException {
- encoder.encode(data);
- sender.flush();
- }
-
- /**
- * This is used to send text to the connected client. To prevent
- * an application code from causing resource issues this will block
- * as soon as a configured linked list of mapped memory buffers has
- * been exhausted. Caution should be taken when writing a broadcast
- * implementation that can write to multiple sockets as a badly
- * behaving socket that has filled its output buffering capacity
- * can cause congestion.
- *
- * @param text this is the text that is to be sent
- */
- public void send(String text) throws IOException {
- encoder.encode(text);
- sender.flush();
- }
-
- /**
- * This is used to send data to the connected client. To prevent
- * an application code from causing resource issues this will block
- * as soon as a configured linked list of mapped memory buffers has
- * been exhausted. Caution should be taken when writing a broadcast
- * implementation that can write to multiple sockets as a badly
- * behaving socket that has filled its output buffering capacity
- * can cause congestion.
- *
- * @param frame this is the frame that is to be sent
- */
- public void send(Frame frame) throws IOException {
- encoder.encode(frame);
- sender.flush();
- }
-
- /**
- * This is used to close the connection with a specific reason.
- * The close reason will be sent as a control frame before the
- * TCP connection is terminated.
- *
- * @param reason the reason for closing the connection
- */
- public void close(Reason reason) throws IOException {
- encoder.encode(reason);
- sender.close();
- }
-
- /**
- * This is used to close the connection without a specific reason.
- * The close reason will be sent as a control frame before the
- * TCP connection is terminated.
- */
- public void close() throws IOException {
- encoder.encode(reason);
- sender.close();
- }
- }