Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fb23299 authored by Li Sun's avatar Li Sun Committed by Linux Build Service Account
Browse files

libstagefright: poke the udp hole twice for future incoming udp packets

- only firing off udp packets once to the source address or the endpoint
  could still be limited in some NAT network environment. As a result,
  client can't receive rtp packets over udp.

- send udp packets to both of the two addresses if they are available.

Change-Id: I7e8a0b36a82bcd85b307c9c15dcfee2bcd7e6030
parent 44c71a9d
Loading
Loading
Loading
Loading
+44 −39
Original line number Diff line number Diff line
@@ -333,23 +333,33 @@ struct MyHandler : public AHandler {

        AString source;
        AString server_port;
        if (!GetAttribute(transport.c_str(),
                          "source",
                          &source)) {
            ALOGW("Missing 'source' field in Transport response. Using "
                 "RTSP endpoint address.");

            struct hostent *ent = gethostbyname(mSessionHost.c_str());
            if (ent == NULL) {
                ALOGE("Failed to look up address of session host '%s'",
                     mSessionHost.c_str());
        Vector<uint32_t> s_addrs;
        if (GetAttribute(transport.c_str(), "source", &source)){
            ALOGI("found 'source' = %s field in Transport response",
                source.c_str());
            uint32_t addr = inet_addr(source.c_str());
            if (addr == INADDR_NONE || IN_LOOPBACK(ntohl(addr))){
                ALOGI("no need to poke the hole");
            } else {
                s_addrs.push(addr);
            }
        }

                return false;
        struct hostent *ent = gethostbyname(mSessionHost.c_str());
        if (ent != NULL){
            ALOGI("get the endpoint address of session host");
            uint32_t addr = *(in_addr_t *)ent->h_addr;
            if (addr == INADDR_NONE || IN_LOOPBACK(ntohl(addr))){
                ALOGI("no need to poke the hole");
            } else if (s_addrs.size() == 0 || s_addrs[0] != addr){
                s_addrs.push(addr);
            }
        }

            addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
        } else {
            addr.sin_addr.s_addr = inet_addr(source.c_str());
        if (s_addrs.size() == 0){
            ALOGI("Failed to get any session address");
            return false;
        }

        if (!GetAttribute(transport.c_str(),
@@ -377,21 +387,15 @@ struct MyHandler : public AHandler {
                 "in the future.");
        }

        if (addr.sin_addr.s_addr == INADDR_NONE) {
            return true;
        }

        if (IN_LOOPBACK(ntohl(addr.sin_addr.s_addr))) {
            // No firewalls to traverse on the loopback interface.
            return true;
        }

        // Make up an RR/SDES RTCP packet.
        sp<ABuffer> buf = new ABuffer(65536);
        buf->setRange(0, 0);
        addRR(buf);
        addSDES(rtpSocket, buf);

        for (uint32_t i = 0; i < s_addrs.size(); i++){
            addr.sin_addr.s_addr = s_addrs[i];

            addr.sin_port = htons(rtpPort);

            ssize_t n = sendto(
@@ -400,7 +404,7 @@ struct MyHandler : public AHandler {

            if (n < (ssize_t)buf->size()) {
                ALOGE("failed to poke a hole for RTP packets");
            return false;
                continue;
            }

            addr.sin_port = htons(rtcpPort);
@@ -411,10 +415,11 @@ struct MyHandler : public AHandler {

            if (n < (ssize_t)buf->size()) {
                ALOGE("failed to poke a hole for RTCP packets");
            return false;
                continue;
            }

        ALOGV("successfully poked holes.");
            ALOGI("successfully poked holes for the address = %u", s_addrs[i]);
        }

        return true;
    }