summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2011-01-18 15:26:40 -0800
committerAndreas Huber <andih@google.com>2011-01-18 15:52:31 -0800
commitf4c056aeacad2dac60a83ccd7928bfeaa9d6ddf6 (patch)
tree33c73abc7fb95445121cc4595a863ed45000b29e /media
parent95304d5488ba465f19cc788f1c7394218c2ea2d1 (diff)
downloadframeworks_av-f4c056aeacad2dac60a83ccd7928bfeaa9d6ddf6.zip
frameworks_av-f4c056aeacad2dac60a83ccd7928bfeaa9d6ddf6.tar.gz
frameworks_av-f4c056aeacad2dac60a83ccd7928bfeaa9d6ddf6.tar.bz2
DO NOT MERGE: Apparently our native TCP sockets do not return an error from blocking "connect"
if the network interface is shutdown while connecting. Change-Id: I168c6026de24812efa9b7e607a9eb83efded8c1f related-to-bug: 3362836
Diffstat (limited to 'media')
-rw-r--r--media/libstagefright/HTTPStream.cpp85
1 files changed, 81 insertions, 4 deletions
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
index ccc6a34..7194614 100644
--- a/media/libstagefright/HTTPStream.cpp
+++ b/media/libstagefright/HTTPStream.cpp
@@ -25,13 +25,14 @@
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/foundation/ADebug.h>
namespace android {
@@ -47,6 +48,82 @@ HTTPStream::~HTTPStream() {
disconnect();
}
+static bool MakeSocketBlocking(int s, bool blocking) {
+ // Make socket non-blocking.
+ int flags = fcntl(s, F_GETFL, 0);
+ if (flags == -1) {
+ return false;
+ }
+
+ if (blocking) {
+ flags &= ~O_NONBLOCK;
+ } else {
+ flags |= O_NONBLOCK;
+ }
+
+ return fcntl(s, F_SETFL, flags) != -1;
+}
+
+static status_t MyConnect(
+ int s, const struct sockaddr *addr, socklen_t addrlen) {
+ status_t result = UNKNOWN_ERROR;
+
+ MakeSocketBlocking(s, false);
+
+ if (connect(s, addr, addrlen) == 0) {
+ result = OK;
+ } else if (errno != EINPROGRESS) {
+ result = -errno;
+ } else {
+ for (;;) {
+ fd_set rs, ws;
+ FD_ZERO(&rs);
+ FD_ZERO(&ws);
+ FD_SET(s, &rs);
+ FD_SET(s, &ws);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000ll;
+
+ int nfds = ::select(s + 1, &rs, &ws, NULL, &tv);
+
+ if (nfds < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ result = -errno;
+ break;
+ }
+
+ if (FD_ISSET(s, &ws) && !FD_ISSET(s, &rs)) {
+ result = OK;
+ break;
+ }
+
+ if (FD_ISSET(s, &rs) || FD_ISSET(s, &ws)) {
+ // Get the pending error.
+ int error = 0;
+ socklen_t errorLen = sizeof(error);
+ if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &errorLen) == -1) {
+ // Couldn't get the real error, so report why not.
+ result = -errno;
+ } else {
+ result = -error;
+ }
+ break;
+ }
+
+ // Timeout expired. Try again.
+ }
+ }
+
+ MakeSocketBlocking(s, true);
+
+ return result;
+}
+
status_t HTTPStream::connect(const char *server, int port) {
Mutex::Autolock autoLock(mLock);
@@ -82,7 +159,7 @@ status_t HTTPStream::connect(const char *server, int port) {
addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
- int res = ::connect(s, (const struct sockaddr *)&addr, sizeof(addr));
+ status_t res = MyConnect(s, (const struct sockaddr *)&addr, sizeof(addr));
mLock.lock();
@@ -90,12 +167,12 @@ status_t HTTPStream::connect(const char *server, int port) {
return UNKNOWN_ERROR;
}
- if (res < 0) {
+ if (res != OK) {
close(mSocket);
mSocket = -1;
mState = READY;
- return UNKNOWN_ERROR;
+ return res;
}
mState = CONNECTED;