VT: ARTPWriter: Supports ipv6

ARTPWriter should sent/receive packets even in IPv6 network.
This is common scenario for IMS video calling.

Bug: 121230209
Change-Id: Ic10d244ffda1ae6e5275929175d3fdef71ce9fe3
Signed-off-by: Byeongjo Park <bjo.park@samsung.com>
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 92eaa70..f4d20dd 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -62,6 +62,7 @@
       mLooper(new ALooper),
       mReflector(new AHandlerReflector<ARTPWriter>(this)) {
     CHECK_GE(fd, 0);
+    mIsIPv6 = false;
 
     mLooper->setName("rtp writer");
     mLooper->registerHandler(mReflector);
@@ -111,56 +112,13 @@
       mLooper(new ALooper),
       mReflector(new AHandlerReflector<ARTPWriter>(this)) {
     CHECK_GE(fd, 0);
+    mIsIPv6 = false;
 
     mLooper->setName("rtp writer");
     mLooper->registerHandler(mReflector);
     mLooper->start();
 
-    mRTPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-    CHECK_GE(mRTPSocket, 0);
-    mRTCPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-    CHECK_GE(mRTCPSocket, 0);
-
-    // socket need to be SO_REUSEADDR to avoid "Address already in use" error.
-    int sockopt = 1;
-    setsockopt(mRTPSocket, SOL_SOCKET, SO_REUSEADDR, (int *)&sockopt, sizeof(sockopt));
-    setsockopt(mRTPSocket, SOL_SOCKET, SO_REUSEPORT, (int *)&sockopt, sizeof(sockopt));
-    setsockopt(mRTCPSocket, SOL_SOCKET, SO_REUSEADDR, (int *)&sockopt, sizeof(sockopt));
-    setsockopt(mRTCPSocket, SOL_SOCKET, SO_REUSEPORT, (int *)&sockopt, sizeof(sockopt));
-
-    // binding rtp socket to assign source ip/port.
-    memset(mLocalAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero));
-    mLocalAddr.sin_family = AF_INET;
-    mLocalAddr.sin_addr.s_addr = inet_addr(localIp.string());
-    mLocalAddr.sin_port = htons((unsigned short int)localPort);
-    if (bind(mRTPSocket, (struct sockaddr*)&mLocalAddr, sizeof(mLocalAddr)) == -1) {
-        ALOGE("failed to bind rtp %s:%d err=%s", localIp.string(),
-                ntohs(mLocalAddr.sin_port), strerror(errno));
-    } else {
-        ALOGD("succeed to bind rtp %s:%d", localIp.string(), ntohs(mLocalAddr.sin_port));
-    }
-    // binding rtcp socket to assign source ip/port.
-    mLocalAddr.sin_port = htons(ntohs(mLocalAddr.sin_port) + 1);
-    if (bind(mRTCPSocket, (struct sockaddr*)&mLocalAddr, sizeof(mLocalAddr)) == -1) {
-        ALOGE("failed to bind rtcp %s:%d", localIp.string(), ntohs(mLocalAddr.sin_port));
-    } else {
-        ALOGD("succeed to bind rtcp %s:%d", localIp.string(), ntohs(mLocalAddr.sin_port) | 1);
-    }
-    mLocalAddr.sin_port = htons(ntohs(mLocalAddr.sin_port) - 1);
-
-    // update client settings
-    memset(mRTPAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero));
-    mRTPAddr.sin_family = AF_INET;
-    mRTPAddr.sin_addr.s_addr = inet_addr(remoteIp.string());
-    mRTPAddr.sin_port = htons((unsigned short int)remotePort);
-
-    mRTCPAddr = mRTPAddr;
-    mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
-
-    ALOGD("localIp=%s, rtp=%d, rtcp=%d", localIp.string(), localPort, localPort+1);
-    ALOGD("remoteIp=%s, rtp=%d, rtcp=%d", remoteIp.string(), ntohs(mRTPAddr.sin_port),
-            ntohs(mRTCPAddr.sin_port));
-
+    makeSocketPairAndBind(localIp, localPort, remoteIp , remotePort);
     mSPSBuf = NULL;
     mPPSBuf = NULL;
 
@@ -470,10 +428,25 @@
 }
 
 void ARTPWriter::send(const sp<ABuffer> &buffer, bool isRTCP) {
-    ssize_t n = sendto(
-            isRTCP ? mRTCPSocket : mRTPSocket, buffer->data(), buffer->size(), 0,
-            (const struct sockaddr *)(isRTCP ? &mRTCPAddr : &mRTPAddr),
-            sizeof(mRTCPAddr));
+    int sizeSockSt;
+    struct sockaddr *remAddr;
+
+    if (mIsIPv6) {
+        sizeSockSt = sizeof(struct sockaddr_in6);
+        if (isRTCP)
+            remAddr = (struct sockaddr *)&mRTCPAddr6;
+        else
+            remAddr = (struct sockaddr *)&mRTPAddr6;
+    } else {
+        sizeSockSt = sizeof(struct sockaddr_in);
+        if (isRTCP)
+            remAddr = (struct sockaddr *)&mRTCPAddr;
+        else
+            remAddr = (struct sockaddr *)&mRTPAddr;
+    }
+
+    ssize_t n = sendto(isRTCP ? mRTCPSocket : mRTPSocket,
+            buffer->data(), buffer->size(), 0, remAddr, sizeSockSt);
 
     CHECK_EQ(n, (ssize_t)buffer->size());
 
@@ -624,7 +597,7 @@
         sdp.append("m=audio ");
     }
 
-    sdp.append(AStringPrintf("%d", ntohs(mRTPAddr.sin_port)));
+    sdp.append(AStringPrintf("%d", mIsIPv6 ? ntohs(mRTPAddr6.sin6_port) : ntohs(mRTPAddr.sin_port)));
     sdp.append(
           " RTP/AVP " PT_STR "\r\n"
           "b=AS 320000\r\n"
@@ -1030,5 +1003,81 @@
     mLastNTPTime = GetNowNTP();
 }
 
+void ARTPWriter::makeSocketPairAndBind(String8& localIp, int localPort,
+        String8& remoteIp, int remotePort) {
+    if (localIp.contains(":"))
+        mIsIPv6 = true;
+    else
+        mIsIPv6 = false;
+
+    mRTPSocket = socket(mIsIPv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
+    CHECK_GE(mRTPSocket, 0);
+    mRTCPSocket = socket(mIsIPv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
+    CHECK_GE(mRTCPSocket, 0);
+
+    int sockopt = 1;
+    setsockopt(mRTPSocket, SOL_SOCKET, SO_REUSEPORT, (int *)&sockopt, sizeof(sockopt));
+    setsockopt(mRTCPSocket, SOL_SOCKET, SO_REUSEPORT, (int *)&sockopt, sizeof(sockopt));
+
+    if (mIsIPv6) {
+        memset(&mLocalAddr6, 0, sizeof(mLocalAddr6));
+        memset(&mRTPAddr6, 0, sizeof(mRTPAddr6));
+        memset(&mRTCPAddr6, 0, sizeof(mRTCPAddr6));
+
+        mLocalAddr6.sin6_family = AF_INET6;
+        inet_pton(AF_INET6, localIp.string(), &mLocalAddr6.sin6_addr);
+        mLocalAddr6.sin6_port = htons((uint16_t)localPort);
+
+        mRTPAddr6.sin6_family = AF_INET6;
+        inet_pton(AF_INET6, remoteIp.string(), &mRTPAddr6.sin6_addr);
+        mRTPAddr6.sin6_port = htons((uint16_t)remotePort);
+
+        mRTCPAddr6 = mRTPAddr6;
+        mRTCPAddr6.sin6_port = htons((uint16_t)(remotePort + 1));
+    } else {
+        memset(&mLocalAddr, 0, sizeof(mLocalAddr));
+        memset(&mRTPAddr, 0, sizeof(mRTPAddr));
+        memset(&mRTCPAddr, 0, sizeof(mRTCPAddr));
+
+        mLocalAddr.sin_family = AF_INET;
+        mLocalAddr.sin_addr.s_addr = inet_addr(localIp.string());
+        mLocalAddr.sin_port = htons((uint16_t)localPort);
+
+        mRTPAddr.sin_family = AF_INET;
+        mRTPAddr.sin_addr.s_addr = inet_addr(remoteIp.string());
+        mRTPAddr.sin_port = htons((uint16_t)remotePort);
+
+        mRTCPAddr = mRTPAddr;
+        mRTCPAddr.sin_port = htons((uint16_t)(remotePort + 1));
+    }
+
+    struct sockaddr *localAddr = mIsIPv6 ?
+        (struct sockaddr*)&mLocalAddr6 : (struct sockaddr*)&mLocalAddr;
+
+    int sizeSockSt = mIsIPv6 ? sizeof(mLocalAddr6) : sizeof(mLocalAddr);
+
+    if (bind(mRTPSocket, localAddr, sizeSockSt) == -1) {
+        ALOGE("failed to bind rtp %s:%d err=%s", localIp.string(), localPort, strerror(errno));
+    } else {
+        ALOGI("succeed to bind rtp %s:%d", localIp.string(), localPort);
+    }
+
+    if (mIsIPv6)
+        mLocalAddr6.sin6_port = htons((uint16_t)(localPort + 1));
+    else
+        mLocalAddr.sin_port = htons((uint16_t)(localPort + 1));
+
+    if (bind(mRTCPSocket, localAddr, sizeSockSt) == -1) {
+        ALOGE("failed to bind rtcp %s:%d err=%s", localIp.string(), localPort + 1, strerror(errno));
+    } else {
+        ALOGI("succeed to bind rtcp %s:%d", localIp.string(), localPort + 1);
+    }
+
+    if (mIsIPv6)
+        mLocalAddr6.sin6_port = htons((uint16_t)localPort);
+    else
+        mLocalAddr.sin_port = htons((uint16_t)localPort);
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/rtsp/ARTPWriter.h b/media/libstagefright/rtsp/ARTPWriter.h
index 6795d28..4c764ee 100644
--- a/media/libstagefright/rtsp/ARTPWriter.h
+++ b/media/libstagefright/rtsp/ARTPWriter.h
@@ -78,10 +78,14 @@
     sp<ALooper> mLooper;
     sp<AHandlerReflector<ARTPWriter> > mReflector;
 
+    bool mIsIPv6;
     int mRTPSocket, mRTCPSocket;
     struct sockaddr_in mLocalAddr;
     struct sockaddr_in mRTPAddr;
     struct sockaddr_in mRTCPAddr;
+    struct sockaddr_in6 mLocalAddr6;
+    struct sockaddr_in6 mRTPAddr6;
+    struct sockaddr_in6 mRTCPAddr6;
 
     AString mProfileLevel;
     AString mSeqParamSet;
@@ -126,6 +130,7 @@
     void sendAMRData(MediaBufferBase *mediaBuf);
 
     void send(const sp<ABuffer> &buffer, bool isRTCP);
+    void makeSocketPairAndBind(String8& localIp, int localPort, String8& remoteIp, int remotePort);
 
     DISALLOW_EVIL_CONSTRUCTORS(ARTPWriter);
 };