/*
 * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 * which is available at https://www.apache.org/licenses/LICENSE-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 */

package io.vertx.core.http.impl;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.FileRegion;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.stream.ChunkedFile;
import io.vertx.codegen.annotations.Nullable;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.GoAway;
import io.vertx.core.http.Http2Settings;
import io.vertx.core.http.HttpConnection;
import io.vertx.core.impl.ContextInternal;
import io.vertx.core.net.impl.ConnectionBase;

Author:Julien Viet
/** * @author <a href="mailto:julien@julienviet.com">Julien Viet</a> */
abstract class Http1xConnectionBase<S extends WebSocketImplBase<S>> extends ConnectionBase implements io.vertx.core.http.HttpConnection { protected S webSocket; Http1xConnectionBase(ContextInternal context, ChannelHandlerContext chctx) { super(context, chctx); } void handleWsFrame(WebSocketFrame msg) { WebSocketImplBase<?> w; synchronized (this) { w = webSocket; } if (w != null) { w.context.execute(msg, w::handleFrame); } } @Override public Future<Void> close() { S sock; synchronized (this) { sock = webSocket; } if (sock == null) { return super.close(); } else { sock.close(); return closeFuture(); } } @Override public Http1xConnectionBase closeHandler(Handler<Void> handler) { return (Http1xConnectionBase) super.closeHandler(handler); } @Override public Http1xConnectionBase exceptionHandler(Handler<Throwable> handler) { return (Http1xConnectionBase) super.exceptionHandler(handler); } @Override public HttpConnection goAway(long errorCode, int lastStreamId, Buffer debugData) { throw new UnsupportedOperationException("HTTP/1.x connections don't support GOAWAY"); } @Override public HttpConnection goAwayHandler(@Nullable Handler<GoAway> handler) { throw new UnsupportedOperationException("HTTP/1.x connections don't support GOAWAY"); } @Override public HttpConnection shutdownHandler(@Nullable Handler<Void> handler) { throw new UnsupportedOperationException("HTTP/1.x connections don't support GOAWAY"); } @Override public void shutdown(long timeout, Handler<AsyncResult<Void>> handler) { throw new UnsupportedOperationException("HTTP/1.x connections don't support GOAWAY"); } @Override public Future<Void> shutdown(long timeoutMs) { throw new UnsupportedOperationException("HTTP/1.x connections don't support GOAWAY"); } @Override public Http2Settings settings() { throw new UnsupportedOperationException("HTTP/1.x connections don't support SETTINGS"); } @Override public Future<Void> updateSettings(Http2Settings settings) { throw new UnsupportedOperationException("HTTP/1.x connections don't support SETTINGS"); } @Override public HttpConnection updateSettings(Http2Settings settings, Handler<AsyncResult<Void>> completionHandler) { throw new UnsupportedOperationException("HTTP/1.x connections don't support SETTINGS"); } @Override public Http2Settings remoteSettings() { throw new UnsupportedOperationException("HTTP/1.x connections don't support SETTINGS"); } @Override public HttpConnection remoteSettingsHandler(Handler<Http2Settings> handler) { throw new UnsupportedOperationException("HTTP/1.x connections don't support SETTINGS"); } @Override public HttpConnection ping(Buffer data, Handler<AsyncResult<Buffer>> pongHandler) { throw new UnsupportedOperationException("HTTP/1.x connections don't support PING"); } @Override public HttpConnection pingHandler(@Nullable Handler<Buffer> handler) { throw new UnsupportedOperationException("HTTP/1.x connections don't support PING"); } @Override public Future<Buffer> ping(Buffer data) { throw new UnsupportedOperationException("HTTP/1.x connections don't support PING"); } @Override protected void reportsBytesWritten(Object msg) { long size = sizeOf(msg); reportBytesWritten(size); } @Override protected void reportBytesRead(Object msg) { long size = sizeOf(msg); reportBytesRead(size); } static long sizeOf(WebSocketFrame obj) { return obj.content().readableBytes(); } static long sizeOf(Object obj) { if (obj instanceof Buffer) { return ((Buffer) obj).length(); } else if (obj instanceof ByteBuf) { return ((ByteBuf) obj).readableBytes(); } else if (obj instanceof HttpContent) { return ((HttpContent) obj).content().readableBytes(); } else if (obj instanceof WebSocketFrame) { return sizeOf((WebSocketFrame) obj); } else if (obj instanceof FileRegion) { return ((FileRegion) obj).count(); } else if (obj instanceof ChunkedFile) { ChunkedFile file = (ChunkedFile) obj; return file.endOffset() - file.startOffset(); } else { return 0L; } } }