get sender IP address of OSC message

Hello,

I’m trying to have several iPhones communicate on local network using OSC broadcast messages to establish links between each device.

When receiving a message, is there a way to know the IP of the sender, in order to be able to reply directly without broadcasting ?

Or if not possible, how the sender can know his own IP (dynamically) so that it can send it as a parameter with his initial broadcast message ?

Thank you.

I found out that ofxOsc has a method ofxOscMessage::getRemoteIp().

in the addon I currently use, ofxOsciPhone, this method does not exist. Since I found this add on on this forum (link to a zip), I’m wondering where the source is. Is there a repository to get the latest version ? May be the missing function has already be added.

Otherwise, I will try to add it to ofxOsciPhone and if successfull, I could contribute by updating the repository. If I know where to contribute.

interesting, where did you find ofxOsciPhone? As far as I can remember, you can use the normal ofxOsc on iphone. ofxOsc is a wrapper for oscpack, and in the normal distribution of ofxOsc oscpack is provided as a precompiled lib (oscpack.a for mac). If you remove the lib folder, and instead download the source of oscpack and include that in your project it should all compile and work fine - note you may have to add oscpack to your header search path in your xcode project. Alternativly, you could just get the latest ofxOsc, and replace the oscpack.a with the oscpack.a from your ofxOscIphone. Hope that makes sense

I found ofxOsciPhone on this forum. There is a link to a zip file in this post:
http://forum.openframeworks.cc/t/iphone-to-arduino/2279/5

There is not many differences between this version and the ofxOsc, I merged most of them from ofxOsc to get the getRemoteIp() function working (also use string instead of char*)

I tried (before my first post) to use ofxOsc, but there were many errors and I gave up. Probably because of missing or misuse of oscpack. I could try again with your explanations, but since it’s working now, there are other problems to handle. I will however try again next time I need Osc on iPhone.

yeah, ofxosciphone was just the name of the zip i put up a while ago. Actually forgot I did this, I had the same thought memo (“what? ofxosciPhone, sounds interesting!”)… its just osciPhone002 or 03 with the change made so it can broadcast and with an uncompiled version of oscpack so it compiles properly for the iphone

So, now that I can broadcast OSC messages and the receiver can get the IP of the sender, there is one remaining problem: The sender has to know his IP and subnet mask to build the broadcast address.

Do you know how to get these 2 infos ? I already http://forum.openframeworks.cc/t/broadcasting-with-ofxosc/1625/6 in the advanced forum, but since this is probably specific to iPhone, I ask here again.

Thank you.

this is the code I found for getting the IP address, unfortunately I haven’t found how to find the subnet mask

  
/*  
 *  IPAddress.h  
*/  
#pragma once  
  
#define MAXADDRS	32  
  
extern char *if_names[MAXADDRS];  
extern char *ip_names[MAXADDRS];  
extern char *hw_addrs[MAXADDRS];  
extern unsigned long ip_addrs[MAXADDRS];  
  
// Function prototypes  
  
void InitAddresses();  
void FreeAddresses();  
void GetIPAddresses();  
void GetHWAddresses();  
  
  

  
  
/*  
 *  IPAddress.c  
 */  
  
#include "IPAddress.h"  
  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/ioctl.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <netdb.h>  
#include <arpa/inet.h>  
#include <sys/sockio.h>  
#include <net/if.h>  
#include <errno.h>  
#include <net/if_dl.h>  
  
  
#define	min(a,b)	((a) < (b) ? (a) : (b))  
#define	max(a,b)	((a) > (b) ? (a) : (b))  
  
#define BUFFERSIZE	4000  
  
char *if_names[MAXADDRS];  
char *ip_names[MAXADDRS];  
char *hw_addrs[MAXADDRS];  
unsigned long ip_addrs[MAXADDRS];  
  
static int   nextAddr = 0;  
  
void InitAddresses()  
{  
	int i;  
	for (i=0; i<MAXADDRS; ++i)  
	{  
		if_names[i] = ip_names[i] = hw_addrs[i] = NULL;  
		ip_addrs[i] = 0;  
	}  
}  
  
void FreeAddresses()  
{  
	int i;  
	for (i=0; i<MAXADDRS; ++i)  
	{  
		if (if_names[i] != 0) free(if_names[i]);  
		if (ip_names[i] != 0) free(ip_names[i]);  
		if (hw_addrs[i] != 0) free(hw_addrs[i]);  
		ip_addrs[i] = 0;  
	}  
	InitAddresses();  
}  
  
void GetIPAddresses()  
{  
	int                 i, len, flags;  
	char                buffer[BUFFERSIZE], *ptr, lastname[IFNAMSIZ], *cptr;  
	struct ifconf       ifc;  
	struct ifreq        *ifr, ifrcopy;  
	struct sockaddr_in	*sin;  
	  
	char temp[80];  
	  
	int sockfd;  
	  
	for (i=0; i<MAXADDRS; ++i)  
	{  
		if_names[i] = ip_names[i] = NULL;  
		ip_addrs[i] = 0;  
	}  
	  
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
	if (sockfd < 0)  
	{  
		perror("socket failed");  
		return;  
	}  
	  
	ifc.ifc_len = BUFFERSIZE;  
	ifc.ifc_buf = buffer;  
	  
	if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)  
	{  
		perror("ioctl error");  
		return;  
	}  
	  
	lastname[0] = 0;  
	  
	for (ptr = buffer; ptr < buffer + ifc.ifc_len; )  
	{  
		ifr = (struct ifreq *)ptr;  
		len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);  
		ptr += sizeof(ifr->ifr_name) + len;	// for next one in buffer  
		  
		if (ifr->ifr_addr.sa_family != AF_INET)  
		{  
			continue;	// ignore if not desired address family  
		}  
		  
		if ((cptr = (char *)strchr(ifr->ifr_name, ':')) != NULL)  
		{  
			*cptr = 0;		// replace colon will null  
		}  
		  
		if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0)  
		{  
			continue;	/* already processed this interface */  
		}  
		  
		memcpy(lastname, ifr->ifr_name, IFNAMSIZ);  
		  
		ifrcopy = *ifr;  
		ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy);  
		flags = ifrcopy.ifr_flags;  
		if ((flags & IFF_UP) == 0)  
		{  
			continue;	// ignore if interface not up  
		}  
		  
		if_names[nextAddr] = (char *)malloc(strlen(ifr->ifr_name)+1);  
		if (if_names[nextAddr] == NULL)  
		{  
			return;  
		}  
		strcpy(if_names[nextAddr], ifr->ifr_name);  
		  
		sin = (struct sockaddr_in *)&ifr->ifr_addr;  
		strcpy(temp, inet_ntoa(sin->sin_addr));  
		  
		ip_names[nextAddr] = (char *)malloc(strlen(temp)+1);  
		if (ip_names[nextAddr] == NULL)  
		{  
			return;  
		}  
		strcpy(ip_names[nextAddr], temp);  
		  
		ip_addrs[nextAddr] = sin->sin_addr.s_addr;  
		  
		++nextAddr;  
	}  
	  
	close(sockfd);  
}  
  
void GetHWAddresses()  
{  
	struct ifconf ifc;  
	struct ifreq *ifr;  
	int i, sockfd;  
	char buffer[BUFFERSIZE], *cp, *cplim;  
	char temp[80];  
	  
	for (i=0; i<MAXADDRS; ++i)  
	{  
		hw_addrs[i] = NULL;  
	}  
	  
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
	if (sockfd < 0)  
	{  
		perror("socket failed");  
		return;  
	}  
	  
	ifc.ifc_len = BUFFERSIZE;  
	ifc.ifc_buf = buffer;  
	  
	if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0)  
	{  
		perror("ioctl error");  
		close(sockfd);  
		return;  
	}  
	  
	ifr = ifc.ifc_req;  
	  
	cplim = buffer + ifc.ifc_len;  
	  
	for (cp=buffer; cp < cplim; )  
	{  
		ifr = (struct ifreq *)cp;  
		if (ifr->ifr_addr.sa_family == AF_LINK)  
		{  
			struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;  
			int a,b,c,d,e,f;  
			int i;  
			  
			strcpy(temp, (char *)ether_ntoa(LLADDR(sdl)));  
			sscanf(temp, "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f);  
			sprintf(temp, "%02X:%02X:%02X:%02X:%02X:%02X",a,b,c,d,e,f);  
			  
			for (i=0; i<MAXADDRS; ++i)  
			{  
				if ((if_names[i] != NULL) && (strcmp(ifr->ifr_name, if_names[i]) == 0))  
				{  
					if (hw_addrs[i] == NULL)  
					{  
						hw_addrs[i] = (char *)malloc(strlen(temp)+1);  
						strcpy(hw_addrs[i], temp);  
						break;  
					}  
				}  
			}  
		}  
		cp += sizeof(ifr->ifr_name) + max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);  
	}  
	  
	close(sockfd);  
}  
  

Just a small update a few months later… :slight_smile:

Thanks for the code, Memo! I had to do a couple of extra things to get it to build without complaining (am running XCode 3.2.4 with SDK 3.2 / 4.1 on OF v0061):

First error I got was “‘ether_addr’ was not declared in this scope”.

I fixed this by adding #include <net/ethernet.h> in IPAddress.c

Build and I got a new error: cannot convert ‘char*’ to ‘const ether_addr*’ for argument ‘1’ to ‘char* ether_ntoa(const ether_addr*)’

So I added a cast in there, just to get it to compile ok.

  
strcpy(temp, (char *)ether_ntoa(LLADDR(sdl)));  

->

  
strcpy(temp, (char *)ether_ntoa((ether_addr*)LLADDR(sdl)));  

Tbh, I’ve no idea whether the cast works, I’ve a feeling it doesn’t, but it allows it to compile and I get the correct device IP displayed…

I’d be interested to hear how other people got it compiling ok…

If you want to get the public IP Address, for people outside of LAN, here is a quick hack:

  
// Gets the IP address from a web service, and parses out the IP. A hack, not sure if it will work for P2P application.   
// TODO: Test public IP Remotely.   
  
void testApp::getPublicIPAddress() {  
	myPublicIP = "";   
	pubIP = popen("curl -s checkip.dyndns.org|sed -e 's/.*Current IP Address: //' -e 's/<.*$//'", "r");  //modes w and r  
	char ip[128];   
	if (fgets(ip, 128, pubIP) != NULL) {		  
		//strip the endline character from the end of the string.   
		int len = strlen(ip);  
		if( ip[len-1] == '\n' ) ip[len-1] = 0;  
		myPublicIP.append(ip);  
		  
		printf("\n PUBLIC IP: '%s' \n", myPublicIP.c_str());   
	}  
	pclose(pubIP);  
}