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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user