Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
e088cb43
authored
Sep 08, 2021
by
claincly
Committed by
Ian Baker
Sep 08, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Handle RTSP request by replying Method Not Allowed.
PiperOrigin-RevId: 395438728
parent
d9bc2231
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
120 additions
and
7 deletions
library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java
library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java
library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtil.java
library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java
library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspClient.java
View file @
e088cb43
...
@@ -34,6 +34,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
...
@@ -34,6 +34,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkState
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkState
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkStateNotNull
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkStateNotNull
;
import
static
com
.
google
.
common
.
base
.
Strings
.
nullToEmpty
;
import
static
com
.
google
.
common
.
base
.
Strings
.
nullToEmpty
;
import
static
java
.
lang
.
Math
.
max
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Handler
;
...
@@ -376,18 +377,23 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
...
@@ -376,18 +377,23 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
lastRequest
.
method
,
sessionId
,
lastRequestHeaders
,
lastRequest
.
uri
));
lastRequest
.
method
,
sessionId
,
lastRequestHeaders
,
lastRequest
.
uri
));
}
}
public
void
sendMethodNotAllowedResponse
(
int
cSeq
)
{
// RTSP status code 405: Method Not Allowed (RFC2326 Section 7.1.1).
sendResponse
(
new
RtspResponse
(
/* status= */
405
,
new
RtspHeaders
.
Builder
(
userAgent
,
sessionId
,
cSeq
).
build
()));
// The server could send a cSeq that is larger than the current stored cSeq. To maintain a
// monotonically increasing cSeq number, this.cSeq needs to be reset to server's cSeq + 1.
this
.
cSeq
=
max
(
this
.
cSeq
,
cSeq
+
1
);
}
private
RtspRequest
getRequestWithCommonHeaders
(
private
RtspRequest
getRequestWithCommonHeaders
(
@RtspRequest
.
Method
int
method
,
@RtspRequest
.
Method
int
method
,
@Nullable
String
sessionId
,
@Nullable
String
sessionId
,
Map
<
String
,
String
>
additionalHeaders
,
Map
<
String
,
String
>
additionalHeaders
,
Uri
uri
)
{
Uri
uri
)
{
RtspHeaders
.
Builder
headersBuilder
=
new
RtspHeaders
.
Builder
();
RtspHeaders
.
Builder
headersBuilder
=
new
RtspHeaders
.
Builder
(
userAgent
,
sessionId
,
cSeq
++);
headersBuilder
.
add
(
RtspHeaders
.
CSEQ
,
String
.
valueOf
(
cSeq
++));
headersBuilder
.
add
(
RtspHeaders
.
USER_AGENT
,
userAgent
);
if
(
sessionId
!=
null
)
{
headersBuilder
.
add
(
RtspHeaders
.
SESSION
,
sessionId
);
}
if
(
rtspAuthenticationInfo
!=
null
)
{
if
(
rtspAuthenticationInfo
!=
null
)
{
checkStateNotNull
(
rtspAuthUserInfo
);
checkStateNotNull
(
rtspAuthUserInfo
);
...
@@ -413,6 +419,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
...
@@ -413,6 +419,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
messageChannel
.
send
(
message
);
messageChannel
.
send
(
message
);
lastRequest
=
request
;
lastRequest
=
request
;
}
}
private
void
sendResponse
(
RtspResponse
response
)
{
List
<
String
>
message
=
RtspMessageUtil
.
serializeResponse
(
response
);
maybeLogMessage
(
message
);
messageChannel
.
send
(
message
);
}
}
}
private
final
class
MessageListener
implements
RtspMessageChannel
.
MessageListener
{
private
final
class
MessageListener
implements
RtspMessageChannel
.
MessageListener
{
...
@@ -436,6 +448,23 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
...
@@ -436,6 +448,23 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private
void
handleRtspMessage
(
List
<
String
>
message
)
{
private
void
handleRtspMessage
(
List
<
String
>
message
)
{
maybeLogMessage
(
message
);
maybeLogMessage
(
message
);
if
(
RtspMessageUtil
.
isRtspResponse
(
message
))
{
handleRtspResponse
(
message
);
}
else
{
handleRtspRequest
(
message
);
}
}
private
void
handleRtspRequest
(
List
<
String
>
message
)
{
// Handling RTSP requests on the client is optional (RFC2326 Section 10). Decline all
// requests with 'Method Not Allowed'.
messageSender
.
sendMethodNotAllowedResponse
(
Integer
.
parseInt
(
checkNotNull
(
RtspMessageUtil
.
parseRequest
(
message
).
headers
.
get
(
RtspHeaders
.
CSEQ
))));
}
private
void
handleRtspResponse
(
List
<
String
>
message
)
{
RtspResponse
response
=
RtspMessageUtil
.
parseResponse
(
message
);
RtspResponse
response
=
RtspMessageUtil
.
parseResponse
(
message
);
int
cSeq
=
Integer
.
parseInt
(
checkNotNull
(
response
.
headers
.
get
(
RtspHeaders
.
CSEQ
)));
int
cSeq
=
Integer
.
parseInt
(
checkNotNull
(
response
.
headers
.
get
(
RtspHeaders
.
CSEQ
)));
...
...
library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspHeaders.java
View file @
e088cb43
...
@@ -79,6 +79,23 @@ import java.util.Map;
...
@@ -79,6 +79,23 @@ import java.util.Map;
}
}
/**
/**
* Creates a new instance with common header values.
*
* @param userAgent The user agent string.
* @param sessionId The RTSP session ID; use {@code null} when the session is not yet set up.
* @param cSeq The RTSP cSeq sequence number.
*/
public
Builder
(
String
userAgent
,
@Nullable
String
sessionId
,
int
cSeq
)
{
this
();
add
(
USER_AGENT
,
userAgent
);
add
(
CSEQ
,
String
.
valueOf
(
cSeq
));
if
(
sessionId
!=
null
)
{
add
(
SESSION
,
sessionId
);
}
}
/**
* Creates a new instance to build upon the provided {@link RtspHeaders}.
* Creates a new instance to build upon the provided {@link RtspHeaders}.
*
*
* @param namesAndValuesBuilder A {@link ImmutableListMultimap.Builder} that this builder builds
* @param namesAndValuesBuilder A {@link ImmutableListMultimap.Builder} that this builder builds
...
...
library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtil.java
View file @
e088cb43
...
@@ -114,10 +114,15 @@ import java.util.regex.Pattern;
...
@@ -114,10 +114,15 @@ import java.util.regex.Pattern;
/**
/**
* Serializes an {@link RtspRequest} to an {@link ImmutableList} of strings.
* Serializes an {@link RtspRequest} to an {@link ImmutableList} of strings.
*
*
* <p>The {@link RtspRequest} must include the {@link RtspHeaders#CSEQ} header, or this method
* throws {@link IllegalArgumentException}.
*
* @param request The {@link RtspRequest}.
* @param request The {@link RtspRequest}.
* @return A list of the lines of the {@link RtspRequest}, without line terminators (CRLF).
* @return A list of the lines of the {@link RtspRequest}, without line terminators (CRLF).
*/
*/
public
static
ImmutableList
<
String
>
serializeRequest
(
RtspRequest
request
)
{
public
static
ImmutableList
<
String
>
serializeRequest
(
RtspRequest
request
)
{
checkArgument
(
request
.
headers
.
get
(
RtspHeaders
.
CSEQ
)
!=
null
);
ImmutableList
.
Builder
<
String
>
builder
=
new
ImmutableList
.
Builder
<>();
ImmutableList
.
Builder
<
String
>
builder
=
new
ImmutableList
.
Builder
<>();
// Request line.
// Request line.
builder
.
add
(
builder
.
add
(
...
@@ -140,10 +145,15 @@ import java.util.regex.Pattern;
...
@@ -140,10 +145,15 @@ import java.util.regex.Pattern;
/**
/**
* Serializes an {@link RtspResponse} to an {@link ImmutableList} of strings.
* Serializes an {@link RtspResponse} to an {@link ImmutableList} of strings.
*
*
* <p>The {@link RtspResponse} must include the {@link RtspHeaders#CSEQ} header, or this method
* throws {@link IllegalArgumentException}.
*
* @param response The {@link RtspResponse}.
* @param response The {@link RtspResponse}.
* @return A list of the lines of the {@link RtspResponse}, without line terminators (CRLF).
* @return A list of the lines of the {@link RtspResponse}, without line terminators (CRLF).
*/
*/
public
static
ImmutableList
<
String
>
serializeResponse
(
RtspResponse
response
)
{
public
static
ImmutableList
<
String
>
serializeResponse
(
RtspResponse
response
)
{
checkArgument
(
response
.
headers
.
get
(
RtspHeaders
.
CSEQ
)
!=
null
);
ImmutableList
.
Builder
<
String
>
builder
=
new
ImmutableList
.
Builder
<>();
ImmutableList
.
Builder
<
String
>
builder
=
new
ImmutableList
.
Builder
<>();
// Request line.
// Request line.
builder
.
add
(
builder
.
add
(
...
@@ -327,6 +337,16 @@ import java.util.regex.Pattern;
...
@@ -327,6 +337,16 @@ import java.util.regex.Pattern;
||
STATUS_LINE_PATTERN
.
matcher
(
line
).
matches
();
||
STATUS_LINE_PATTERN
.
matcher
(
line
).
matches
();
}
}
/**
* Returns whether the RTSP message is an RTSP response.
*
* @param lines The non-empty list of received lines, with line terminators removed.
* @return Whether the lines represent an RTSP response.
*/
public
static
boolean
isRtspResponse
(
List
<
String
>
lines
)
{
return
STATUS_LINE_PATTERN
.
matcher
(
lines
.
get
(
0
)).
matches
();
}
/** Returns the lines in an RTSP message body split by the line terminator used in body. */
/** Returns the lines in an RTSP message body split by the line terminator used in body. */
public
static
String
[]
splitRtspMessageBody
(
String
body
)
{
public
static
String
[]
splitRtspMessageBody
(
String
body
)
{
return
Util
.
split
(
body
,
body
.
contains
(
CRLF
)
?
CRLF
:
LF
);
return
Util
.
split
(
body
,
body
.
contains
(
CRLF
)
?
CRLF
:
LF
);
...
...
library/rtsp/src/test/java/com/google/android/exoplayer2/source/rtsp/RtspMessageUtilTest.java
View file @
e088cb43
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
package
com
.
google
.
android
.
exoplayer2
.
source
.
rtsp
;
package
com
.
google
.
android
.
exoplayer2
.
source
.
rtsp
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertThrows
;
import
android.net.Uri
;
import
android.net.Uri
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
...
@@ -336,6 +337,52 @@ public final class RtspMessageUtilTest {
...
@@ -336,6 +337,52 @@ public final class RtspMessageUtilTest {
}
}
@Test
@Test
public
void
serialize_requestWithoutCseqHeader_throwsIllegalArgumentException
()
{
RtspRequest
request
=
new
RtspRequest
(
Uri
.
parse
(
"rtsp://127.0.0.1/test.mkv/track1"
),
RtspRequest
.
METHOD_OPTIONS
,
RtspHeaders
.
EMPTY
,
/* messageBody= */
""
);
assertThrows
(
IllegalArgumentException
.
class
,
()
->
RtspMessageUtil
.
serializeRequest
(
request
));
}
@Test
public
void
serialize_responseWithoutCseqHeader_throwsIllegalArgumentException
()
{
RtspResponse
response
=
new
RtspResponse
(
/* status= */
200
,
RtspHeaders
.
EMPTY
);
assertThrows
(
IllegalArgumentException
.
class
,
()
->
RtspMessageUtil
.
serializeResponse
(
response
));
}
@Test
public
void
isRtspResponse_withSuccessfulRtspResponse_returnsTrue
()
{
List
<
String
>
responseLines
=
Arrays
.
asList
(
"RTSP/1.0 200 OK"
,
"CSeq: 2"
,
"Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER"
,
""
);
assertThat
(
RtspMessageUtil
.
isRtspResponse
(
responseLines
)).
isTrue
();
}
@Test
public
void
isRtspResponse_withUnsuccessfulRtspResponse_returnsTrue
()
{
List
<
String
>
responseLines
=
Arrays
.
asList
(
"RTSP/1.0 405 Method Not Allowed"
,
"CSeq: 2"
,
""
);
assertThat
(
RtspMessageUtil
.
isRtspResponse
(
responseLines
)).
isTrue
();
}
@Test
public
void
isRtspResponse_withRtspRequest_returnsFalse
()
{
List
<
String
>
requestLines
=
Arrays
.
asList
(
"OPTIONS rtsp://localhost:554/foo.bar RTSP/1.0"
,
"CSeq: 2"
,
""
);
assertThat
(
RtspMessageUtil
.
isRtspResponse
(
requestLines
)).
isFalse
();
}
@Test
public
void
serialize_failedResponse_succeeds
()
{
public
void
serialize_failedResponse_succeeds
()
{
RtspResponse
response
=
RtspResponse
response
=
new
RtspResponse
(
new
RtspResponse
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment