aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2010-08-04 16:56:27 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2010-08-04 16:56:27 +0000
commitd9dd3c0ff10c12133b4bfaf95e68cad34aef35e5 (patch)
treede7630b0d59051e4b606ba0611779ae11aca6f03
parent063b821d2badd1172fd92b348c6fa1ee751a738e (diff)
Can set multicast interface in MacOSX, added a udpsend_sock_err function to print system errors in the pd console instead of stderr.
svn path=/trunk/externals/mrpeach/; revision=13744
-rw-r--r--net/udpsend.c195
1 files changed, 140 insertions, 55 deletions
diff --git a/net/udpsend.c b/net/udpsend.c
index 0922c61..0fd2c32 100644
--- a/net/udpsend.c
+++ b/net/udpsend.c
@@ -13,7 +13,7 @@
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
-#include <iphlpapi.h> // for interface addresses
+#include <iphlpapi.h> // for interface addresses
#else
#include <sys/types.h>
#include <sys/socket.h>
@@ -23,7 +23,11 @@
#include <sys/ioctl.h> // for SIOCGIFCONF
#include <net/if.h> // for SIOCGIFCONF
#include <arpa/inet.h>
-#endif
+#include <errno.h>
+#endif // _WIN32
+#ifdef __APPLE__
+#include <ifaddrs.h> // for getifaddrs
+#endif // __APPLE__
static t_class *udpsend_class;
@@ -43,6 +47,7 @@ static void udpsend_connect(t_udpsend *x, t_symbol *hostname, t_floatarg fportno
static void udpsend_set_multicast_loopback(t_udpsend *x, t_floatarg loop_state);
static void udpsend_set_multicast_ttl(t_udpsend *x, t_floatarg ttl_hops);
static void udpsend_set_multicast_interface (t_udpsend *x, t_symbol *s, int argc, t_atom *argv);
+static void udpsend_sock_err(t_udpsend *x, char *err_string);
static void *udpsend_new(void);
static void *udpsend_new(void)
@@ -67,7 +72,7 @@ static void udpsend_connect(t_udpsend *x, t_symbol *hostname,
if (x->x_fd >= 0)
{
- error("udpsend: already connected");
+ pd_error(x, "udpsend: already connected");
return;
}
@@ -78,7 +83,7 @@ static void udpsend_connect(t_udpsend *x, t_symbol *hostname,
#endif
if (sockfd < 0)
{
- sys_sockerror("udpsend: socket");
+ udpsend_sock_err(x, "udpsend socket");
return;
}
/* Based on zmoelnig's patch 2221504:
@@ -86,7 +91,7 @@ Enable sending of broadcast messages (if hostname is a broadcast address)*/
#ifdef SO_BROADCAST
if( 0 != setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&broadcast, sizeof(broadcast)))
{
- pd_error(x, "couldn't switch to broadcast mode");
+ udpsend_sock_err(x, "couldn't switch to broadcast mode");
}
#endif /* SO_BROADCAST */
@@ -115,7 +120,7 @@ Enable sending of broadcast messages (if hostname is a broadcast address)*/
/* try to connect. */
if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
{
- sys_sockerror("udpsend: connecting stream socket");
+ udpsend_sock_err(x, "udpsend connect");
sys_closesocket(sockfd);
return;
}
@@ -131,7 +136,7 @@ static void udpsend_set_multicast_loopback(t_udpsend *x, t_floatarg loop_state)
if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP,
&multicast_loop_state, sizeof(multicast_loop_state)) < 0)
- error("udpreceive: setsockopt (IP_MULTICAST_LOOP) failed");
+ udpsend_sock_err(x, "udpsend setsockopt IP_MULTICAST_LOOP");
getsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &multicast_loop_state, &size);
x->x_multicast_loop_state = multicast_loop_state;
}
@@ -144,7 +149,7 @@ static void udpsend_set_multicast_ttl(t_udpsend *x, t_floatarg ttl_hops)
if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
&multicast_ttl, sizeof(multicast_ttl)) < 0)
- error("udpsend: setsockopt (IP_MULTICAST_LOOP) failed");
+ udpsend_sock_err(x, "udpsend setsockopt IP_MULTICAST_TTL");
getsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &multicast_ttl, &size);
x->x_multicast_ttl = multicast_ttl;
}
@@ -152,18 +157,18 @@ static void udpsend_set_multicast_ttl(t_udpsend *x, t_floatarg ttl_hops)
static void udpsend_set_multicast_interface (t_udpsend *x, t_symbol *s, int argc, t_atom *argv)
{
#ifdef _WIN32
- int i, n_ifaces = 32;
- PMIB_IPADDRTABLE pIPAddrTable;
- DWORD dwSize;
- DWORD dwRetVal = 0;
- IN_ADDR IPAddr;
- LPVOID lpMsgBuf;
- int if_index = -1;
- int found = 0;
- t_symbol *interfacename = gensym("none");
- struct hostent *hp = 0;
+ int i, n_ifaces = 32;
+ PMIB_IPADDRTABLE pIPAddrTable;
+ DWORD dwSize;
+ DWORD dwRetVal = 0;
+ IN_ADDR IPAddr;
+ LPVOID lpMsgBuf;
+ int if_index = -1;
+ int found = 0;
+ t_symbol *interfacename = gensym("none");
+ struct hostent *hp = 0;
struct sockaddr_in server;
-
+
if (x->x_fd < 0)
{
pd_error(x, "udpsend_set_multicast_interface: not connected");
@@ -188,43 +193,43 @@ static void udpsend_set_multicast_interface (t_udpsend *x, t_symbol *s, int argc
if (hp != 0) memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
else // maybe interface is its index (1) (names aren't available in _WIN32)
{
- /* get the list of interfaces, IPv4 only */
- dwSize = sizeof(MIB_IPADDRTABLE)*n_ifaces;
- if ((pIPAddrTable = (MIB_IPADDRTABLE *) getbytes(dwSize)) == NULL)
- {
- post("udpsend: unable to allocate %lu bytes for GetIpAddrTable", dwSize);
- return;
- }
- if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR)
- {
- post("udpsend: GetIpAddrTable failed with error %d", dwRetVal);
- if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) & lpMsgBuf, 0, NULL))
- {
- post("udpsend: %s", lpMsgBuf);
- LocalFree(lpMsgBuf);
- }
- return;
- }
-
- n_ifaces = pIPAddrTable->dwNumEntries;
+ /* get the list of interfaces, IPv4 only */
+ dwSize = sizeof(MIB_IPADDRTABLE)*n_ifaces;
+ if ((pIPAddrTable = (MIB_IPADDRTABLE *) getbytes(dwSize)) == NULL)
+ {
+ post("udpsend: unable to allocate %lu bytes for GetIpAddrTable", dwSize);
+ return;
+ }
+ if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR)
+ {
+ post("udpsend: GetIpAddrTable failed with error %d", dwRetVal);
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) & lpMsgBuf, 0, NULL))
+ {
+ post("udpsend: %s", lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ }
+ return;
+ }
+
+ n_ifaces = pIPAddrTable->dwNumEntries;
post("udpsend: %d interface%s available:", n_ifaces, (n_ifaces == 1)?"":"s");
- for (i = 0; i < n_ifaces; i++)
- {
- IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
+ for (i = 0; i < n_ifaces; i++)
+ {
+ IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
post("[%d]: %s", pIPAddrTable->table[i].dwIndex, inet_ntoa(IPAddr));
if (pIPAddrTable->table[i].dwIndex == if_index)
{
server.sin_addr = IPAddr;
found = 1;
}
- }
-
- if (pIPAddrTable)
- {
- freebytes(pIPAddrTable, dwSize);
- pIPAddrTable = NULL;
- }
+ }
+
+ if (pIPAddrTable)
+ {
+ freebytes(pIPAddrTable, dwSize);
+ pIPAddrTable = NULL;
+ }
if (! found)
{
post("udpsend_set_multicast_interface: bad host name? (%s)\n", interfacename->s_name);
@@ -232,10 +237,73 @@ static void udpsend_set_multicast_interface (t_udpsend *x, t_symbol *s, int argc
}
}
if (setsockopt(x->x_fd, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&server.sin_addr, sizeof(struct in_addr)) == SOCKET_ERROR)
- sys_sockerror("udpsend_set_multicast_interface: setsockopt");
+ udpsend_sock_err(x, "udpsend setsockopt IP_MULTICAST_IF");
else post("udpsend multicast interface is %s", inet_ntoa(server.sin_addr));
-#else
+#elif defined __APPLE__
+ int if_index = -1;
+ int found = 0;
+ t_symbol *interfacename = gensym("none");
+ struct ifaddrs *ifap;
+ int i = 0;
+ int n_ifaces = 0;
+ struct hostent *hp = 0;
+ struct sockaddr_in server;
+ struct sockaddr *sa;
+ char ifname[IFNAMSIZ]; /* longest possible interface name */
+
+ if (x->x_fd < 0)
+ {
+ pd_error(x, "udpsend_set_multicast_interface: not connected");
+ return;
+ }
+ switch (argv[0].a_type)
+ {
+ case A_FLOAT:
+ if_index = (int)atom_getfloat(&argv[0]);
+ break;
+ case A_SYMBOL:
+ interfacename = atom_getsymbol(&argv[0]);
+ break;
+ default:
+ pd_error(x, "udpsend_set_multicast_interface: argument not float or symbol");
+ return;
+ }
+ if (if_index == -1)
+ {
+ hp = gethostbyname(interfacename->s_name); // if interface is a dotted or named IP address (192.168.0.88)
+ }
+ if (hp != 0) memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+ else // maybe interface is its name (eth0) or index (1)
+ { // scan all the interfaces to get the IP address of interface
+ if (getifaddrs(&ifap)) udpsend_sock_err(x, "udpsend getifaddrs");
+ i = found = n_ifaces = 0;
+ while (NULL != ifap)
+ {
+ sa = ifap->ifa_addr;
+ if (AF_INET == sa->sa_family)
+ {
+ ++n_ifaces;
+ strncpy (ifname, ifap->ifa_name, IFNAMSIZ);
+ post("[%d]: %s: %s", i, ifname, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr));
+ if((i == if_index) || ((if_index == -1) && (!strncmp(interfacename->s_name, ifname, IFNAMSIZ))))
+ { // either the index or the name match
+ server.sin_addr = ((struct sockaddr_in *)sa)->sin_addr;
+ found = 1;
+ }
+ }
+ i++;
+ ifap = ifap->ifa_next; // next record or NULL
+ }
+ freeifaddrs(ifap);
+ post ("udpsend: %d interfaces", n_ifaces);
+ if (!found) return;
+ }
+ if (setsockopt(x->x_fd, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&server.sin_addr, sizeof(struct in_addr)))
+ udpsend_sock_err(x, "udpsend setsockopt IP_MULTICAST_IF");
+ else post("udpsend multicast interface is %s", inet_ntoa(server.sin_addr));
+ return;
+#else // __linux__
struct sockaddr_in server;
struct sockaddr *sa;
struct hostent *hp = 0;
@@ -244,7 +312,7 @@ static void udpsend_set_multicast_interface (t_udpsend *x, t_symbol *s, int argc
char ifname[IFNAMSIZ]; /* longest possible interface name */
t_symbol *interface = gensym("none");
int if_index = -1;
-
+
if (x->x_fd < 0)
{
pd_error(x, "udpsend_set_multicast_interface: not connected");
@@ -276,7 +344,7 @@ static void udpsend_set_multicast_interface (t_udpsend *x, t_symbol *s, int argc
if (ifc.ifc_buf != NULL)
{ //
if (ioctl(x->x_fd, SIOCGIFCONF, &ifc) < 0) // get list of interfaces
- sys_sockerror("udpsend_set_multicast_interface: getting list of interfaces");
+ udpsend_sock_err(x, "udpsend_set_multicast_interface: getting list of interfaces");
else
{
n_ifaces = ifc.ifc_len/sizeof(struct ifreq);
@@ -307,11 +375,28 @@ static void udpsend_set_multicast_interface (t_udpsend *x, t_symbol *s, int argc
}
}
if (setsockopt(x->x_fd, IPPROTO_IP, IP_MULTICAST_IF, &server.sin_addr, sizeof(struct in_addr)) < 0)
- sys_sockerror("udpsend_set_multicast_interface: setsockopt");
+ udpsend_sock_err(x, "udpsend_set_multicast_interface: setsockopt");
else post("udpsend multicast interface is %s", inet_ntoa(server.sin_addr));
#endif // _WIN32
}
+static void udpsend_sock_err(t_udpsend *x, char *err_string)
+{
+/* prints the last error from errno or WSAGetLasError() */
+#ifdef _WIN32
+ LPVOID lpMsgBuf;
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
+ , NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpMsgBuf, 0, NULL))
+ {
+ pd_error(x, "%s: %s (%d)", err_string, WSAGetLastError());
+ post("udpsend: %s", lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ }
+#else
+ pd_error(x, "%s: %s (%d)", err_string, strerror(errno), errno);
+#endif
+}
+
static void udpsend_disconnect(t_udpsend *x)
{
if (x->x_fd >= 0)
@@ -430,7 +515,7 @@ static void udpsend_send(t_udpsend *x, t_symbol *s, int argc, t_atom *argv)
}
if (result <= 0)
{
- sys_sockerror("udpsend");
+ udpsend_sock_err(x, "udpsend send");
udpsend_disconnect(x);
break;
}