/* * Copyright 2015 Netflix, Inc. * * 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 io.reactivex.netty.protocol.http.ws; import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketFrame; import io.reactivex.netty.channel.Connection; import rx.Observable; import rx.annotations.Beta; import rx.functions.Func1; /** * A WebSocket connection which is used to read/write {@link WebSocketFrame}s. */ public final class WebSocketConnection { private final Connection<WebSocketFrame, WebSocketFrame> delegate; public WebSocketConnection(Connection<WebSocketFrame, WebSocketFrame> delegate) { this.delegate = delegate; } /** * Returns the input stream for this connection, until a {@link CloseWebSocketFrame} is received. The terminal * {@link CloseWebSocketFrame} is included in the returned stream. * * @return The input stream for this connection. */ public Observable<WebSocketFrame> getInput() { return getInput(true); } /** * Returns the input stream for this connection. If {@code untilCloseFrame} is {@code true} then the returned stream * completes after receiving (and emitting) a {@link CloseWebSocketFrame}, otherwise, it completes with an error * when the underlying channel is closed. * * @return The input stream for this connection. */ @Beta public Observable<WebSocketFrame> getInput(boolean untilCloseFrame) { Observable<WebSocketFrame> rawInput = delegate.getInput(); if (untilCloseFrame) { return rawInput.takeUntil(new Func1<WebSocketFrame, Boolean>() { @Override public Boolean call(WebSocketFrame webSocketFrame) { return webSocketFrame instanceof CloseWebSocketFrame; } }); } else { return rawInput; } } /** * Writes a stream of frames on this connection. The writes are flushed on completion of the stream, if other flush * strategies are required, one must use {@link #write(Observable, Func1)} or * {@link #writeAndFlushOnEach(Observable)} * * @param msgs Stream of frames to write. * * @return {@link Observable} representing the result of this write. Every subscription to this {@link Observable} * will replay the write on the channel. */ public Observable<Void> write(Observable<WebSocketFrame> msgs) { return delegate.write(msgs); } /** * On subscription of the returned {@link Observable}, writes the passed message stream on the underneath channel * and flushes the channel, everytime, {@code flushSelector} returns {@code true} . Any writes issued before * subscribing, will also be flushed. However, the returned {@link Observable} will not capture the result of those * writes, i.e. if the other writes, fail and this write does not, the returned {@link Observable} will not fail. * * @param msgs Message stream to write. * @param flushSelector A {@link Func1} which is invoked for every item emitted from {@code msgs}. Channel is * flushed, iff this function returns, {@code true}. * * @return An {@link Observable} representing the result of this write. Every * subscription to this {@link Observable} will write the passed messages and flush all pending writes, when the * {@code flushSelector} returns {@code true} */ public Observable<Void> write(Observable<WebSocketFrame> msgs, Func1<WebSocketFrame, Boolean> flushSelector) { return delegate.write(msgs, flushSelector); } /** * On subscription of the returned {@link Observable}, writes the passed message stream on the underneath channel * and flushes the channel, on every write. Any writes issued before subscribing, will also be flushed. However, the * returned {@link Observable} will not capture the result of those writes, i.e. if the other writes, fail and this * write does not, the returned {@link Observable} will not fail. * * @param msgs Message stream to write. * * @return An {@link Observable} representing the result of this write. Every * subscription to this {@link Observable} will write the passed messages and flush all pending writes, on every * write. */ public Observable<Void> writeAndFlushOnEach(Observable<WebSocketFrame> msgs) { return delegate.writeAndFlushOnEach(msgs); } /** * Flushes all writes, if any, before calling the flush. */ public void flush() { delegate.flush(); } /** * Flushes any pending writes and closes the connection. Same as calling {@code close(true)} * * @return {@link Observable} representing the result of close. */ public Observable<Void> close() { return delegate.close(); } /** * Closes this channel after flushing all pending writes. * * @return {@link Observable} representing the result of close and flush. */ public Observable<Void> close(boolean flush) { return delegate.close(flush); } /** * Returns an {@link Observable} that completes when this connection is closed. * * @return An {@link Observable} that completes when this connection is closed. */ public Observable<Void> closeListener() { return delegate.closeListener(); } /** * Closes the connection immediately. Same as calling {@link #close()} and subscribing to the returned * {@code Observable} */ public void closeNow() { delegate.closeNow(); } }