From d8ede0fb2fd8c008b4dc0f9c547bf0260a1880c8 Mon Sep 17 00:00:00 2001
From: Paul Gregoire <mondain@gmail.com>
Date: Fri, 6 May 2022 08:44:29 -0700
Subject: [PATCH] Updated version to 1.2.23. Fixes for scope lookup and rtmpe
 playback

---
 client/pom.xml                                |  2 +-
 .../main/java/org/red5/client/Red5Client.java |  2 +-
 common/pom.xml                                |  2 +-
 .../main/java/org/red5/server/api/Red5.java   |  4 +-
 .../red5/server/net/rtmp/RTMPConnection.java  | 17 ++++++-
 .../server/net/rtmp/RTMPMinaConnection.java   | 14 +++--
 .../java/org/red5/server/scope/Scope.java     |  2 +-
 .../org/red5/server/stream/PlayEngine.java    | 51 ++++++++++---------
 .../stream/consumer/ConnectionConsumer.java   | 17 +++++--
 io/pom.xml                                    |  2 +-
 pom.xml                                       |  2 +-
 red5-eclipse-format.xml                       |  4 +-
 server/pom.xml                                |  2 +-
 .../server/net/rtmp/RTMPMinaIoHandler.java    |  2 +-
 .../red5/server/net/rtmpe/RTMPEIoFilter.java  | 18 ++++---
 service/pom.xml                               |  2 +-
 16 files changed, 87 insertions(+), 56 deletions(-)

diff --git a/client/pom.xml b/client/pom.xml
index 2b4e7514..6eafe123 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.red5</groupId>
         <artifactId>red5-parent</artifactId>
-        <version>1.2.22</version>
+        <version>1.2.23</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>red5-client</artifactId>
diff --git a/client/src/main/java/org/red5/client/Red5Client.java b/client/src/main/java/org/red5/client/Red5Client.java
index f3399c2d..c1b16d4d 100644
--- a/client/src/main/java/org/red5/client/Red5Client.java
+++ b/client/src/main/java/org/red5/client/Red5Client.java
@@ -18,7 +18,7 @@ public final class Red5Client {
     /**
      * Current server version with revision
      */
-    public static final String VERSION = "Red5 Client 1.2.22";
+    public static final String VERSION = "Red5 Client 1.2.23";
 
     /**
      * Create a new Red5Client object using the connection local to the current thread A bit of magic that lets you access the red5 scope
diff --git a/common/pom.xml b/common/pom.xml
index 4fadebb0..fac697bd 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.red5</groupId>
         <artifactId>red5-parent</artifactId>
-        <version>1.2.22</version>
+        <version>1.2.23</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>red5-server-common</artifactId>
diff --git a/common/src/main/java/org/red5/server/api/Red5.java b/common/src/main/java/org/red5/server/api/Red5.java
index 53df466a..d2167a14 100644
--- a/common/src/main/java/org/red5/server/api/Red5.java
+++ b/common/src/main/java/org/red5/server/api/Red5.java
@@ -55,12 +55,12 @@ public final class Red5 {
     /**
      * Server version with revision
      */
-    public static final String VERSION = "Red5 Server 1.2.22";
+    public static final String VERSION = "Red5 Server 1.2.23";
 
     /**
      * Server version for fmsVer requests
      */
-    public static final String FMS_VERSION = "RED5/1,2,22,0";
+    public static final String FMS_VERSION = "RED5/1,2,23,0";
 
     /**
      * Server capabilities
diff --git a/common/src/main/java/org/red5/server/net/rtmp/RTMPConnection.java b/common/src/main/java/org/red5/server/net/rtmp/RTMPConnection.java
index c494ace2..a1217abf 100755
--- a/common/src/main/java/org/red5/server/net/rtmp/RTMPConnection.java
+++ b/common/src/main/java/org/red5/server/net/rtmp/RTMPConnection.java
@@ -49,11 +49,13 @@ import org.red5.server.api.stream.IStreamService;
 import org.red5.server.exception.ClientRejectedException;
 import org.red5.server.net.protocol.RTMPDecodeState;
 import org.red5.server.net.rtmp.codec.RTMP;
+import org.red5.server.net.rtmp.event.AudioData;
 import org.red5.server.net.rtmp.event.BytesRead;
 import org.red5.server.net.rtmp.event.ChunkSize;
 import org.red5.server.net.rtmp.event.ClientBW;
 import org.red5.server.net.rtmp.event.ClientInvokeEvent;
 import org.red5.server.net.rtmp.event.ClientNotifyEvent;
+import org.red5.server.net.rtmp.event.IRTMPEvent;
 import org.red5.server.net.rtmp.event.Invoke;
 import org.red5.server.net.rtmp.event.Notify;
 import org.red5.server.net.rtmp.event.Ping;
@@ -1366,6 +1368,10 @@ public abstract class RTMPConnection extends BaseConnection implements IStreamCa
             }
             old.incrementAndGet();
         }
+        // XXX(paul) work-around for RTMPE issue with Mina messageSent callback
+        if (isEncrypted()) {
+            writtenMessages.incrementAndGet();
+        }
     }
 
     /**
@@ -1602,7 +1608,10 @@ public abstract class RTMPConnection extends BaseConnection implements IStreamCa
      *            Message to mark
      */
     public void messageSent(Packet message) {
-        if (message.getMessage() instanceof VideoData) {
+        //log.info("messageSent: {}", message);
+        IRTMPEvent event = message.getMessage();
+        if (event instanceof VideoData) {
+            log.info("Video message sent");
             Number streamId = message.getHeader().getStreamId();
             AtomicInteger pending = pendingVideos.get(streamId.doubleValue());
             if (isTrace) {
@@ -1611,6 +1620,12 @@ public abstract class RTMPConnection extends BaseConnection implements IStreamCa
             if (pending != null) {
                 pending.decrementAndGet();
             }
+        } else if (event instanceof AudioData) {
+            log.info("Audio message sent");
+        } else if (event instanceof Notify) {
+            log.info("Notify message sent");
+        } else {
+            log.warn("Message sent: {} data type: {}", event.getType(), event.getDataType());
         }
         writtenMessages.incrementAndGet();
     }
diff --git a/common/src/main/java/org/red5/server/net/rtmp/RTMPMinaConnection.java b/common/src/main/java/org/red5/server/net/rtmp/RTMPMinaConnection.java
index 33b40d41..74cda653 100644
--- a/common/src/main/java/org/red5/server/net/rtmp/RTMPMinaConnection.java
+++ b/common/src/main/java/org/red5/server/net/rtmp/RTMPMinaConnection.java
@@ -327,15 +327,14 @@ public class RTMPMinaConnection extends RTMPConnection implements RTMPMinaConnec
     public void write(Packet out) {
         if (ioSession != null) {
             final Semaphore lock = getLock();
-            if (log.isTraceEnabled()) {
-                log.trace("Write lock wait count: {} closed: {}", lock.getQueueLength(), isClosed());
-            }
+            //if (log.isTraceEnabled()) {
+            //    log.trace("Write lock wait count: {} closed: {}", lock.getQueueLength(), isClosed());
+            //}
             while (!isClosed()) {
                 boolean acquired = false;
                 try {
                     acquired = lock.tryAcquire(10, TimeUnit.MILLISECONDS);
-                    if (acquired) {
-                        // attempt write if not closing
+                    if (acquired) { // attempt write if not closing 
                         if (!ioSession.isClosing()) {
                             if (log.isTraceEnabled()) {
                                 log.trace("Writing message");
@@ -348,12 +347,11 @@ public class RTMPMinaConnection extends RTMPConnection implements RTMPMinaConnec
                 } catch (InterruptedException e) {
                     log.warn("Interrupted while waiting for write lock. State: {}", RTMP.states[state.getState()], e);
                     if (log.isInfoEnabled()) {
-                        // further debugging to assist with possible connection problems
+                        // further debugging to assist with possible connection problems 
                         log.info("Session id: {} in queue size: {} pending msgs: {} last ping/pong: {}", getSessionId(), currentQueueSize(), getPendingMessages(), getLastPingSentAndLastPongReceivedInterval());
                         log.info("Available permits - decoder: {} encoder: {}", decoderLock.availablePermits(), encoderLock.availablePermits());
                     }
-                    String exMsg = e.getMessage();
-                    // if the exception cause is null break out of here to prevent looping until closed
+                    String exMsg = e.getMessage(); // if the exception cause is null break out of here to prevent looping until closed 
                     if (exMsg == null || exMsg.indexOf("null") >= 0) {
                         log.debug("Exception writing to connection: {}", this);
                         break;
diff --git a/common/src/main/java/org/red5/server/scope/Scope.java b/common/src/main/java/org/red5/server/scope/Scope.java
index 9dffd570..35d88fb5 100644
--- a/common/src/main/java/org/red5/server/scope/Scope.java
+++ b/common/src/main/java/org/red5/server/scope/Scope.java
@@ -1446,7 +1446,7 @@ public class Scope extends BasicScope implements IScope, IScopeStatistics, Scope
                 // if its broadcast type then allow an alias match in addition to the name match
                 if (type == ScopeType.BROADCAST) {
                     // checks publish and subscribe aliases
-                    scope = stream().filter(child -> child.getType().equals(type) && (name.equals(child.getName()) || name.equals(((IBroadcastScope) child).getClientBroadcastStream().getAlias()) || ((IBroadcastScope) child).getClientBroadcastStream().containsAlias(name))).findFirst();
+                    scope = stream().filter(child -> child.getType().equals(type) && (name.equals(child.getName()) || ((IBroadcastScope) child).getClientBroadcastStream().containsAlias(name))).findFirst();
                 } else {
                     scope = stream().filter(child -> child.getType().equals(type) && name.equals(child.getName())).findFirst();
                 }
diff --git a/common/src/main/java/org/red5/server/stream/PlayEngine.java b/common/src/main/java/org/red5/server/stream/PlayEngine.java
index dd9d9913..73fe5206 100755
--- a/common/src/main/java/org/red5/server/stream/PlayEngine.java
+++ b/common/src/main/java/org/red5/server/stream/PlayEngine.java
@@ -83,6 +83,10 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
 
     private static final Logger log = Red5LoggerFactory.getLogger(PlayEngine.class);
 
+    private static boolean isDebug = log.isDebugEnabled();
+
+    private static boolean isTrace = log.isTraceEnabled();
+
     private final AtomicReference<IMessageInput> msgInReference = new AtomicReference<>();
 
     private final AtomicReference<IMessageOutput> msgOutReference = new AtomicReference<>();
@@ -280,7 +284,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
      * Start stream
      */
     public void start() {
-        if (log.isDebugEnabled()) {
+        if (isDebug) {
             log.debug("start - subscriber stream state: {}", (subscriberStream != null ? subscriberStream.getState() : null));
         }
         switch (subscriberStream.getState()) {
@@ -290,7 +294,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                 IMessageOutput out = consumerService.getConsumerOutput(subscriberStream);
                 if (msgOutReference.compareAndSet(null, out)) {
                     out.subscribe(this, null);
-                } else if (log.isDebugEnabled()) {
+                } else if (isDebug) {
                     log.debug("Message output was already set for stream: {}", subscriberStream);
                 }
                 break;
@@ -389,7 +393,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
         IMessage msg = null;
         currentItem.set(item);
         long itemLength = item.getLength();
-        if (log.isDebugEnabled()) {
+        if (isDebug) {
             log.debug("Play decision is {} (0=Live, 1=File, 2=Wait, 3=N/A) item length: {}", playDecision, itemLength);
         }
         switch (playDecision) {
@@ -431,7 +435,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                 in = providerService.getLiveProviderInput(thisScope, itemName, true);
                 if (msgInReference.compareAndSet(null, in)) {
                     if (type == -1 && itemLength >= 0) {
-                        if (log.isDebugEnabled()) {
+                        if (isDebug) {
                             log.debug("Creating wait job for {}", itemLength);
                         }
                         // Wait given timeout for stream to be published
@@ -443,7 +447,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                             }
                         });
                     } else if (type == -2) {
-                        if (log.isDebugEnabled()) {
+                        if (isDebug) {
                             log.debug("Creating wait job");
                         }
                         // Wait x seconds for the stream to be published
@@ -456,7 +460,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                     } else {
                         connectToProvider(itemName);
                     }
-                } else if (log.isDebugEnabled()) {
+                } else if (isDebug) {
                     log.debug("Message input already set for {}", itemName);
                 }
                 break;
@@ -756,7 +760,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
      *             If stream is in stopped state
      */
     public void stop() throws IllegalStateException {
-        if (log.isDebugEnabled()) {
+        if (isDebug) {
             log.debug("stop - subscriber stream state: {}", (subscriberStream != null ? subscriberStream.getState() : null));
         }
         // allow stop if playing or paused
@@ -805,7 +809,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
      * Close stream
      */
     public void close() {
-        if (log.isDebugEnabled()) {
+        if (isDebug) {
             log.debug("close");
         }
         if (!subscriberStream.getState().equals(StreamState.CLOSED)) {
@@ -824,7 +828,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
             if (out != null) {
                 List<IConsumer> consumers = out.getConsumers();
                 // assume a list of 1 in most cases
-                if (log.isDebugEnabled()) {
+                if (isDebug) {
                     log.debug("Message out consumers: {}", consumers.size());
                 }
                 if (!consumers.isEmpty()) {
@@ -965,7 +969,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
      *            The message to send.
      */
     private void doPushMessage(AbstractMessage message) {
-        if (log.isTraceEnabled()) {
+        if (isTrace) {
             String msgType = message.getMessageType();
             log.trace("doPushMessage: {}", msgType);
         }
@@ -1019,7 +1023,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
         event.setSourceType(eventIn.getSourceType());
         // instance the outgoing message
         RTMPMessage messageOut = RTMPMessage.build(event, eventTime);
-        if (log.isTraceEnabled()) {
+        if (isTrace) {
             log.trace("Source type - in: {} out: {}", eventIn.getSourceType(), messageOut.getBody().getSourceType());
             long delta = System.currentTimeMillis() - playbackStart;
             log.trace("sendMessage: streamStartTS {}, length {}, streamOffset {}, timestamp {} last timestamp {} delta {} buffered {}", new Object[] { streamStartTS.get(), currentItem.get().getLength(), streamOffset, eventTime, lastMessageTs, delta, lastMessageTs - delta });
@@ -1032,7 +1036,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
             long length = currentItem.get().getLength();
             if (length >= 0) {
                 int duration = eventTime - streamStartTS.get();
-                if (log.isTraceEnabled()) {
+                if (isTrace) {
                     log.trace("sendMessage duration={} length={}", duration, length);
                 }
                 if (duration - streamOffset >= length) {
@@ -1052,7 +1056,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                 // subtract the offset time of when the stream started playing for the client
                 eventTime -= startTs;
                 messageOut.getBody().setTimestamp(eventTime);
-                if (log.isTraceEnabled()) {
+                if (isTrace) {
                     log.trace("sendMessage (updated): streamStartTS={}, length={}, streamOffset={}, timestamp={}", new Object[] { startTs, currentItem.get().getLength(), streamOffset, eventTime });
                 }
             }
@@ -1150,7 +1154,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
      * @param bytes
      */
     private void sendOnPlayStatus(String code, int duration, long bytes) {
-        if (log.isDebugEnabled()) {
+        if (isDebug) {
             log.debug("Sending onPlayStatus - code: {} duration: {} bytes: {}", code, duration, bytes);
         }
         // create the buffer
@@ -1204,7 +1208,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
     private void sendCompleteStatus() {
         // may be the correct duration
         int duration = (lastMessageTs > 0) ? Math.max(0, lastMessageTs - streamStartTS.get()) : 0;
-        if (log.isDebugEnabled()) {
+        if (isDebug) {
             log.debug("sendCompleteStatus - duration: {} bytes sent: {}", duration, bytesSent.get());
         }
         sendOnPlayStatus(StatusCodes.NS_PLAY_COMPLETE, duration, bytesSent.get());
@@ -1417,7 +1421,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                 }
                 break;
             default:
-                if (log.isDebugEnabled()) {
+                if (isDebug) {
                     log.debug("Unhandled pipe event: {}", event);
                 }
         }
@@ -1447,10 +1451,11 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
             RTMPMessage rtmpMessage = (RTMPMessage) message;
             IRTMPEvent body = rtmpMessage.getBody();
             if (body instanceof IStreamData) {
+                final String subscribedStreamName = subscriberStream.getBroadcastStreamPublishName();
                 // the subscriber paused 
                 if (subscriberStream.getState() == StreamState.PAUSED) {
                     if (log.isInfoEnabled() && shouldLogPacketDrop()) {
-                        log.info("Dropping packet because we are paused. sessionId={} stream={} count={}", sessionId, subscriberStream.getBroadcastStreamPublishName(), droppedPacketsCount);
+                        log.info("Dropping packet because we are paused. sessionId={} stream={} count={}", sessionId, subscribedStreamName, droppedPacketsCount);
                     }
                     videoFrameDropper.dropPacket(rtmpMessage);
                     return;
@@ -1469,7 +1474,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                                     droppedPacketsCount++;
                                     if (log.isInfoEnabled() && shouldLogPacketDrop()) {
                                         // client disabled video or the app doesn't have enough bandwidth allowed for this stream
-                                        log.info("Drop packet. Failed to acquire token or no video. sessionId={} stream={} count={}", sessionId, subscriberStream.getBroadcastStreamPublishName(), droppedPacketsCount);
+                                        log.info("Drop packet. Failed to acquire token or no video. sessionId={} stream={} count={}", sessionId, subscribedStreamName, droppedPacketsCount);
                                     }
                                     return;
                                 }
@@ -1480,14 +1485,14 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                                 // pending video messages and drop video packets until the queue is below the threshold.
                                 // only check for frame dropping if the codec supports it
                                 long pendingVideos = pendingVideoMessages();
-                                if (log.isTraceEnabled()) {
-                                    log.trace("Pending messages sessionId={} pending={} threshold={} sequential={} stream={}, count={}", new Object[] { sessionId, pendingVideos, maxPendingVideoFrames, numSequentialPendingVideoFrames, subscriberStream.getBroadcastStreamPublishName(), droppedPacketsCount });
+                                if (isTrace) {
+                                    log.trace("Pending messages sessionId={} stream={} pending={} threshold={} sequential={} dropped={}", new Object[] { sessionId, subscribedStreamName, pendingVideos, maxPendingVideoFrames, numSequentialPendingVideoFrames, droppedPacketsCount });
                                 }
                                 if (!videoFrameDropper.canSendPacket(rtmpMessage, pendingVideos)) {
                                     // drop frame as it depends on other frames that were dropped before
                                     droppedPacketsCount++;
                                     if (log.isInfoEnabled() && shouldLogPacketDrop()) {
-                                        log.info("Frame dropper says to drop packet. sessionId={} stream={} count={}", sessionId, subscriberStream.getBroadcastStreamPublishName(), droppedPacketsCount);
+                                        log.info("Frame dropper says to drop packet. sessionId={} stream={} dropped={}", sessionId, subscribedStreamName, droppedPacketsCount);
                                     }
                                     return;
                                 }
@@ -1501,7 +1506,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                                 if (pendingVideos > maxPendingVideoFrames || numSequentialPendingVideoFrames > maxSequentialPendingVideoFrames) {
                                     droppedPacketsCount++;
                                     if (log.isInfoEnabled() && shouldLogPacketDrop()) {
-                                        log.info("Drop packet. Pending above threshold. sessionId={} pending={} threshold={} sequential={} stream={} count={}", new Object[] { sessionId, pendingVideos, maxPendingVideoFrames, numSequentialPendingVideoFrames, subscriberStream.getBroadcastStreamPublishName(), droppedPacketsCount });
+                                        log.info("Drop packet. Pending above threshold. sessionId={} stream={} pending={} threshold={} sequential={} dropped={}", new Object[] { sessionId, subscribedStreamName, pendingVideos, maxPendingVideoFrames, numSequentialPendingVideoFrames, droppedPacketsCount });
                                     }
                                     // drop because the client has insufficient bandwidth
                                     long now = System.currentTimeMillis();
@@ -1570,7 +1575,7 @@ public final class PlayEngine implements IFilter, IPushableConsumer, IPipeConnec
                 return (Long) pendingRequest.getResult();
             }
         }
-        return 0;
+        return 0L;
     }
 
     /**
diff --git a/common/src/main/java/org/red5/server/stream/consumer/ConnectionConsumer.java b/common/src/main/java/org/red5/server/stream/consumer/ConnectionConsumer.java
index 40626455..a4d614e0 100644
--- a/common/src/main/java/org/red5/server/stream/consumer/ConnectionConsumer.java
+++ b/common/src/main/java/org/red5/server/stream/consumer/ConnectionConsumer.java
@@ -11,7 +11,6 @@ import java.util.Optional;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.mina.core.buffer.IoBuffer;
-import org.red5.server.api.stream.IClientStream;
 import org.red5.server.messaging.IMessage;
 import org.red5.server.messaging.IMessageComponent;
 import org.red5.server.messaging.IPipe;
@@ -150,7 +149,7 @@ public class ConnectionConsumer implements IPushableConsumer, IPipeConnectionLis
                 log.debug("Message has negative timestamp, flipping it to positive: {}", Integer.MIN_VALUE, eventTime);
                 msg.setTimestamp(eventTime);
             }
-            // get the data type
+            // get the data type (AMF)
             byte dataType = msg.getDataType();
             if (isTrace) {
                 log.trace("Data type: {} source type: {}", dataType, ((BaseEvent) msg).getSourceType());
@@ -273,12 +272,22 @@ public class ConnectionConsumer implements IPushableConsumer, IPipeConnectionLis
             if ("pendingCount".equals(serviceName)) {
                 oobCtrlMsg.setResult(conn.getPendingMessages());
             } else if ("pendingVideoCount".equals(serviceName)) {
+                /* 
+                 * This section relies on the messageSent call-back from Mina to update the pending counter
+                 * the logic does not work if RTMPE is used due to the marshalling. For now we will simply return 0
+                 * and the caller sending the oob will proceed. The pending video check was implemented to handle
+                 * flash player connections on slow links and is most likely irrelevant at this point.
+                 * 
                 IClientStream stream = conn.getStreamByChannelId(video.getId());
-                if (stream != null) {
-                    oobCtrlMsg.setResult(conn.getPendingVideoMessages(stream.getStreamId()));
+                log.trace("pending video count for video id: {} stream: {}", video.getId(), stream);
+                if (stream != null) { 
+                    oobCtrlMsg.setResult(conn.getPendingVideoMessages(stream.getStreamId())); 
                 } else {
                     oobCtrlMsg.setResult(0L);
                 }
+                */
+                // always return 0 if the connection is encrypted
+                oobCtrlMsg.setResult(0L);
             } else if ("writeDelta".equals(serviceName)) {
                 //TODO: Revisit the max stream value later
                 long maxStream = 120 * 1024;
diff --git a/io/pom.xml b/io/pom.xml
index 62ca70ca..882cd289 100644
--- a/io/pom.xml
+++ b/io/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.red5</groupId>
         <artifactId>red5-parent</artifactId>
-        <version>1.2.22</version>
+        <version>1.2.23</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>red5-io</artifactId>
diff --git a/pom.xml b/pom.xml
index 826c6f7c..6db44b78 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
     <name>Red5</name>
     <description>The Red5 server</description>
     <groupId>org.red5</groupId>
-    <version>1.2.22</version>
+    <version>1.2.23</version>
     <url>https://github.com/Red5/red5-server</url>
     <inceptionYear>2005</inceptionYear>
     <organization>
diff --git a/red5-eclipse-format.xml b/red5-eclipse-format.xml
index ea84cf1f..b74633c5 100644
--- a/red5-eclipse-format.xml
+++ b/red5-eclipse-format.xml
@@ -232,7 +232,7 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
@@ -280,7 +280,7 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
diff --git a/server/pom.xml b/server/pom.xml
index 2e911180..a1269576 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.red5</groupId>
         <artifactId>red5-parent</artifactId>
-        <version>1.2.22</version>
+        <version>1.2.23</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>red5-server</artifactId>
diff --git a/server/src/main/java/org/red5/server/net/rtmp/RTMPMinaIoHandler.java b/server/src/main/java/org/red5/server/net/rtmp/RTMPMinaIoHandler.java
index bb9775d2..24943136 100644
--- a/server/src/main/java/org/red5/server/net/rtmp/RTMPMinaIoHandler.java
+++ b/server/src/main/java/org/red5/server/net/rtmp/RTMPMinaIoHandler.java
@@ -192,7 +192,7 @@ public class RTMPMinaIoHandler extends IoHandlerAdapter {
     /** {@inheritDoc} */
     @Override
     public void messageSent(IoSession session, Object message) throws Exception {
-        log.trace("messageSent session: {} message: {}", session, message);
+        log.info("messageSent session: {} message: {}", session, message);
         String sessionId = (String) session.getAttribute(RTMPConnection.RTMP_SESSION_ID);
         if (isTrace) {
             log.trace("Message sent on session: {} id: {}", session.getId(), sessionId);
diff --git a/server/src/main/java/org/red5/server/net/rtmpe/RTMPEIoFilter.java b/server/src/main/java/org/red5/server/net/rtmpe/RTMPEIoFilter.java
index 18f840b4..a4ec50ca 100644
--- a/server/src/main/java/org/red5/server/net/rtmpe/RTMPEIoFilter.java
+++ b/server/src/main/java/org/red5/server/net/rtmpe/RTMPEIoFilter.java
@@ -35,14 +35,18 @@ public class RTMPEIoFilter extends IoFilterAdapter {
 
     private static final Logger log = LoggerFactory.getLogger(RTMPEIoFilter.class);
 
+    private static boolean isDebug = log.isDebugEnabled();
+
+    private static boolean isTrace = log.isTraceEnabled();
+
     @Override
     public void messageReceived(NextFilter nextFilter, IoSession session, Object obj) throws Exception {
-        if (log.isTraceEnabled()) {
+        if (isTrace) {
             log.trace("messageReceived nextFilter: {} session: {} message: {}", nextFilter, session, obj);
         }
         String sessionId = (String) session.getAttribute(RTMPConnection.RTMP_SESSION_ID);
         if (sessionId != null) {
-            if (log.isTraceEnabled()) {
+            if (isTrace) {
                 log.trace("RTMP Session id: {}", sessionId);
             }
             RTMPMinaConnection conn = (RTMPMinaConnection) RTMPConnManager.getInstance().getConnectionBySessionId(sessionId);
@@ -135,7 +139,7 @@ public class RTMPEIoFilter extends IoFilterAdapter {
                         } else {
                             Cipher cipher = (Cipher) session.getAttribute(RTMPConnection.RTMPE_CIPHER_IN);
                             if (cipher != null) {
-                                if (log.isDebugEnabled()) {
+                                if (isDebug) {
                                     log.debug("Decrypting message: {}", message);
                                 }
                                 byte[] encrypted = new byte[message.remaining()];
@@ -143,7 +147,7 @@ public class RTMPEIoFilter extends IoFilterAdapter {
                                 message.free();
                                 byte[] plain = cipher.update(encrypted);
                                 IoBuffer messageDecrypted = IoBuffer.wrap(plain);
-                                if (log.isDebugEnabled()) {
+                                if (isDebug) {
                                     log.debug("Receiving decrypted message: {}", messageDecrypted);
                                 }
                                 nextFilter.messageReceived(session, messageDecrypted);
@@ -168,14 +172,14 @@ public class RTMPEIoFilter extends IoFilterAdapter {
         log.trace("filterWrite nextFilter: {} session: {} request: {}", nextFilter, session, request);
         Cipher cipher = (Cipher) session.getAttribute(RTMPConnection.RTMPE_CIPHER_OUT);
         if (cipher == null) {
-            if (log.isTraceEnabled()) {
+            if (isTrace) {
                 log.trace("Writing message");
             }
             nextFilter.filterWrite(session, request);
         } else {
             IoBuffer message = (IoBuffer) request.getMessage();
             if (message.hasRemaining()) {
-                if (log.isDebugEnabled()) {
+                if (isDebug) {
                     log.debug("Encrypting message: {}", message);
                 }
                 byte[] plain = new byte[message.remaining()];
@@ -184,7 +188,7 @@ public class RTMPEIoFilter extends IoFilterAdapter {
                 // encrypt and write
                 byte[] encrypted = cipher.update(plain);
                 IoBuffer messageEncrypted = IoBuffer.wrap(encrypted);
-                if (log.isDebugEnabled()) {
+                if (isDebug) {
                     log.debug("Writing encrypted message: {}", messageEncrypted);
                 }
                 nextFilter.filterWrite(session, new EncryptedWriteRequest(request, messageEncrypted));
diff --git a/service/pom.xml b/service/pom.xml
index 783d6a90..bb5746c5 100644
--- a/service/pom.xml
+++ b/service/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.red5</groupId>
         <artifactId>red5-parent</artifactId>
-        <version>1.2.22</version>
+        <version>1.2.23</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>red5-service</artifactId>
-- 
GitLab