-
-
Save avesus/fdb465b60a4f5204845c to your computer and use it in GitHub Desktop.
| # include <sys/types.h> | |
| # include <sys/socket.h> | |
| # include <ifaddrs.h> | |
| # include <arpa/inet.h> | |
| # include <netinet/in.h> | |
| // Bad dirty quick functions written by hot fingers: | |
| char* ipToStr(sockaddr* addr) { | |
| static char ip[32]; | |
| sprintf(ip, "%d.%d.%d.%d", (unsigned char)addr->sa_data[2], (unsigned char)addr->sa_data[3], (unsigned char)addr->sa_data[4], (unsigned char)addr->sa_data[5]); | |
| return ip; | |
| } | |
| // so on... | |
| char* ip32ToStr(int addr) { | |
| static char ip[32]; | |
| char* bytes = (char*)&addr; | |
| sprintf(ip, "%d.%d.%d.%d", (unsigned char)bytes[3], (unsigned char)bytes[2], (unsigned char)bytes[1], (unsigned char)bytes[0]); | |
| return ip; | |
| } | |
| // Look here: | |
| void test_stun_ip_multipath_ios() { | |
| ifaddrs* addrs = 0; | |
| getifaddrs(&addrs); | |
| sockaddr* clt1 = 0; | |
| sockaddr* clt2 = 0; | |
| while(addrs) { | |
| char* ip = ipToStr(addrs->ifa_addr); | |
| fprintf(stderr, "%s: %s\n", addrs->ifa_name, ip); | |
| // FIX THIS ACCORDING YOUR ACTUAL Wi-Fi and 3G IP Addresses: | |
| if (0 == strncmp("192.168.", ip, 8) ) { | |
| clt1 = addrs->ifa_addr; | |
| } else if (0 == strncmp("10.", ip, 3) ) { | |
| clt2 = addrs->ifa_addr; | |
| } | |
| addrs = addrs->ifa_next; | |
| } | |
| int sock1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
| int sock2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
| sockaddr_in cltAddr = {0}; | |
| cltAddr.sin_family = AF_INET; | |
| cltAddr.sin_port = htons(5555); | |
| // This binds to the enumerated addresses. | |
| // Auto-assigned ports could be acquired by getsockname, i.e., | |
| // int nLen = sizeof(serverAddr); | |
| // getsockname(sock, (sockaddr*)&serverAddr, &nLen); | |
| // int recvOnPort = ntohs(serverAddr.sin_port); | |
| // printf("My port: %d\n", recvOnPort); | |
| int res1 = bind(sock1, (struct sockaddr *)clt1, sizeof(sockaddr_in)); | |
| int res2 = bind(sock2, (struct sockaddr *)clt2, sizeof(sockaddr_in)); | |
| sockaddr_in serverAddr = {0}; | |
| serverAddr.sin_family = AF_INET; | |
| // A STUN server (I forgot whom) | |
| serverAddr.sin_addr.s_addr = inet_addr("23.21.150.121"); | |
| serverAddr.sin_port = htons(3478); | |
| struct StunRequest | |
| { | |
| uint16_t msgType; | |
| uint16_t payloadLen; | |
| uint32_t magic; | |
| uint8_t transaction[12]; | |
| }; | |
| StunRequest r = {0}; | |
| r.msgType = 0x0100; | |
| r.payloadLen = 0; | |
| r.magic = 0x42A41221; | |
| r.transaction[0] = 5; | |
| r.transaction[5] = 7; | |
| // Send thru ONE SOCKET | |
| int sentBytes = sendto(sock1, (char*)&r, sizeof(r), 0, | |
| (sockaddr*)&serverAddr, sizeof(serverAddr)); | |
| // Send thru ANOTHER SOCKET | |
| int sentBytes2 = sendto(sock2, (char*)&r, sizeof(r), 0, | |
| (sockaddr*)&serverAddr, sizeof(serverAddr)); | |
| char recvBuffer[ 1280 ] = {0}; | |
| sockaddr_in from = {0}; | |
| socklen_t fromLen = sizeof(from); | |
| ssize_t nrecvd = recvfrom(sock1, (void*)recvBuffer, sizeof(recvBuffer), | |
| 0, (sockaddr*)&from, &fromLen); | |
| uint16_t externalPort = ntohs(*((uint16_t*)&recvBuffer[26]));// ^ 0x2112; | |
| uint32_t externalIp = ntohl(*((uint32_t*)&recvBuffer[28]));// ^ 0x2112A442; | |
| char* extIp1 = ip32ToStr(externalIp); | |
| fprintf(stderr, "External IP1: %s", extIp1); | |
| nrecvd = recvfrom(sock2, (void*)recvBuffer, sizeof(recvBuffer), | |
| 0, (sockaddr*)&from, &fromLen); | |
| externalPort = ntohs(*((uint16_t*)&recvBuffer[26]));// ^ 0x2112; | |
| externalIp = ntohl(*((uint32_t*)&recvBuffer[28]));// ^ 0x2112A442; | |
| char* extIp2 = ip32ToStr(externalIp); | |
| fprintf(stderr, "External IP2: %s", extIp2); | |
| } |
Hi @avesus,
I need to make HTTP request on 2G/3g/4g only in iOS. In android its possible using connectivityManager trying to do the same in iOS but no luck.
If device is connected to Wifi and mobile data both, I need to check and make HTTP request over mobile network.
I know it is not possible to do with the high level API's. But with low-level APIs I can force a particular TCP connection to run over a particular interface, which allows this sort of thing.
Please provide a recommended solution for the same.
Regards,
Bhawna
Please, enumerate interfaces, obtain the last IP addresses, and re-bind sockets.
Hi, @avesus
I have used above code to make use of wifi and cellular interfaces in parallel.
But it don't work in Network Extensions(Packet Tunnel). I receive errno 49.
Please provide a recommended solution for me, Thanks!
Regards,
Kevinhao
@haojingjing2018 Did you got any solution? I am facing the same problem right now.
Hi @shivintu ,
Hope you have read the comment
// FIX THIS ACCORDING YOUR ACTUAL Wi-Fi and 3G IP Addressescarefully: you need two different IP addresses. Never bind to 0.0.0.0.
Which version of iOS you have used?