summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/rtsp/MyHandler.h
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2011-02-15 10:39:48 -0800
committerAndreas Huber <andih@google.com>2011-02-15 12:00:07 -0800
commitdc468c5f9d72ce54de0070493e9a23efb8907e06 (patch)
tree60bc0bbce4d9d765f13235d702443fecbe7e03ea /media/libstagefright/rtsp/MyHandler.h
parentf1958f9442bc937e1f8c8d9175901500b944b021 (diff)
downloadframeworks_av-dc468c5f9d72ce54de0070493e9a23efb8907e06.zip
frameworks_av-dc468c5f9d72ce54de0070493e9a23efb8907e06.tar.gz
frameworks_av-dc468c5f9d72ce54de0070493e9a23efb8907e06.tar.bz2
Work around several issues with non-compliant RTSP servers.
In this particular case these RTSP servers were implemented as local services, retransmitting live streams via a local RTSP server instance. They picked wrong rtp/rtcp port pairs (odd rtp port), blank lines in the session description, wrong case of the format description, relative base URLs... Change-Id: I63fa90ca2398f19e8b52c147248bd2c5c2372426 related-to-bug: 3452103
Diffstat (limited to 'media/libstagefright/rtsp/MyHandler.h')
-rw-r--r--media/libstagefright/rtsp/MyHandler.h99
1 files changed, 78 insertions, 21 deletions
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index ba7c1b2..e6ae52b 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -248,7 +248,7 @@ struct MyHandler : public AHandler {
// In case we're behind NAT, fire off two UDP packets to the remote
// rtp/rtcp ports to poke a hole into the firewall for future incoming
// packets. We're going to send an RR/SDES RTCP packet to both of them.
- void pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) {
+ bool pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) {
AString source;
AString server_port;
if (!GetAttribute(transport.c_str(),
@@ -257,16 +257,25 @@ struct MyHandler : public AHandler {
|| !GetAttribute(transport.c_str(),
"server_port",
&server_port)) {
- return;
+ return false;
}
int rtpPort, rtcpPort;
if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2
|| rtpPort <= 0 || rtpPort > 65535
|| rtcpPort <=0 || rtcpPort > 65535
- || rtcpPort != rtpPort + 1
- || (rtpPort & 1) != 0) {
- return;
+ || rtcpPort != rtpPort + 1) {
+ LOGE("Server picked invalid RTP/RTCP port pair %s,"
+ " RTP port must be even, RTCP port must be one higher.",
+ server_port.c_str());
+
+ return false;
+ }
+
+ if (rtpPort & 1) {
+ LOGW("Server picked an odd RTP port, it should've picked an "
+ "even one, we'll let it pass for now, but this may break "
+ "in the future.");
}
struct sockaddr_in addr;
@@ -275,7 +284,12 @@ struct MyHandler : public AHandler {
addr.sin_addr.s_addr = inet_addr(source.c_str());
if (addr.sin_addr.s_addr == INADDR_NONE) {
- return;
+ return true;
+ }
+
+ if (IN_LOOPBACK(ntohl(addr.sin_addr.s_addr))) {
+ // No firewalls to traverse on the loopback interface.
+ return true;
}
// Make up an RR/SDES RTCP packet.
@@ -289,16 +303,26 @@ struct MyHandler : public AHandler {
ssize_t n = sendto(
rtpSocket, buf->data(), buf->size(), 0,
(const sockaddr *)&addr, sizeof(addr));
- CHECK_EQ(n, (ssize_t)buf->size());
+
+ if (n < (ssize_t)buf->size()) {
+ LOGE("failed to poke a hole for RTP packets");
+ return false;
+ }
addr.sin_port = htons(rtcpPort);
n = sendto(
rtcpSocket, buf->data(), buf->size(), 0,
(const sockaddr *)&addr, sizeof(addr));
- CHECK_EQ(n, (ssize_t)buf->size());
+
+ if (n < (ssize_t)buf->size()) {
+ LOGE("failed to poke a hole for RTCP packets");
+ return false;
+ }
LOGV("successfully poked holes.");
+
+ return true;
}
virtual void onMessageReceived(const sp<AMessage> &msg) {
@@ -381,6 +405,7 @@ struct MyHandler : public AHandler {
response->mContent->size());
if (!mSessionDesc->isValid()) {
+ LOGE("Failed to parse session description.");
result = ERROR_MALFORMED;
} else {
ssize_t i = response->mHeaders.indexOfKey("content-base");
@@ -395,6 +420,25 @@ struct MyHandler : public AHandler {
}
}
+ if (!mBaseURL.startsWith("rtsp://")) {
+ // Some misbehaving servers specify a relative
+ // URL in one of the locations above, combine
+ // it with the absolute session URL to get
+ // something usable...
+
+ LOGW("Server specified a non-absolute base URL"
+ ", combining it with the session URL to "
+ "get something usable...");
+
+ AString tmp;
+ CHECK(MakeURL(
+ mSessionURL.c_str(),
+ mBaseURL.c_str(),
+ &tmp));
+
+ mBaseURL = tmp;
+ }
+
CHECK_GT(mSessionDesc->countTracks(), 1u);
setupTrack(1);
}
@@ -455,17 +499,22 @@ struct MyHandler : public AHandler {
if (!track->mUsingInterleavedTCP) {
AString transport = response->mHeaders.valueAt(i);
- pokeAHole(track->mRTPSocket,
- track->mRTCPSocket,
- transport);
+ if (!pokeAHole(
+ track->mRTPSocket,
+ track->mRTCPSocket,
+ transport)) {
+ result = UNKNOWN_ERROR;
+ }
}
- mRTPConn->addStream(
- track->mRTPSocket, track->mRTCPSocket,
- mSessionDesc, index,
- notify, track->mUsingInterleavedTCP);
+ if (result == OK) {
+ mRTPConn->addStream(
+ track->mRTPSocket, track->mRTCPSocket,
+ mSessionDesc, index,
+ notify, track->mUsingInterleavedTCP);
- mSetupTracksSuccessful = true;
+ mSetupTracksSuccessful = true;
+ }
}
}
@@ -853,17 +902,16 @@ struct MyHandler : public AHandler {
case 'tiou':
{
if (!mReceivedFirstRTCPPacket) {
- if (mTryFakeRTCP) {
- LOGW("Never received any data, disconnecting.");
- (new AMessage('abor', id()))->post();
- } else if (mTryTCPInterleaving && mReceivedFirstRTPPacket) {
+ if (mReceivedFirstRTPPacket && !mTryFakeRTCP) {
LOGW("We received RTP packets but no RTCP packets, "
"using fake timestamps.");
mTryFakeRTCP = true;
mReceivedFirstRTCPPacket = true;
- } else {
+
+ fakeTimestamps();
+ } else if (!mReceivedFirstRTPPacket && !mTryTCPInterleaving) {
LOGW("Never received any data, switching transports.");
mTryTCPInterleaving = true;
@@ -871,6 +919,9 @@ struct MyHandler : public AHandler {
sp<AMessage> msg = new AMessage('abor', id());
msg->setInt32("reconnect", true);
msg->post();
+ } else {
+ LOGW("Never received any data, disconnecting.");
+ (new AMessage('abor', id()))->post();
}
}
break;
@@ -1158,6 +1209,12 @@ private:
return true;
}
+ void fakeTimestamps() {
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ onTimeUpdate(i, 0, 0ll);
+ }
+ }
+
void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) {
LOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = 0x%016llx",
trackIndex, rtpTime, ntpTime);