package cc.blynk.server.core.protocol.handlers; import cc.blynk.server.core.protocol.exceptions.BaseServerException; import cc.blynk.server.core.protocol.exceptions.UnsupportedCommandException; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.DecoderException; import io.netty.handler.ssl.NotSslRecordException; import io.netty.handler.timeout.ReadTimeoutException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.net.ssl.SSLException; import java.io.IOException; import static cc.blynk.utils.BlynkByteBufUtil.makeResponse; /** * The Blynk Project. * Created by Dmitriy Dumanskiy. * Created on 2/11/2015. */ public interface DefaultExceptionHandler { Logger log = LogManager.getLogger(DefaultExceptionHandler.class); default void handleGeneralException(ChannelHandlerContext ctx, Throwable cause, int msgId) { if (cause instanceof BaseServerException) { BaseServerException baseServerException = (BaseServerException) cause; log.debug(baseServerException.getMessage()); if (ctx.channel().isWritable()) { ctx.writeAndFlush(makeResponse(msgId, baseServerException.errorCode), ctx.voidPromise()); } } else { handleUnexpectedException(ctx, cause); } } default void handleGeneralException(ChannelHandlerContext ctx, Throwable cause) { if (cause instanceof BaseServerException) { BaseServerException baseServerException = (BaseServerException) cause; //no need for stack trace for known exceptions log.debug(baseServerException.getMessage()); if (ctx.channel().isWritable()) { ctx.writeAndFlush(makeResponse(baseServerException.msgId, baseServerException.errorCode), ctx.voidPromise()); } } else { handleUnexpectedException(ctx, cause); } } default void handleUnexpectedException(ChannelHandlerContext ctx, Throwable cause) { if (cause instanceof ReadTimeoutException) { log.trace("Channel was inactive for a long period. Closing..."); //channel is already closed here by ReadTimeoutHandler } else if (cause instanceof DecoderException) { if (cause.getCause() instanceof UnsupportedCommandException) { log.debug("Input command is invalid. Closing socket. Reason {}. Address {}", cause.getMessage(), ctx.channel().remoteAddress()); } else if (cause.getCause() instanceof SSLException) { log.debug("Unsecured connection attempt. Channel : {}. Reason : {}", ctx.channel().remoteAddress(), cause.getMessage()); } else { log.error("DecoderException.", cause); } ctx.close(); } else if (cause instanceof NotSslRecordException) { log.debug("Not secure connection attempt detected. {}. IP {}", cause.getMessage(), ctx.channel().remoteAddress()); ctx.close(); } else if (cause instanceof SSLException) { log.warn("SSL exception. {}.", cause.getMessage()); ctx.close(); } else if (cause instanceof IOException) { log.trace("Blynk server IOException.", cause); } else { String message = cause == null ? "" : cause.getMessage(); if (message != null && message.contains("OutOfDirectMemoryError")) { log.error("OutOfDirectMemoryError!!!"); } else { log.error("Unexpected error!!!", message); log.error("Handler class : {}. Name : {}", ctx.handler().getClass(), ctx.name()); } } } }