void ARTSPConnection::onReceiveResponse() { mReceiveResponseEventPending = false; if (mState != CONNECTED) { return; } struct timeval tv; tv.tv_sec = 0; tv.tv_usec = kSelectTimeoutUs; fd_set rs; FD_ZERO(&rs); FD_SET(mSocket, &rs); int res = select(mSocket + 1, &rs, NULL, NULL, &tv); if (res == 1) { MakeSocketBlocking(mSocket, true); bool success = receiveRTSPReponse(); MakeSocketBlocking(mSocket, false); if (!success) { // Something horrible, irreparable has happened. flushPendingRequests(); return; } } postReceiveReponseEvent(); }
int MyConnect( int s, const struct sockaddr *addr, socklen_t addrlen) { int 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; }
bool ARTSPConnection::createSocketAndConnect(void *res, unsigned port,const sp<AMessage> &reply) { int32_t addrTried = mConnectionTimes; for (struct addrinfo *result = (struct addrinfo *)res; result; result = result->ai_next) { if (addrTried != 0) { // skip the address which has been tried addrTried--; continue; } char ipstr[INET6_ADDRSTRLEN]; int ipver; void *sptr; switch (result->ai_family) { case AF_INET: sptr = &((struct sockaddr_in *)result->ai_addr)->sin_addr; ((struct sockaddr_in *)result->ai_addr)->sin_port = htons(port); reply->setInt32("server-ip", ntohl(((struct in_addr *)sptr)->s_addr)); ipver = 4; break; case AF_INET6: sptr = &((struct sockaddr_in6 *)result->ai_addr)->sin6_addr; ((struct sockaddr_in6 *)result->ai_addr)->sin6_port = htons(port); ipver = 6; break; default: ALOGW("Skipping unknown protocol family %d", result->ai_family); mConnectionTimes++; continue; } inet_ntop(result->ai_family, sptr, ipstr, sizeof(ipstr)); ALOGV("Connecting to IPv%d: %s", ipver, ipstr); mSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (mUIDValid) { HTTPBase::RegisterSocketUserTag(mSocket, mUID, (uint32_t)*(uint32_t*) "RTSP"); HTTPBase::RegisterSocketUserMark(mSocket, mUID); } MakeSocketBlocking(mSocket, false); int err = ::connect(mSocket, result->ai_addr, result->ai_addrlen); if (err == 0) { ALOGV("Connected to (%s)", ipstr); reply->setInt32("result", OK); mState = CONNECTED; mNextCSeq = 1; postReceiveReponseEvent(); reply->post(); freeaddrinfo((struct addrinfo *)res); mAddrHeader = NULL; return true; } if (errno == EINPROGRESS) { ALOGV("Connection to %s in progress", ipstr); sp<AMessage> msg = new AMessage(kWhatCompleteConnection, id()); msg->setMessage("reply", reply); ALOGV("setting ipversion:%d", ipver); msg->setInt32("ipversion", ipver); msg->setInt32("connection-id", mConnectionID); msg->setInt32("port", port); msg->post(); return true; } if (mUIDValid) { HTTPBase::UnRegisterSocketUserTag(mSocket); HTTPBase::UnRegisterSocketUserMark(mSocket); } close(mSocket); ALOGV("Connection err %d, (%s)", errno, strerror(errno)); mConnectionTimes++; } return false; }
void ARTSPConnection::onConnect(const sp<AMessage> &msg) { ++mConnectionID; if (mState != DISCONNECTED) { close(mSocket); mSocket = -1; flushPendingRequests(); } mState = CONNECTING; AString url; CHECK(msg->findString("url", &url)); sp<AMessage> reply; CHECK(msg->findMessage("reply", &reply)); AString host, path; unsigned port; if (!ParseURL(url.c_str(), &host, &port, &path)) { LOGE("Malformed rtsp url %s", url.c_str()); reply->setInt32("result", ERROR_MALFORMED); reply->post(); mState = DISCONNECTED; return; } struct hostent *ent = gethostbyname(host.c_str()); if (ent == NULL) { LOGE("Unknown host %s", host.c_str()); reply->setInt32("result", -ENOENT); reply->post(); mState = DISCONNECTED; return; } mSocket = socket(AF_INET, SOCK_STREAM, 0); MakeSocketBlocking(mSocket, false); struct sockaddr_in remote; memset(remote.sin_zero, 0, sizeof(remote.sin_zero)); remote.sin_family = AF_INET; remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr; remote.sin_port = htons(port); int err = ::connect( mSocket, (const struct sockaddr *)&remote, sizeof(remote)); reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr)); if (err < 0) { if (errno == EINPROGRESS) { sp<AMessage> msg = new AMessage(kWhatCompleteConnection, id()); msg->setMessage("reply", reply); msg->setInt32("connection-id", mConnectionID); msg->post(); return; } reply->setInt32("result", -errno); mState = DISCONNECTED; close(mSocket); mSocket = -1; } else { reply->setInt32("result", OK); mState = CONNECTED; mNextCSeq = 1; postReceiveReponseEvent(); } reply->post(); }
void ARTSPConnection::onConnect(const sp<AMessage> &msg) { ++mConnectionID; if (mState != DISCONNECTED) { if (mUIDValid) { HTTPBase::UnRegisterSocketUserTag(mSocket); HTTPBase::UnRegisterSocketUserMark(mSocket); } close(mSocket); mSocket = -1; flushPendingRequests(); } mState = CONNECTING; AString url; CHECK(msg->findString("url", &url)); sp<AMessage> reply; CHECK(msg->findMessage("reply", &reply)); AString host, path; unsigned port; if (!ParseURL(url.c_str(), &host, &port, &path, &mUser, &mPass) || (mUser.size() > 0 && mPass.size() == 0)) { // If we have a user name but no password we have to give up // right here, since we currently have no way of asking the user // for this information. ALOGE("Malformed rtsp url %s", url.c_str()); reply->setInt32("result", ERROR_MALFORMED); reply->post(); mState = DISCONNECTED; return; } if (mUser.size() > 0) { ALOGV("user = '******', pass = '******'", mUser.c_str(), mPass.c_str()); } #ifndef ANDROID_DEFAULT_CODE if (!mProxyHost.empty()) { ALOGI("connect through proxy %s:%d", mProxyHost.c_str(), mProxyPort); host = mProxyHost; port = mProxyPort; } #endif // #ifndef ANDROID_DEFAULT_CODE struct hostent *ent = gethostbyname(host.c_str()); if (ent == NULL) { ALOGE("Unknown host %s", host.c_str()); #ifndef ANDROID_DEFAULT_CODE reply->setInt32("result", -EHOSTUNREACH); #else reply->setInt32("result", -ENOENT); #endif // #ifndef ANDROID_DEFAULT_CODE reply->post(); mState = DISCONNECTED; return; } mSocket = socket(AF_INET, SOCK_STREAM, 0); if (mUIDValid) { HTTPBase::RegisterSocketUserTag(mSocket, mUID, (uint32_t)*(uint32_t*) "RTSP"); HTTPBase::RegisterSocketUserMark(mSocket, mUID); } MakeSocketBlocking(mSocket, false); struct sockaddr_in remote; memset(remote.sin_zero, 0, sizeof(remote.sin_zero)); remote.sin_family = AF_INET; remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr; remote.sin_port = htons(port); #ifndef ANDROID_DEFAULT_CODE mRemote = remote; struct timeval tv; tv.tv_sec = kAccessUnitTimeoutUs / 1000000LL; tv.tv_usec = 0; if (setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)) < 0) { ALOGE("can not set recv timeout"); reply->setInt32("result", -errno); mState = DISCONNECTED; close(mSocket); mSocket = -1; reply->post(); return; } ALOGI("connecting %s, %s:%d now", host.c_str(), inet_ntoa(remote.sin_addr), port); #endif // #ifndef ANDROID_DEFAULT_CODE int err = ::connect( mSocket, (const struct sockaddr *)&remote, sizeof(remote)); reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr)); if (err < 0) { if (errno == EINPROGRESS) { sp<AMessage> msg = new AMessage(kWhatCompleteConnection, id()); msg->setMessage("reply", reply); msg->setInt32("connection-id", mConnectionID); #ifndef ANDROID_DEFAULT_CODE msg->setInt64("timestamp", ALooper::GetNowUs()); ALOGI("connection EINPROGRESS"); #endif // #ifndef ANDROID_DEFAULT_CODE msg->post(); return; } reply->setInt32("result", -errno); mState = DISCONNECTED; if (mUIDValid) { HTTPBase::UnRegisterSocketUserTag(mSocket); HTTPBase::UnRegisterSocketUserMark(mSocket); } close(mSocket); mSocket = -1; } else { reply->setInt32("result", OK); mState = CONNECTED; mNextCSeq = 1; postReceiveReponseEvent(); } reply->post(); }
void ARTSPConnection::onConnect(const sp<AMessage> &msg) { ++mConnectionID; if (mState != DISCONNECTED) { if (mUIDValid) { HTTPBase::UnRegisterSocketUserTag(mSocket); } close(mSocket); mSocket = -1; flushPendingRequests(); } mState = CONNECTING; AString url; CHECK(msg->findString("url", &url)); sp<AMessage> reply; CHECK(msg->findMessage("reply", &reply)); AString host, path; unsigned port; if (!ParseURL(url.c_str(), &host, &port, &path, &mUser, &mPass) || (mUser.size() > 0 && mPass.size() == 0)) { // If we have a user name but no password we have to give up // right here, since we currently have no way of asking the user // for this information. LOGE("Malformed rtsp url %s", url.c_str()); reply->setInt32("result", ERROR_MALFORMED); reply->post(); mState = DISCONNECTED; return; } if (mUser.size() > 0) { LOGV("user = '******', pass = '******'", mUser.c_str(), mPass.c_str()); } struct hostent *ent = gethostbyname(host.c_str()); if (ent == NULL) { LOGE("Unknown host %s", host.c_str()); reply->setInt32("result", -ENOENT); reply->post(); mState = DISCONNECTED; return; } mSocket = socket(AF_INET, SOCK_STREAM, 0); if (mUIDValid) { HTTPBase::RegisterSocketUserTag(mSocket, mUID, (uint32_t)*(uint32_t*) "RTSP"); } MakeSocketBlocking(mSocket, false); union { struct sockaddr_in remote; struct sockaddr remote_generic; }; memset(remote.sin_zero, 0, sizeof(remote.sin_zero)); remote.sin_family = AF_INET; remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr; remote.sin_port = htons(port); int err = ::connect( mSocket, &remote_generic, sizeof(remote)); reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr)); if (err < 0) { if (errno == EINPROGRESS) { sp<AMessage> msg = new AMessage(kWhatCompleteConnection, id()); msg->setMessage("reply", reply); msg->setInt32("connection-id", mConnectionID); msg->post(); return; } reply->setInt32("result", -errno); mState = DISCONNECTED; if (mUIDValid) { HTTPBase::UnRegisterSocketUserTag(mSocket); } close(mSocket); mSocket = -1; } else { reply->setInt32("result", OK); mState = CONNECTED; mNextCSeq = 1; postReceiveReponseEvent(); } reply->post(); }