diff options
author | Andreas Huber <andih@google.com> | 2011-01-18 15:35:35 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-01-18 15:35:35 -0800 |
commit | de16890e98cdd241398ed155cd47daf061584a77 (patch) | |
tree | 8273f7629019c9a38090c485b550d20b1b8969e2 /media/libstagefright | |
parent | 31389148f4ab7587e150f4043b7379eaefe2af2b (diff) | |
parent | 368ef16787c3fe2334dadc767e7418b610c83cbd (diff) | |
download | frameworks_av-de16890e98cdd241398ed155cd47daf061584a77.zip frameworks_av-de16890e98cdd241398ed155cd47daf061584a77.tar.gz frameworks_av-de16890e98cdd241398ed155cd47daf061584a77.tar.bz2 |
Merge "Apparently our native TCP sockets do not return an error from blocking "connect"" into honeycomb
Diffstat (limited to 'media/libstagefright')
-rw-r--r-- | media/libstagefright/HTTPStream.cpp | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp index e7f00aa..057868c 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; |