diff --git a/client/pom.xml b/client/pom.xml
index 3e8ecd251..be18970de 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -3,7 +3,7 @@
org.red5
red5-parent
- 1.3.5
+ 1.3.6
4.0.0
red5-client
diff --git a/client/src/main/java/org/red5/client/Red5Client.java b/client/src/main/java/org/red5/client/Red5Client.java
index ff0a082e2..d7e8bbbf9 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.3.5";
+ public static final String VERSION = "Red5 Client 1.3.6";
/**
* 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 038fe0677..990fe247a 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -3,7 +3,7 @@
org.red5
red5-parent
- 1.3.5
+ 1.3.6
4.0.0
red5-server-common
@@ -124,7 +124,7 @@
net.engio
mbassador
- 1.3.5
+ 1.3.6
-->
junit
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 997eca6e1..ffef3ba68 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.3.5";
+ public static final String VERSION = "Red5 Server 1.3.6";
/**
* Server version for fmsVer requests
*/
- public static final String FMS_VERSION = "RED5/1,3,5,0";
+ public static final String FMS_VERSION = "RED5/1,3,6,0";
/**
* Server capabilities
diff --git a/common/src/main/java/org/red5/server/stream/AbstractClientStream.java b/common/src/main/java/org/red5/server/stream/AbstractClientStream.java
index f43282e54..00e5f0a71 100644
--- a/common/src/main/java/org/red5/server/stream/AbstractClientStream.java
+++ b/common/src/main/java/org/red5/server/stream/AbstractClientStream.java
@@ -72,7 +72,8 @@ public void setConnection(IStreamCapableConnection conn) {
* @return Stream capable connection object
*/
public IStreamCapableConnection getConnection() {
- return conn.get();
+ // prevent NPE on first call
+ return conn != null ? conn.get() : null;
}
/** {@inheritDoc} */
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 053de003e..c0f609d23 100755
--- a/common/src/main/java/org/red5/server/stream/PlayEngine.java
+++ b/common/src/main/java/org/red5/server/stream/PlayEngine.java
@@ -483,7 +483,7 @@ public void execute(ISchedulingService service) {
sendStreamNotFoundStatus(item);
throw new StreamNotFoundException(itemName);
}
- //continue with common play processes (live and vod)
+ // continue with common play processes (live and vod)
if (sendNotifications) {
if (withReset) {
sendReset();
diff --git a/common/src/main/java/org/red5/server/stream/PlaylistSubscriberStream.java b/common/src/main/java/org/red5/server/stream/PlaylistSubscriberStream.java
index 11d06608c..db8b8079c 100644
--- a/common/src/main/java/org/red5/server/stream/PlaylistSubscriberStream.java
+++ b/common/src/main/java/org/red5/server/stream/PlaylistSubscriberStream.java
@@ -790,10 +790,17 @@ public long getCreationTime() {
/** {@inheritDoc} */
public int getCurrentTimestamp() {
int lastMessageTs = engine.getLastMessageTimestamp();
+ /* XXX(paul) I think this is incorrect
if (lastMessageTs >= 0) {
return 0;
}
return lastMessageTs;
+ */
+ // XXX(paul) this seems to be what the correct logic would be
+ if (lastMessageTs >= 0) {
+ return lastMessageTs;
+ }
+ return 0;
}
/** {@inheritDoc} */
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 65d2c3529..2161c8293 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
@@ -142,11 +142,9 @@ public void pushMessage(IPipe pipe, IMessage message) {
int eventTime = msg.getTimestamp();
log.debug("Message timestamp: {}", eventTime);
if (eventTime < 0) {
- //eventTime += Integer.MIN_VALUE;
- //log.debug("Message has negative timestamp, applying {} offset: {}", Integer.MIN_VALUE, eventTime);
- // everyone seems to prefer positive timestamps
- eventTime += (eventTime * -1);
- log.debug("Message has negative timestamp, flipping it to positive: {}", Integer.MIN_VALUE, eventTime);
+ // handle roll-over -1 is top of the range when keeping things positive
+ eventTime ^= Integer.MIN_VALUE;
+ log.debug("Message has negative timestamp, applying {} ts: {}", Integer.MIN_VALUE, eventTime);
msg.setTimestamp(eventTime);
}
// get the data type (AMF)
diff --git a/common/src/test/java/org/red5/server/stream/consumer/TestConnectionConsumer.java b/common/src/test/java/org/red5/server/stream/consumer/TestConnectionConsumer.java
index f0def59b8..f12e889dc 100644
--- a/common/src/test/java/org/red5/server/stream/consumer/TestConnectionConsumer.java
+++ b/common/src/test/java/org/red5/server/stream/consumer/TestConnectionConsumer.java
@@ -23,16 +23,27 @@ public class TestConnectionConsumer {
@Before
public void setUp() {
- connection = new RTMPMinaConnection();
- channel = new Channel(connection, 1);
+ connection = new RTMPMinaConnection() {
+
+ @Override
+ public Channel getChannel(int channelId) {
+ Channel channel = new Channel(this, channelId);
+ return channel;
+ }
+
+ };
+ channel = connection.getChannel(1);
underTest = new ConnectionConsumer(connection, channel, channel, channel);
}
@Test
public void testNegativeTimestampsAreRolledOver() {
log.debug("\n testNegativeTimestampsAreRolledOver");
+ // https://www.rfc-editor.org/rfc/rfc1982
+ log.debug("\n max: {} min: {} 0:{} -1:{}", Integer.toHexString(Integer.MAX_VALUE), Integer.toHexString(Integer.MIN_VALUE), Integer.toHexString(0), Integer.toHexString(-1));
+
VideoData videoData1 = new VideoData();
- videoData1.setTimestamp(-1);
+ videoData1.setTimestamp(-1); // maximum timestamp value 0xffffffff expect 2147483647
underTest.pushMessage(null, RTMPMessage.build(videoData1));
assertEquals(Integer.MAX_VALUE, videoData1.getTimestamp());
diff --git a/io/pom.xml b/io/pom.xml
index 9c198d7c7..d7f9689b7 100644
--- a/io/pom.xml
+++ b/io/pom.xml
@@ -3,7 +3,7 @@
org.red5
red5-parent
- 1.3.5
+ 1.3.6
4.0.0
red5-io
diff --git a/pom.xml b/pom.xml
index 6256ddfe7..cdddd7ce8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
Red5
The Red5 server
org.red5
- 1.3.5
+ 1.3.6
https://github.com/Red5/red5-server
2005
diff --git a/server/pom.xml b/server/pom.xml
index e79650be1..ff89d6126 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -3,7 +3,7 @@
org.red5
red5-parent
- 1.3.5
+ 1.3.6
4.0.0
red5-server
diff --git a/server/src/main/java/org/red5/net/websocket/WebSocketScopeManager.java b/server/src/main/java/org/red5/net/websocket/WebSocketScopeManager.java
index d303ba209..e2cf80ac7 100644
--- a/server/src/main/java/org/red5/net/websocket/WebSocketScopeManager.java
+++ b/server/src/main/java/org/red5/net/websocket/WebSocketScopeManager.java
@@ -163,7 +163,7 @@ public boolean addWebSocketScope(WebSocketScope webSocketScope) {
try {
// ping connected websocket
if (wsConn.isConnected()) {
- log.debug("pinging ws: {} on scope: {}", wsConn.getWsSessionId(), sName);
+ log.trace("pinging ws: {} on scope: {}", wsConn.getWsSessionId(), sName);
try {
wsConn.sendPing(PING_BYTES);
} catch (Exception e) {
diff --git a/server/src/main/java/org/red5/net/websocket/server/WsHttpUpgradeHandler.java b/server/src/main/java/org/red5/net/websocket/server/WsHttpUpgradeHandler.java
index 183942fad..8024445b1 100644
--- a/server/src/main/java/org/red5/net/websocket/server/WsHttpUpgradeHandler.java
+++ b/server/src/main/java/org/red5/net/websocket/server/WsHttpUpgradeHandler.java
@@ -38,6 +38,9 @@ public class WsHttpUpgradeHandler implements InternalHttpUpgradeHandler {
private Logger log = LoggerFactory.getLogger(WsHttpUpgradeHandler.class); // must not be static
+ private final boolean isTrace = log.isTraceEnabled();
+
+ @SuppressWarnings("unused")
private final boolean isDebug = log.isDebugEnabled();
private static final StringManager sm = StringManager.getManager(WsHttpUpgradeHandler.class);
@@ -104,6 +107,7 @@ public void preInit(Endpoint ep, EndpointConfig endpointConfig, DefaultWsServerC
}
}
+ @SuppressWarnings("deprecation")
@Override
public void init(WebConnection connection) {
if (ep == null) {
@@ -125,52 +129,52 @@ public void init(WebConnection connection) {
try {
// instance a remote endpoint server
wsRemoteEndpointServer = new WsRemoteEndpointImplServer(socketWrapper, upgradeInfo);
- if (isDebug) {
- log.debug("New connection 1 {}", wsRemoteEndpointServer);
+ if (isTrace) {
+ log.trace("New connection 1 {}", wsRemoteEndpointServer);
}
- if (isDebug) {
- log.debug("WS session pre-ctor - wsRemoteEndpointServer: {}, webSocketContainer: {}, handshakeRequest.getRequestURI: {}, handshakeRequest.getParameterMap: {}, handshakeRequest.getQueryString: {}, handshakeRequest.getUserPrincipal: {}, httpSessionId: {}, negotiatedExtensions: {}, subProtocol: {}, pathParameters: {}, secure: {}, endpointConfig: {}", wsRemoteEndpointServer, webSocketContainer,
+ if (isTrace) {
+ log.trace("WS session pre-ctor - wsRemoteEndpointServer: {}, webSocketContainer: {}, handshakeRequest.getRequestURI: {}, handshakeRequest.getParameterMap: {}, handshakeRequest.getQueryString: {}, handshakeRequest.getUserPrincipal: {}, httpSessionId: {}, negotiatedExtensions: {}, subProtocol: {}, pathParameters: {}, secure: {}, endpointConfig: {}", wsRemoteEndpointServer, webSocketContainer,
handshakeRequest.getRequestURI(), handshakeRequest.getParameterMap(), handshakeRequest.getQueryString(), handshakeRequest.getUserPrincipal(), httpSessionId, negotiatedExtensions, subProtocol, pathParameters, secure, endpointConfig);
}
// deprecated version
wsSession = new WsSession(ep, wsRemoteEndpointServer, webSocketContainer, handshakeRequest.getRequestURI(), handshakeRequest.getParameterMap(), handshakeRequest.getQueryString(), handshakeRequest.getUserPrincipal(), httpSessionId, negotiatedExtensions, subProtocol, pathParameters, secure, endpointConfig);
// newest ctor
//wsSession = new WsSession(wsRemoteEndpointServer, webSocketContainer, handshakeRequest.getRequestURI(), handshakeRequest.getParameterMap(), handshakeRequest.getQueryString(), handshakeRequest.getUserPrincipal(), httpSessionId, negotiatedExtensions, subProtocol, pathParameters, secure, endpointConfig);
- if (isDebug) {
- log.debug("New connection 2 {}", wsSession);
+ if (isTrace) {
+ log.trace("New connection 2 {}", wsSession);
}
wsFrame = new WsFrameServer(socketWrapper, upgradeInfo, wsSession, transformation, applicationClassLoader);
- if (isDebug) {
- log.debug("New connection 3 {}", wsFrame);
+ if (isTrace) {
+ log.trace("New connection 3 {}", wsFrame);
}
// WsFrame adds the necessary final transformations. Copy the completed transformation chain to the remote end point.
wsRemoteEndpointServer.setTransformation(wsFrame.getTransformation());
- if (isDebug) {
- log.debug("New connection 4");
+ if (isTrace) {
+ log.trace("New connection 4");
}
// get the ws scope manager from user props
WebSocketScopeManager manager = (WebSocketScopeManager) endpointConfig.getUserProperties().get(WSConstants.WS_MANAGER);
- if (isDebug) {
- log.debug("New connection 5");
+ if (isTrace) {
+ log.trace("New connection 5");
}
// get ws scope from user props
WebSocketScope scope = (WebSocketScope) endpointConfig.getUserProperties().get(WSConstants.WS_SCOPE);
- if (isDebug) {
- log.debug("New connection 6 - Scope: {} WS session: {}", scope, wsSession);
+ if (isTrace) {
+ log.trace("New connection 6 - Scope: {} WS session: {}", scope, wsSession);
}
// create a ws connection instance
WebSocketConnection conn = new WebSocketConnection(scope, wsSession);
// in debug check since WebSocketConnection.toString is a tiny bit expensive
- if (isDebug) {
- log.debug("New connection 7: {}", conn);
+ if (isTrace) {
+ log.trace("New connection 7: {}", conn);
}
// set ip and port
conn.setAttribute(WSConstants.WS_HEADER_REMOTE_IP, socketWrapper.getRemoteAddr());
conn.setAttribute(WSConstants.WS_HEADER_REMOTE_PORT, socketWrapper.getRemotePort());
// add the request headers
conn.setHeaders(handshakeRequest.getHeaders());
- if (isDebug) {
- log.debug("New connection 8: {}", conn);
+ if (isTrace) {
+ log.trace("New connection 8: {}", conn);
}
// add the connection to the user props
endpointConfig.getUserProperties().put(WSConstants.WS_CONNECTION, conn);
@@ -180,14 +184,14 @@ public void init(WebConnection connection) {
conn.setConnected();
// fire endpoint handler
ep.onOpen(wsSession, endpointConfig);
- if (isDebug) {
- log.debug("New connection 9: endpoint opened");
+ if (isTrace) {
+ log.trace("New connection 9: endpoint opened");
}
// get the endpoint path to use in registration since we're a server
String path = ((ServerEndpointConfig) endpointConfig).getPath();
webSocketContainer.registerSession(path, wsSession);
- if (isDebug) {
- log.debug("New connection 10: session registered");
+ if (isTrace) {
+ log.trace("New connection 10: session registered");
}
// add the connection to the manager
manager.addConnection(conn);
diff --git a/server/src/test/java/org/red5/server/scope/ScopeTest.java b/server/src/test/java/org/red5/server/scope/ScopeTest.java
index cbe5f99ea..7c403b01b 100644
--- a/server/src/test/java/org/red5/server/scope/ScopeTest.java
+++ b/server/src/test/java/org/red5/server/scope/ScopeTest.java
@@ -16,7 +16,6 @@
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
diff --git a/service/pom.xml b/service/pom.xml
index b612c205c..9fbb93180 100644
--- a/service/pom.xml
+++ b/service/pom.xml
@@ -3,7 +3,7 @@
org.red5
red5-parent
- 1.3.5
+ 1.3.6
4.0.0
red5-service