/*
* ServiceChannel.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 java.io.IOException;
import org.simpleframework.http.socket.Frame;
import org.simpleframework.http.socket.FrameListener;
import org.simpleframework.http.socket.Reason;
import org.simpleframework.http.socket.FrameChannel;
/**
* The <code>ServiceChannel</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
*/
class ServiceChannel implements FrameChannel {
/**
* This is the internal channel for full duplex communication.
*/
private final FrameChannel channel;
/**
* Constructor for the <code>ServiceChannel</code> object. This is
* used to create a channel that is given to the application. This
* is synchronized so only one frame can be dispatched at a time.
*
* @param channel this is the channel to delegate to
*/
public ServiceChannel(FrameChannel channel) {
this.channel = channel;
}
/**
* 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 synchronized void send(byte[] data) throws IOException {
channel.send(data);
}
/**
* 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 synchronized void send(String text) throws IOException {
channel.send(text);
}
/**
* 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 synchronized void send(Frame frame) throws IOException {
channel.send(frame);
}
/**
* 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 synchronized void register(FrameListener listener) throws IOException {
channel.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 synchronized void remove(FrameListener listener) throws IOException {
channel.remove(listener);
}
/**
* 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 synchronized void close(Reason reason) throws IOException {
channel.close(reason);
}
/**
* 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 {
channel.close();
}
}