Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You 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.apache.catalina.websocket;
 
 import static org.jboss.web.CatalinaMessages.MESSAGES;
 
 
 
Provides the means to write WebSocket messages to the client. All methods that write to the client (or update a buffer that is later written to the client) are synchronized to prevent multiple threads trying to write to the client at the same time.
 
 public class WsOutbound {
 
     public static final int DEFAULT_BUFFER_SIZE = 8192;
 
     private HttpEvent event;
     private StreamInbound streamInbound;
     private ByteBuffer bb;
     private CharBuffer cb;
     private boolean closed = false;
     private Boolean text = null;
     private boolean firstFrame = true;
 
 
     public WsOutbound(HttpEvent event,
             StreamInbound streamInbound) {
         this(eventstreamInbound,
                 );
     }
 
 
     public WsOutbound(HttpEvent eventStreamInbound streamInbound,
             int byteBufferSizeint charBufferSize) {
         this. = event;
         this. = streamInbound;
         this. = ByteBuffer.allocate(byteBufferSize);
         this. = CharBuffer.allocate(charBufferSize);
     }


    
Adds the data to the buffer for binary data. If a textual message is currently in progress that message will be completed and a new binary message started. If the buffer for binary data is full, the buffer will be flushed and a new binary continuation fragment started.

Parameters:
b The byte (only the least significant byte is used) of data to send to the client.
Throws:
java.io.IOException If a flush is required and an error occurs writing the WebSocket frame to the client
 
     public synchronized void writeBinaryData(int bthrows IOException {
         if () {
             throw new IOException(.outboundClosed());
         }
 
         if (.position() == .capacity()) {
             doFlush(false);
         }
         if ( == null) {
              = .;
         } else if ( == .) {
             // Flush the character data
             flush();
              = .;
         }
         .put((byte) (b & 0xFF));
     }


    
Adds the data to the buffer for textual data. If a binary message is currently in progress that message will be completed and a new textual message started. If the buffer for textual data is full, the buffer will be flushed and a new textual continuation fragment started.

Parameters:
c The character to send to the client.
Throws:
java.io.IOException If a flush is required and an error occurs writing the WebSocket frame to the client
    public synchronized void writeTextData(char cthrows IOException {
        if () {
            throw new IOException(.outboundClosed());
        }
        if (.position() == .capacity()) {
            doFlush(false);
        }
        if ( == null) {
             = .;
        } else if ( == .) {
            // Flush the binary data
            flush();
             = .;
        }
        .append(c);
    }


    
Flush any message (binary or textual) that may be buffered and then send a WebSocket binary message as a single frame with the provided buffer as the payload of the message.

Parameters:
msgBb The buffer containing the payload
Throws:
java.io.IOException If an error occurs writing to the client
    public synchronized void writeBinaryMessage(ByteBuffer msgBb)
            throws IOException {
        if () {
            throw new IOException(.outboundClosed());
        }
        if ( != null) {
            // Empty the buffer
            flush();
        }
         = .;
        doWriteBytes(msgBbtrue);
    }


    
Flush any message (binary or textual) that may be buffered and then send a WebSocket text message as a single frame with the provided buffer as the payload of the message.

Parameters:
msgCb The buffer containing the payload
Throws:
java.io.IOException If an error occurs writing to the client
    public synchronized void writeTextMessage(CharBuffer msgCb)
            throws IOException {
        if () {
            throw new IOException(.outboundClosed());
        }
        if ( != null) {
            // Empty the buffer
            flush();
        }
         = .;
        doWriteText(msgCbtrue);
    }


    
Flush any message (binary or textual) that may be buffered.

Throws:
java.io.IOException If an error occurs writing to the client
    public synchronized void flush() throws IOException {
        if () {
            throw new IOException(.outboundClosed());
        }
        doFlush(true);
    }
    private void doFlush(boolean finalFragmentthrows IOException {
        if ( == null) {
            // No data
            return;
        }
        if (.booleanValue()) {
            .flip();
            doWriteText(finalFragment);
        } else {
            .flip();
            doWriteBytes(finalFragment);
        }
    }


    
Respond to a client close by sending a close that echoes the status code and message.

Parameters:
frame The close frame received from a client
Throws:
java.io.IOException If an error occurs writing to the client
    protected void close(WsFrame framethrows IOException {
        if (frame.getPayLoadLength() > 0) {
            // Must be status (2 bytes) plus optional message
            if (frame.getPayLoadLength() == 1) {
                throw new IOException();
            }
            int status = (frame.getPayLoad().get() & 0xFF) << 8;
            status += frame.getPayLoad().get() & 0xFF;
            if (validateCloseStatus(status)) {
                // Echo the status back to the client
                close(statusframe.getPayLoad());
            } else {
                // Invalid close code
                close(.null);
            }
        } else {
            // No status
            close(0, null);
        }
    }
    private boolean validateCloseStatus(int status) {
        if (status == . ||
                status == . ||
                status == . ||
                status == . ||
                status == . ||
                status == . ||
                status == . ||
                status == . ||
                status == . ||
                (status > 2999 && status < 5000)) {
            // Other 1xxx reserved / not permitted
            // 2xxx reserved
            // 3xxx framework defined
            // 4xxx application defined
            return true;
        }
        // <1000 unused
        // >4999 undefined
        return false;
    }


    
Send a close message to the client

Parameters:
status Must be a valid status code or zero to send no code
data Optional message. If message is defined, a valid status code must be provided.
Throws:
java.io.IOException If an error occurs writing to the client
    public synchronized void close(int statusByteBuffer data)
            throws IOException {
        if () {
            return;
        }
        // Send any partial data we have
        try {
            doFlush(false);
        } finally {
             = true;
        }
        os.write(0x88);
        if (status == 0) {
            os.write(0);
        } else if (data == null || data.position() == data.limit()) {
            os.write(2);
            os.write(status >>> 8);
            os.write(status);
        } else {
            os.write(2 + data.limit() - data.position());
            os.write(status >>> 8);
            os.write(status);
            os.write(data.array(), data.position(),
                    data.limit() - data.position());
        }
        os.flush();
         = null;
         = null;
    }


    
Send a pong message to the client

Parameters:
data Optional message.
Throws:
java.io.IOException If an error occurs writing to the client
    public synchronized void pong(ByteBuffer datathrows IOException {
    }

    
Send a ping message to the client

Parameters:
data Optional message.
Throws:
java.io.IOException If an error occurs writing to the client
    public synchronized void ping(ByteBuffer datathrows IOException {
    }

    
Generic function to send either a ping or a pong.

Parameters:
data Optional message.
opcode The byte to include as the opcode.
Throws:
java.io.IOException If an error occurs writing to the client
    private synchronized void sendControlMessage(ByteBuffer databyte opcodethrows IOException {
        if () {
            throw new IOException(.outboundClosed());
        }
        doFlush(false);
        os.write(0x80 | opcode);
        if (data == null) {
            os.write(0);
        } else {
            os.write(data.limit() - data.position());
            os.write(data.array(), data.position(),
                    data.limit() - data.position());
        }
        os.flush();
    }


    
Writes the provided bytes as the payload in a new WebSocket frame.

Parameters:
buffer The bytes to include in the payload.
finalFragment Do these bytes represent the final fragment of a WebSocket message?
Throws:
java.io.IOException
    private void doWriteBytes(ByteBuffer bufferboolean finalFragment)
            throws IOException {
        if () {
            throw new IOException(.outboundClosed());
        }
        try {
            // Work out the first byte
            int first = 0x00;
            if (finalFragment) {
                first = first + 0x80;
            }
            if () {
                if (.booleanValue()) {
                    first = first + 0x1;
                } else {
                    first = first + 0x2;
                }
            }
            // Continuation frame is OpCode 0
            os.write(first);
    
            if (buffer.limit() < 126) {
                os.write(buffer.limit());
            } else if (buffer.limit() < 65536) {
                os.write(126);
                os.write(buffer.limit() >>> 8);
                os.write(buffer.limit() & 0xFF);
            } else {
                // Will never be more than 2^31-1
                os.write(127);
                os.write(0);
                os.write(0);
                os.write(0);
                os.write(0);
                os.write(buffer.limit() >>> 24);
                os.write(buffer.limit() >>> 16);
                os.write(buffer.limit() >>> 8);
                os.write(buffer.limit() & 0xFF);
            }
    
            // Write the content
            os.write(buffer.array(), buffer.arrayOffset(),
                    buffer.limit());
            os.flush();
    
            // Reset
            if (finalFragment) {
                 = null;
                 = true;
            } else {
                 = false;
            }
            .clear();
        } catch (IOException ioe) {
            // Any IOException is terminal. Make sure the Inbound side knows
            // that something went wrong.
            throw ioe;
        }
    }
    /*
     * Convert the textual message to bytes and then output it.
     */
    private void doWriteText(CharBuffer bufferboolean finalFragment)
            throws IOException {
        CharsetEncoder encoder = ..newEncoder();
        do {
            CoderResult cr = encoder.encode(buffertrue);
            if (cr.isError()) {
                cr.throwException();
            }
            .flip();
            if (buffer.hasRemaining()) {
                doWriteBytes(false);
            } else {
                doWriteBytes(finalFragment);
            }
        } while (buffer.hasRemaining());
        // Reset - bb will be cleared in doWriteBytes()
        .clear();
    }
New to GrepCode? Check out our FAQ X