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();
}
Beispiel #2
0
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();
}
Beispiel #5
0
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();
}