【问题标题】:Apps are reviewed on an IPv6 network. Please ensure that your app supports IPv6 networks, as IPv6 compatibility is required应用程序在 IPv6 网络上进行审核。请确保您的应用支持 IPv6 网络,因为需要兼容 IPv6
【发布时间】:2016-10-14 11:20:25
【问题描述】:

在过去的几天里,我收到了 Apple 对我的应用程序的以下拒绝。我的应用程序与 UDP 通信,远程服务器始终是 IPv4。我使用过 BSD 套接字。请指导我如何解决这个问题。

我尝试使用 IPv4 网络创建 NAT64 热点,但无法向服务器发送任何数据包。此外,我们现在没有可用的 IPv6。

来自苹果:

2.2 详情

在运行 iOS 9.3.2 的 iPad 和运行 iOS 9.3.2 的 iPhone 上同时通过 Wi-Fi 和蜂窝网络进行审查时,我们发现您的应用存在一个或多个错误。

具体来说,在审核期间,我们无法绕过 Initializing 页面。我们在等待应用加载时遇到错误。我们附上了截图供您参考。

接下来的步骤

请在设备上运行您的应用以确定问题,然后修改并重新提交您的应用以供审核。

在 IPv6 网络上审核应用程序。请确保您的应用支持 IPv6 网络,因为需要兼容 IPv6。

有关支持 IPv6 网络的更多信息,请参阅支持 iPv6 DNS64/NAT64 网络。

源代码如下:

UdpSocketManager.h >>

#ifndef UDP_SOCKET_MANAGER_H__
#define UDP_SOCKET_MANAGER_H__

#import "TInetAddr.h"

class UdpSocketManager
{
public:
    UdpSocketManager();
    ~UdpSocketManager();

    void getLocalAddress();
    void initializeSocket();
    void start();
    void stop();

    void sendSignal(int p_type, TInetAddr *p_destAddress, unsigned char *p_data, int p_length); 
    void receiveSignal();

    int localPort;    
    int signalingSocket;
    int signalSocketRecvLength;
    int socketFamily;

    int isIPV4Available;
    int isIPV6Available;

    char wifiIP[INET_ADDRSTRLEN];
    char cellularIP[INET_ADDRSTRLEN];

    char wifiIP_v6[INET6_ADDRSTRLEN];
    char cellularIP_v6[INET6_ADDRSTRLEN];    

    long returnLength;
    struct sockaddr_in remoteAddrForRecv;

    struct sockaddr_in  srcAddrV4;
    struct sockaddr_in6 srcAddrV6;    

    struct sockaddr_in  sendAddr4;
    struct sockaddr_in6 sendAddr6;

    bool running;
    pthread_t thread;
};

#endif

UdpSocketManager.m >>

#include <string.h>
#include <pthread.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#include "UdpSocketManager.h"
#import <Foundation/Foundation.h>

unsigned int ipAddressToUnsignedInt(char *ipAddress)
{
    unsigned int ipAddressLongValue = 0L;
    int byteSegment = 0;

    for(int i = 0; i < strlen(ipAddress); i++)
    {
        char ch = ipAddress[i];
        if(ch == '.')
        {
            ipAddressLongValue <<= 8;
            ipAddressLongValue |= byteSegment;
            byteSegment = 0;
        }
        else
        {
            byteSegment = byteSegment * 10 + (ch - 48);
        }
    }

    ipAddressLongValue <<= 8;
    ipAddressLongValue |= byteSegment;
    return ipAddressLongValue;
}

int custom_random(int max=65535)
{
    int randomValue;
    randomValue = arc4random_uniform(65535)%max;
    return randomValue;
}

int custom_random(int min, int max)
{
    int randomValue;
    randomValue = arc4random_uniform(max);
    if(randomValue<min)
        randomValue=(min+custom_random(max-min));
    return randomValue;
}



void* runUdpSocketManager(void *objRef)
{
    UdpSocketManager *THIS = (UdpSocketManager *) objRef;
    THIS->running=true;

    while (THIS->running) 
    {
        THIS->receiveSignal();
    }

    pthread_exit(NULL);
    return 0;
}


UdpSocketManager::UdpSocketManager()
{
    socketFamily=AF_INET;
    signalingSocket=-1;
    running=false;
    initializeSocket();
}

UdpSocketManager::~UdpSocketManager()
{

}

void UdpSocketManager::getLocalAddress()
{
    //Read local address
    getLocalAddress();

    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success=0;

    isIPV4Available=FALSE;
    isIPV6Available=FALSE;
    success = getifaddrs(&interfaces);

    if (success == 0)
    {
        // Loop through linked list of interfaces
        temp_addr = interfaces;
        while(temp_addr != NULL)
        {
            if(temp_addr->ifa_addr->sa_family==AF_INET)
            {
                if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:@"en"])
                {
                    isIPV4Available=TRUE;
                    strcpy(wifiIP, inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
                    printf("IP Address: %s\n",inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
                }
                else if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:@"pdp_ip0"])
                {
                    isIPV4Available=TRUE;
                    strcpy(cellularIP, inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
                    printf("IP Address: %s\n",inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
                }
            }
            else if(temp_addr->ifa_addr->sa_family==AF_INET6)
            {
                if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:@"en"])
                {
                    isIPV6Available=TRUE;
                    inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr), (char*)wifiIP_v6, INET6_ADDRSTRLEN);
                    printf("Interface: %s IPV6: %s\n",temp_addr->ifa_name,wifiIP_v6);
                }
                else if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:@"pdp_ip0"])
                {
                    isIPV6Available=TRUE;
                    inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr), (char*)cellularIP_v6, INET6_ADDRSTRLEN);
                    printf("Interface: %s IPV6: %s\n",temp_addr->ifa_name,cellularIP_v6);
                }
            }
            temp_addr = temp_addr->ifa_next;
        }
    }
    freeifaddrs(interfaces);
}

void UdpSocketManager::initializeSocket()
{
    if(signalingSocket!=-1)
        close(signalingSocket);

    if (isIPV4Available)
    {
        if((signalingSocket=socket(AF_INET, SOCK_DGRAM, 0))==-1)
        {
            NSLog(@"Unable to create signaling socket of AF_INET");
        }
        else
        {
            socketFamily=AF_INET;
            NSLog(@"Socket created successfully. [AF_INET]");
        }
    }
    else if(!isIPV4Available && isIPV6Available)
    {
        if((signalingSocket=socket(AF_INET6, SOCK_DGRAM, 0))==-1)
        {
            NSLog(@"Unable to create signaling socket of AF_INET6");
        }
        else
        {
            socketFamily=AF_INET6;
            NSLog(@"Socket created successfully. [AF_INET6]");
        }
    }
    else
    {
        if((signalingSocket=socket(AF_INET, SOCK_DGRAM, 0))==-1)
        {
            NSLog(@"Unable to create signaling socket of AF_INET");
        }
        else
        {
            socketFamily=AF_INET;
            NSLog(@"Socket created successfully. [AF_INET]");
        }
    }

    int count=0;
    while(true)
    {
        count++;
        if(socketFamily==AF_INET)
        {
            srcAddrV4.sin_len = sizeof(srcAddrV4);
            srcAddrV4.sin_family = socketFamily;
            srcAddrV4.sin_addr.s_addr = INADDR_ANY;
            srcAddrV4.sin_port = htons(localPort);

            if (bind(signalingSocket, (struct sockaddr *) &srcAddrV4, sizeof(srcAddrV4)) < 0)
            {
                NSLog(@"[AF_INET] ERROR occured creating signaling port at attempt (%d) Port: %d", count, localPort);
                localPort=(int)custom_random(1024, 65535);
            }
            else
            {
                int on=1;
                setsockopt(signalingSocket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
                setsockopt(signalingSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));

                NSLog(@"[AF_INET] SignalingSocket Created Successfully at attempt (%d) Port: %d\n", count, localPort);
                break;
            }
        }
        else
        {
            srcAddrV6.sin6_len = sizeof(srcAddrV6);
            srcAddrV6.sin6_family = socketFamily;
            srcAddrV6.sin6_addr = in6addr_any;
            srcAddrV6.sin6_port = htons(localPort);

            if (bind(signalingSocket, (struct sockaddr *) &srcAddrV6, sizeof(srcAddrV6)) < 0)
            {
                NSLog(@"[AF_INET] ERROR occured creating signaling port at attempt (%d) Port: %d", count, localPort);
                localPort=(int)custom_random(1024, 65535);
            }
            else
            {
                int on=1;
                setsockopt(signalingSocket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
                setsockopt(signalingSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
                NSLog(@"[AF_INET6] SignalingSocket Created Successfully at attempt (%d) Port: %d\n", count, localPort);
                break;
            }
        }
    }
}

void UdpSocketManager::start()
{
    pthread_create(&thread, NULL, runUdpSocketManager, (void *) this);
}

void UdpSocketManager::stop()
{
    running=false;
}

void UdpSocketManager::receiveSignal()
{
    int port;
    char ipAddress[16];

    socklen_t fromlen;
    unsigned char udpSignalRecvBuffer[1600];

    fromlen = sizeof(remoteAddrForRecv);
    signalSocketRecvLength = (int)recvfrom(signalingSocket, (char *)udpSignalRecvBuffer,1600,0,(struct sockaddr *)&remoteAddrForRecv,&fromlen);

    if(signalSocketRecvLength>0)
    {
        strcpy(ipAddress, inet_ntoa(remoteAddrForRecv.sin_addr));
        port = ntohs(remoteAddrForRecv.sin_port);
        NSLog(@"RECEIVED %d bytes from %s:%d", signalSocketRecvLength, ipAddress, port);
    }
    else
    {
        usleep(10000);// 10 ms
    }
}


void UdpSocketManager::sendSignal(int p_type, TInetAddr *p_destAddress, unsigned char *p_data, int p_length)
{
    if(socketFamily==AF_INET6)
    {
        // Convert IPv4 address to IPv4-mapped-into-IPv6 address.        
        sendAddr6.sin6_family = AF_INET6;
        sendAddr6.sin6_port = p_destAddress->m_port;

        sendAddr6.sin6_addr.__u6_addr.__u6_addr32[0] = 0;
        sendAddr6.sin6_addr.__u6_addr.__u6_addr32[1] = 0;
        sendAddr6.sin6_addr.__u6_addr.__u6_addr32[2] = htonl(0xffff);
        sendAddr6.sin6_addr.__u6_addr.__u6_addr32[3] = ntohl(ipAddressToUnsignedInt(p_destAddress->m_address));

        sendAddr6.sin6_addr.__u6_addr.__u6_addr16[4] = 0;
        sendAddr6.sin6_addr.__u6_addr.__u6_addr16[5] = 0xffff;

        char ipV6Address[INET6_ADDRSTRLEN];
        inet_ntop(AF_INET6, &sendAddr6.sin6_addr, ipV6Address, INET6_ADDRSTRLEN);
        NSLog(@"ipV6Address: %s\n", ipV6Address);

        sendAddr6.sin6_flowinfo = 0;
        sendAddr6.sin6_scope_id = 0;
    }
    else
    {
        sendAddr4.sin_family = AF_INET;
        sendAddr4.sin_port   = htons(p_destAddress->m_port);

        if(inet_aton((char *) p_destAddress->m_address, &sendAddr4.sin_addr)==0)
        {
            NSLog(@"signal message - inet_aton() failed, %s", p_destAddress->m_address);
        }
    }


    if(socketFamily==AF_INET)
        returnLength=sendto(signalingSocket, p_data, p_length, 0, (struct sockaddr *)&sendAddr4, sizeof(sendAddr4));
    else
        returnLength=sendto(signalingSocket, p_data, p_length, 0, (struct sockaddr *)&sendAddr6, sizeof(sendAddr6));

    NSLog(@"SENT %ld bytes to %s:%d\n", returnLength,p_destAddress->m_address,p_destAddress->m_port);
}

【问题讨论】:

  • "我尝试使用 IPV4 网络创建热点 NAT64,但无法向服务器发送任何数据包。"这就是问题所在。在您将其提交到 App Store 之前,它需要在 NAT64 环境中运行。
  • 当你在socket上发送东西时,你需要给它一个地址结构。你从哪里得到这个地址?
  • @user102008: 还有this: "在 WWDC 2015 上,我们宣布在 iOS 9 中过渡到仅 IPv6 的网络服务......如果您的应用使用 IPv4 特定的 API 或硬-编码的 IP 地址,您需要进行一些更改"
  • 您已表明您无权访问 IPv6 网络来对此进行测试,Maverick。我认为这是您需要解决的第一件事 - 您无法猜测解决方案并将其重新提交给 Apple,希望它能够正常工作。如果引入错误会发生什么?
  • @RemyLebeau,当 Apple 说“iOS 9 将支持 IPv6-only 网络服务”时,并不是指“ iOS 9 将支持 IPv6 网络服务。" Apple 的要求是,其商店中的任何应用程序都必须在纯 IPv6 网络上运行,而不是排他性地。

标签: ios iphone sockets networking ipv6


【解决方案1】:

AFNetworking 在 IPv6 和 IPv4 中的可达性解决方案

在类 AFNetworkReachabilityManager

中更改以下代码
 + (instancetype)sharedManager {
    static AFNetworkReachabilityManager *_sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        struct sockaddr_in6 address;
        bzero(&address, sizeof(address));
        address.sin6_len = sizeof(address);
        address.sin6_family = AF_INET6;
        _sharedManager = [self managerForAddress:&address];
    });
    return _sharedManager;
}

【讨论】:

    【解决方案2】:

    我认为您的“将 IPv4 地址转换为 IPv4 映射到 IPv6 地址”不正确。与其尝试自己构建地址,不如调用 getaddrinfo() 并使用您要连接的东西的字符串(可以是主机名或 IPv4 地址文字),它会返回给您一个 @ 列表987654324@s;您应该从那里使用第一个传递给sendto。它将为您提供适当的 IP 地址系列以供使用,如果您提供 IPv4 地址并且它是纯 IPv6 网络(无需您进行任何测试),它将自动为您提供正确的 IPv6 地址以用于该 NAT64路由器(无需您自己弄清楚)。 (如果您想使用 NAT64/DNS64 从 IPv4 手动构造 IPv6 地址而不使用 getaddrinfo(),则必须遵循 RFC 7050 中的复杂过程。)

    此外,您在getLocalAddress() 中所做的所有事情都是不必要的,并且可能会导致更多问题。你不需要isIPV4AvailableisIPV6Available——那时你不应该在意。只需在开始时创建并绑定 both IPv4 和 IPv6 套接字(无需关心哪个有效),并且每次需要发送时,您都会获得正确的 sockaddr 以使用 @ 987654331@同上,然后发送到地址族对应你正在使用的sockaddr的socket。当你想接收时,你可以在两个套接字上调用recvfrom

    【讨论】:

    • 我已经完全按照您的建议进行了操作,但是这种方式无法将 UDP 数据包发送到服务器。
    • @MaverickKing:你遇到了什么错误?如果您使用带有数字端口号的 IPv4 文字,您可能会遇到this bug,其中getaddrinfo() 错误地返回端口 0,您需要在之后手动设置端口。
    【解决方案3】:

    我发现您显示的代码存在几个问题:

    1. UdpSocketManager 在调用initializeSocket() 之前不会调用getLocalAddress(),因此绑定套接字始终是 IPv4,而不是 IPv6。您也没有在调用initializeSocket() 之前初始化localPort

    2. getLocalAddress()(如果曾经调用过)会调用自身,因此您有一个无限递归循环。

    3. 在循环中使用custom_random() 来选择一个随机绑定端口是完全错误的、不必要的,并且可能是无休止的。要在您配置的端口失败时选择一个随机端口,只需调用bind() 一次,并将端口设置为 0。操作系统知道哪些端口可用,并将为您选择一个可用的随机端口。你的整个initializeSocket() 试图做的事情过于复杂。可以大大简化。

    4. 启用SO_REUSEADDR 时,必须在调用bind() 之前启用它,而不是之后。另请查看SO_REUSEPORT

    5. 您的remoteAddrForRecv 变量被声明为sockaddr_in,它的大小仅足以容纳一个IPv4 地址,如果在IPv6 套接字上调用会导致recvfrom() 失败。请改用sockaddr_storage。实际上。您的所有sockaddr_insockaddr_in6 变量都应替换为sockaddr_storage

    6. inet_ntoa() 同样也仅限 IPv4。请改用inet_ntop() 来处理 IPv4 和 IPv6 地址。

    试试类似的方法:

    UdpSocketManager.h

    #ifndef UDP_SOCKET_MANAGER_H__
    #define UDP_SOCKET_MANAGER_H__
    
    #import "TInetAddr.h"
    
    class UdpSocketManager
    {
    public:
        UdpSocketManager();
        ~UdpSocketManager();
    
        void getLocalAddresses();
        void initializeSocket();
        void start();
        void stop();
    
        void sendSignal(int p_type, TInetAddr *p_destAddress, unsigned char *p_data, int p_length);    
        void receiveSignal();
    
        int localPort;    
        int signalingSocket;
        int socketFamily;
    
        int isIPV4Available;
        int isIPV6Available;
    
        char wifiIP_v4[INET_ADDRSTRLEN];
        char cellularIP_v4[INET_ADDRSTRLEN];
    
        char wifiIP_v6[INET6_ADDRSTRLEN];
        char cellularIP_v6[INET6_ADDRSTRLEN];    
    
        bool running;
        pthread_t thread;
    };
    
    #endif
    

    UdpSocketManager.m

    #include <string.h>
    #include <pthread.h>
    #include <ifaddrs.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    
    #include "UdpSocketManager.h"
    #import <Foundation/Foundation.h>
    
    void* runUdpSocketManager(void *objRef)
    {
        UdpSocketManager *THIS = (UdpSocketManager *) objRef;
    
        while (THIS->running) 
        {
            THIS->receiveSignal();
        }
    
        pthread_exit(NULL);
        return 0;
    }
    
    UdpSocketManager::UdpSocketManager()
    {
        socketFamily = AF_INET;
        signalingSocket = -1;
        localPort = 0; // or whatever port you actual want
        srcAddrLen = 0;
        sendAddrLen = 0;
        running = false;
        initializeSocket();
    }
    
    UdpSocketManager::~UdpSocketManager()
    {
        if(signalingSocket != -1)
        {
            close(signalingSocket);
            signalingSocket = -1;
        }
    }
    
    void UdpSocketManager::getLocalAddresses()
    {
        //Read local addresses
    
        struct ifaddrs *interfaces = NULL;
        struct ifaddrs *temp_addr = NULL;
    
        isIPV4Available = FALSE;
        isIPV6Available = FALSE;
    
        memset(&wifiIP_v4, 0, sizeof(wifiIP_v4));
        memset(&cellularIP_v4, 0, sizeof(cellularIP_v4));
    
        memset(&wifiIP_v6, 0, sizeof(wifiIP_v6));
        memset(&cellularIP_v6, 0, sizeof(cellularIP_v6));
    
        if(getifaddrs(&interfaces) == 0)
        {
            // Loop through linked list of interfaces
            temp_addr = interfaces;
            while(temp_addr != NULL)
            {
                if ([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:@"en"])
                {
                    if(temp_addr->ifa_addr->sa_family == AF_INET)
                    {
                        isIPV4Available = TRUE;
                        inet_ntop(AF_INET, &(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr), wifiIP_v4, sizeof(wifiIP_v4));
                        printf("Interface: %s IPv4: %s\n", temp_addr->ifa_name, wifiIP_v4);
                    }
                    else if(temp_addr->ifa_addr->sa_family == AF_INET6)
                    {
                        isIPV6Available = TRUE;
                        inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr), wifiIP_v6, sizeof(wifiIP_v6));
                        printf("Interface: %s IPv6: %s\n", temp_addr->ifa_name, wifiIP_v6);
                    }
                }
                else if([[NSString stringWithUTF8String:temp_addr->ifa_name] hasPrefix:@"pdp_ip0"])
                {
                    if(temp_addr->ifa_addr->sa_family == AF_INET)
                    {
                        isIPV4Available = TRUE;
                        inet_ntop(AF_INET, &(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr), cellularIP_v4, sizeof(cellularIP_v4));
                        printf("Interface: %s IPv6: %s\n", temp_addr->ifa_name, cellularIP_v4);
                    }
                    else if(temp_addr->ifa_addr->sa_family == AF_INET6)
                    {
                        isIPV6Available = TRUE;
                        inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr), cellularIP_v6, sizeof(cellularIP_v6));
                        printf("Interface: %s IPv6: %s\n", temp_addr->ifa_name, cellularIP_v6);
                    }
                }
                temp_addr = temp_addr->ifa_next;
            }
    
            freeifaddrs(interfaces);
        }
    }
    
    void UdpSocketManager::initializeSocket()
    {
        struct sockaddr_storage srcAddr;
        struct sockaddr_in6 *srcAddr6;
        struct sockaddr_in *srcAddr4;
        socklen_t srcAddrLen;
    
        if(signalingSocket != -1)
        {
            close(signalingSocket);
            signalingSocket = -1;
        }
    
        getLocalAddresses();
    
        if(isIPV6Available)
        {
            signalingSocket = socket(AF_INET6, SOCK_DGRAM, 0);
            if(signalingSocket == -1)
            {
                NSLog(@"Unable to create IPv6 signaling socket");
                return;
            }
    
            socketFamily = AF_INET6;
            NSLog(@"IPv6 Socket created successfully");
        }
        else
        {
            signalingSocket = socket(AF_INET, SOCK_DGRAM, 0);
            if(signalingSocket == -1)
            {
                NSLog(@"Unable to create IPv4 signaling socket");
                return;
            }
    
            socketFamily = AF_INET;
            NSLog(@"IPv4 Socket created successfully");
        }
    
        int on = 1;
        setsockopt(signalingSocket, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
        setsockopt(signalingSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    
        if(socketFamily == AF_INET6)
        {
            on = 0;
            setsockopt(signalingSocket, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
    
            srcAddr6 = (struct sockaddr_in6 *) &srcAddr;
            srcAddrLen = sizeof(sockaddr_in6);
    
            srcAddr6->sin6_len = srcAddrLen;
            srcAddr6->sin6_family = socketFamily;
            srcAddr6->sin6_addr = in6addr_any;
            srcAddr6->sin6_port = htons(localPort);
        }
        else
        {
            srcAddr4 = (struct sockaddr_in *) &srcAddr;
            srcAddrLen = sizeof(sockaddr_in);
    
            srcAddr4->sin_len = srcAddrLen;
            srcAddr4->sin_family = socketFamily;
            srcAddr4->sin_addr.s_addr = INADDR_ANY;
            srcAddr4->sin_port = htons(localPort);
        }
    
        if (bind(signalingSocket, (struct sockaddr *) &srcAddr, srcAddrLen) < 0)
        {
            if (localPort == 0)
            {
                NSLog(@"ERROR occured binding random signaling port");
                close(signalingSocket);
                signalingSocket = -1;
                return;
            }
    
            NSLog(@"ERROR occured binding signaling port: %d", localPort);
    
            if(socketFamily == AF_INET6)
                srcAddr6->sin6_port = 0;
            else
                srcAddr4->sin_port = 0;
    
            if (bind(signalingSocket, (struct sockaddr *) &srcAddr, srcAddrLen) < 0)
            {
                NSLog(@"ERROR occured binding random signaling port");
                close(signalingSocket);
                signalingSocket = -1;
                return;
            }
    
            getsockname(signalingSocket, (struct sockaddr *) &srcAddr, &srcAddrLen);
    
            if(socketFamily == AF_INET6)
                localPort = ntohs(srcAddr6->sin6_port);
            else
                localPort = ntohs(srcAddr4->sin_port);
        }
    
        NSLog(@"SignalingSocket bound successfully on Port: %d\n", localPort);
    }
    
    void UdpSocketManager::start()
    {
        if(signalingSocket != -1)
        {
            running = true;
            pthread_create(&thread, NULL, runUdpSocketManager, this);
        }
    }
    
    void UdpSocketManager::stop()
    {
        running = false;
    }
    
    void UdpSocketManager::receiveSignal()
    {
        int port;
        char ipAddress[INET6_ADDRSTRLEN];
    
        unsigned char udpSignalRecvBuffer[1600];
        ssize_t signalRecvLength;
    
        struct sockaddr_storage remoteAddr;
        socklen_t fromlen;
    
        fromlen = sizeof(remoteAddr);
        signalRecvLength = recvfrom(signalingSocket, udpSignalRecvBuffer, sizeof(udpSignalRecvBuffer), 0, (struct sockaddr *) &remoteAddr, &fromlen);
    
        if(signalRecvLength >= 0)
        {
            if(remoteAddrForRecv.ss_family == AF_INET6)
            {
                struct sockaddr_in6 *remoteAddr6 = (struct sockaddr_in6 *) &remoteAddr;
                inet_ntop(AF_INET6, &(remoteAddr6->sin6_addr), ipAddress, sizeof(ipAddress));
                port = ntohs(remoteAddr6->sin6_port);
            }
            else
            {
                struct sockaddr_in *remoteAddr4 = (struct sockaddr_in4 *) &remoteAddr;
                inet_ntop(AF_INET, &(remoteAddr4->sin_addr), ipAddress, sizeof(ipAddress));
                port = ntohs(remoteAddr4->sin_port);
            }
    
            NSLog(@"RECEIVED %d bytes from %s:%d", signalRecvLength, ipAddress, port);
        }
        else
        {
            usleep(10000);// 10 ms
        }
    }
    
    
    void UdpSocketManager::sendSignal(int p_type, TInetAddr *p_destAddress, unsigned char *p_data, int p_length)
    {
        struct sockaddr_storage sendAddr;
        socklen_t sendAddrLen;
    
        ssize_t returnLength;
    
        char ipAddress[INET6_ADDRSTRLEN];
    
        if(socketFamily == AF_INET6)
        {
            struct sockaddr_in6 *sendAddr6 = (struct sockaddr_in6 *) &sendAddr;
            sendAddrLen = sizeof(sockaddr_in6);
    
            sendAddr6->sin6_family = AF_INET6;
            sendAddr6->sin6_port = htons(p_destAddress->m_port);
    
            // Convert IPv4 address to IPv4-mapped IPv6 address.        
            sendAddr6->sin6_addr.__u6_addr.__u6_addr32[0] = 0;
            sendAddr6->sin6_addr.__u6_addr.__u6_addr32[1] = 0;
            sendAddr6->sin6_addr.__u6_addr.__u6_addr16[4] = 0;
            sendAddr6->sin6_addr.__u6_addr.__u6_addr16[5] = 0xffff;
            sendAddr6->sin6_addr.__u6_addr.__u6_addr32[3] = inet_addr(p_destAddress->m_address);            
    
            sendAddr6->sin6_flowinfo = 0;
            sendAddr6->sin6_scope_id = 0;
    
            inet_ntop(AF_INET6, &(sendAddr6->sin6_addr), ipAddress, sizeof(ipAddress));
        }
        else
        {
            struct sockaddr_in *sendAddr4 = (struct sockaddr_in *) &sendAddr;
            sendAddrLen = sizeof(sockaddr_in);
    
            sendAddr4->sin_family = AF_INET;
            sendAddr4->sin_port = htons(p_destAddress->m_port);
    
            if(inet_aton((char *) p_destAddress->m_address, &(sendAddr4->sin_addr)) == 0)
            {
                NSLog(@"signal message - inet_aton() failed, %s", p_destAddress->m_address);
                return;
            }
    
            inet_ntop(AF_INET, &(sendAddr4->sin_addr), ipAddress, sizeof(ipAddress));
        }
    
        returnLength = sendto(signalingSocket, p_data, p_length, 0, (struct sockaddr *) &sendAddr, sendAddrLen);
        if(returnLength >= 0)
            NSLog(@"SENT %ld bytes to %s:%d\n", returnLength, ipAddress, p_destAddress->m_port);
    }
    

    【讨论】:

      猜你喜欢
      • 2016-10-29
      • 1970-01-01
      • 2016-11-07
      • 2017-01-06
      • 1970-01-01
      • 2017-06-07
      • 2012-05-21
      • 2016-11-24
      • 2017-02-13
      相关资源
      最近更新 更多