Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@avesus
Created April 21, 2015 22:30
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save avesus/fdb465b60a4f5204845c to your computer and use it in GitHub Desktop.
Save avesus/fdb465b60a4f5204845c to your computer and use it in GitHub Desktop.
iOS Multipath BSD Sockets Test. Comments welcomed!
# 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);
}
@shivintu
Copy link

shivintu commented Aug 1, 2015

Hi,
I have used above code to make use of wifi and cellular interfaces in parallel. The thing is even I switched off wifi and try to send data using cellular interface the two sendto(sock1, ....) sendto(sock2, ....) uses cellular interfaces why the sock1 didn't throw error as it is wifi and its off to send the data?

@avesus
Copy link
Author

avesus commented Apr 21, 2016

Hi @shivintu ,
Hope you have read the comment // FIX THIS ACCORDING YOUR ACTUAL Wi-Fi and 3G IP Addresses
carefully: you need two different IP addresses. Never bind to 0.0.0.0.
Which version of iOS you have used?

@BhawnaBhandari24
Copy link

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

@avesus
Copy link
Author

avesus commented May 11, 2017

Hi @BhawnaBhandari24,

Please, enumerate interfaces, obtain the last IP addresses, and re-bind sockets.

@haojingjing2018
Copy link

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

@RahulRai02
Copy link

@haojingjing2018 Did you got any solution? I am facing the same problem right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment