am e9a00235: Merge "DO NOT MERGE: Apparently our native TCP sockets do not return an error from blocking "connect"" into gingerbread

* commit 'e9a00235c102d198a702bc665b2ea5b5e8c4bc07':
  DO NOT MERGE: Apparently our native TCP sockets do not return an error from blocking "connect"
This commit is contained in:
Andreas Huber
2011-01-19 08:23:47 -08:00
committed by Android Git Automerger

View File

@@ -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;