Skip to content

Commit

Permalink
Add multicast and broadcast support
Browse files Browse the repository at this point in the history
  • Loading branch information
emilmont committed Mar 1, 2013
1 parent 6a57daf commit a80058d
Show file tree
Hide file tree
Showing 20 changed files with 284 additions and 28 deletions.
18 changes: 16 additions & 2 deletions libraries/net/EthernetInterface/EthernetInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
/* TCP/IP and Network Interface Initialisation */
static struct netif lpcNetif;

static char ip_addr[16] = "\0";
static char mac_addr[19];
static char ip_addr[17] = "\0";
static bool use_dhcp = false;

static Semaphore tcpip_inited(0);
Expand Down Expand Up @@ -67,14 +68,23 @@ static void init_netif(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw) {
netif_set_status_callback(&lpcNetif, netif_status_callback);
}

static void set_mac_address(void) {
char mac[6];
mbed_mac_address(mac);
snprintf(mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

int EthernetInterface::init() {
use_dhcp = true;
set_mac_address();
init_netif(NULL, NULL, NULL);
return 0;
}

int EthernetInterface::init(const char* ip, const char* mask, const char* gateway) {
use_dhcp = false;

set_mac_address();
strcpy(ip_addr, ip);

ip_addr_t ip_n, mask_n, gateway_n;
Expand All @@ -94,7 +104,7 @@ int EthernetInterface::connect(unsigned int timeout_ms) {
if (use_dhcp) {
dhcp_start(&lpcNetif);

// Wait for an IP
// Wait for an IP Address
// -1: error, 0: timeout
inited = netif_up.wait(timeout_ms);
} else {
Expand All @@ -120,6 +130,10 @@ int EthernetInterface::disconnect() {
return 0;
}

char* EthernetInterface::getMACAddress() {
return mac_addr;
}

char* EthernetInterface::getIPAddress() {
return ip_addr;
}
12 changes: 10 additions & 2 deletions libraries/net/EthernetInterface/EthernetInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,25 @@ class EthernetInterface {

/** Connect
* Bring the interface up, start DHCP if needed.
* \param timeout_ms timeout in ms (default: (10)s).
* \param timeout_ms timeout in ms (default: (15)s).
* \return 0 on success, a negative number on failure
*/
static int connect(unsigned int timeout_ms=10000);
static int connect(unsigned int timeout_ms=15000);

/** Disconnect
* Bring the interface down
* \return 0 on success, a negative number on failure
*/
static int disconnect();

/** Get the MAC address of your Ethernet interface
* \return a pointer to a string containing the MAC address
*/
static char* getMACAddress();

/** Get the IP address of your Ethernet interface
* \return a pointer to a string containing the IP address
*/
static char* getIPAddress();
};

Expand Down
2 changes: 2 additions & 0 deletions libraries/net/EthernetInterface/lwip-eth/arch/lpc17_emac.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,8 @@ static struct pbuf *lpc_low_level_input(struct netif *netif)
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
("lpc_low_level_input: Packet dropped with errors (0x%x)\n",
lpc_enetif->prxs[idx].statusinfo));

p = NULL;
} else {
/* A packet is waiting, get length */
length = (lpc_enetif->prxs[idx].statusinfo & 0x7FF) + 1;
Expand Down
34 changes: 23 additions & 11 deletions libraries/net/lwip/Socket/Endpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,42 @@
#include "Socket/Socket.h"
#include "Socket/Endpoint.h"
#include <cstring>

using std::memset;
#include <cstdio>

Endpoint::Endpoint() {
reset_address();
}
Endpoint::~Endpoint() {}

void Endpoint::reset_address(void) {
memset(&_remoteHost, 0, sizeof(struct sockaddr_in));
std::memset(&_remoteHost, 0, sizeof(struct sockaddr_in));
_ipAddress[0] = '\0';
}

#include "stdio.h"

int Endpoint::set_address(const char* host, const int port) {
//Resolve DNS address or populate hard-coded IP address
struct hostent *server = ::gethostbyname(host);
if (server == NULL)
return -1; //Could not resolve address

reset_address();

// Set IP address
std::memcpy((char*) &_remoteHost.sin_addr.s_addr,
(char*) server->h_addr_list[0], server->h_length);
// IP Address
char address[5];
char *p_address = address;

// Dot-decimal notation
int result = std::sscanf(host, "%3u.%3u.%3u.%3u",
(unsigned int*)&address[0], (unsigned int*)&address[1],
(unsigned int*)&address[2], (unsigned int*)&address[3]);

if (result != 4) {
// Resolve address with DNS
struct hostent *host_address = lwip_gethostbyname(host);
if (host_address == NULL)
return -1; //Could not resolve address
p_address = (char*)host_address->h_addr_list[0];
}
std::memcpy((char*)&_remoteHost.sin_addr.s_addr, p_address, 4);

// Address family
_remoteHost.sin_family = AF_INET;

// Set port
Expand Down
2 changes: 1 addition & 1 deletion libraries/net/lwip/Socket/Endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Endpoint {
int get_port(void);

protected:
char _ipAddress[16];
char _ipAddress[17];
struct sockaddr_in _remoteHost;

};
Expand Down
8 changes: 8 additions & 0 deletions libraries/net/lwip/Socket/Socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ int Socket::init_socket(int type) {
return 0;
}

int Socket::set_option(int level, int optname, const void *optval, socklen_t optlen) {
return lwip_setsockopt(_sock_fd, level, optname, optval, optlen);
}

int Socket::get_option(int level, int optname, void *optval, socklen_t *optlen) {
return lwip_getsockopt(_sock_fd, level, optname, optval, optlen);
}

int Socket::select(struct timeval *timeout, bool read, bool write) {
fd_set fdSet;
FD_ZERO(&fdSet);
Expand Down
18 changes: 18 additions & 0 deletions libraries/net/lwip/Socket/Socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ class Socket {
*/
void set_blocking(bool blocking, unsigned int timeout=1500);

/** Set socket options
\param level stack level (see: lwip/sockets.h)
\param optname option ID
\param optval option value
\param socklen_t length of the option value
\return 0 on success, -1 on failure
*/
int set_option(int level, int optname, const void *optval, socklen_t optlen);

/** Get socket options
\param level stack level (see: lwip/sockets.h)
\param optname option ID
\param optval buffer pointer where to write the option value
\param socklen_t length of the option value
\return 0 on success, -1 on failure
*/
int get_option(int level, int optname, void *optval, socklen_t *optlen);

/** Close the socket file descriptor
*/
int close();
Expand Down
15 changes: 15 additions & 0 deletions libraries/net/lwip/Socket/UDPSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ int UDPSocket::bind(int port) {
return 0;
}

int UDPSocket::join_multicast_group(const char* address) {
struct ip_mreq mreq;

// Set up group address
mreq.imr_multiaddr.s_addr = inet_addr(address);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);

return set_option(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
}

int UDPSocket::set_broadcasting(void) {
int option = 1;
return set_option(SOL_SOCKET, SO_BROADCAST, &option, sizeof(option));
}

// -1 if unsuccessful, else number of bytes written
int UDPSocket::sendTo(Endpoint &remote, char *packet, int length) {
if (_sock_fd < 0)
Expand Down
11 changes: 11 additions & 0 deletions libraries/net/lwip/Socket/UDPSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ class UDPSocket : public Socket {
*/
int bind(int port);

/** Join the multicast group at the given address
\param address The address of the multicast group
\return 0 on success, -1 on failure.
*/
int join_multicast_group(const char* address);

/** Set the socket in broadcasting mode
\return 0 on success, -1 on failure.
*/
int set_broadcasting(void);

/** Send a packet to a remote endpoint
\param remote The remote endpoint
\param packet The packet to be sent
Expand Down
12 changes: 0 additions & 12 deletions libraries/net/lwip/lwip/core/ipv4/igmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr);
static err_t igmp_remove_group(struct igmp_group *group);
static void igmp_timeout( struct igmp_group *group);
static void igmp_start_timer(struct igmp_group *group, u8_t max_time);
static void igmp_stop_timer(struct igmp_group *group);
static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif);
static void igmp_send(struct igmp_group *group, u8_t type);
Expand Down Expand Up @@ -706,17 +705,6 @@ igmp_start_timer(struct igmp_group *group, u8_t max_time)
group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
}

/**
* Stop a timer for an igmp_group
*
* @param group the igmp_group for which to stop the timer
*/
static void
igmp_stop_timer(struct igmp_group *group)
{
group->timer = 0;
}

/**
* Delaying membership report for a group if necessary
*
Expand Down
5 changes: 5 additions & 0 deletions libraries/net/lwip/lwip/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
#define LWIP_DHCP 1
#define LWIP_DNS 1

// Support Multicast
#include "stdlib.h"
#define LWIP_IGMP 1
#define LWIP_RAND() rand()

#define LWIP_COMPAT_SOCKETS 0
#define LWIP_POSIX_SOCKETS_IO_NAMES 0
#define LWIP_SO_RCVTIMEO 1
Expand Down
23 changes: 23 additions & 0 deletions libraries/tests/net/helloworld/broadcast_receive/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "mbed.h"
#include "EthernetInterface.h"

const int BROADCAST_PORT = 58083;

int main() {
EthernetInterface eth;
eth.init(); //Use DHCP
eth.connect();

UDPSocket socket;
socket.bind(BROADCAST_PORT);
socket.set_broadcasting();

Endpoint broadcaster;
char buffer[256];
while (true) {
printf("\nWait for packet...\n");
int n = socket.receiveFrom(broadcaster, buffer, sizeof(buffer));
buffer[n] = '\0';
printf("Packet from \"%s\": %s\n", broadcaster.get_address(), buffer);
}
}
25 changes: 25 additions & 0 deletions libraries/tests/net/helloworld/broadcast_send/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "mbed.h"
#include "EthernetInterface.h"

const int BROADCAST_PORT = 58083;

int main() {
EthernetInterface eth;
eth.init(); //Use DHCP
eth.connect();

UDPSocket sock;
sock.init();
sock.set_broadcasting();

Endpoint broadcast;
broadcast.set_address("255.255.255.255", BROADCAST_PORT);

char out_buffer[] = "very important data";

while (true) {
printf("Broadcasting...\n");
sock.sendTo(broadcast, out_buffer, sizeof(out_buffer));
Thread::wait(1000);
}
}
27 changes: 27 additions & 0 deletions libraries/tests/net/helloworld/multicast_receive/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "mbed.h"
#include "EthernetInterface.h"

const char* MCAST_GRP = "224.1.1.1";
const int MCAST_PORT = 5007;

int main() {
EthernetInterface eth;
eth.init(); //Use DHCP
eth.connect();

UDPSocket server;
server.bind(MCAST_PORT);
if (server.join_multicast_group(MCAST_GRP) != 0) {
printf("Error joining the multicast group\n");
while (true) {}
}

Endpoint client;
char buffer[256];
while (true) {
printf("\nWait for packet...\n");
int n = server.receiveFrom(client, buffer, sizeof(buffer));

printf("Packet from \"%s\": %s\n", client.get_address(), buffer);
}
}
24 changes: 24 additions & 0 deletions libraries/tests/net/helloworld/multicast_send/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "mbed.h"
#include "EthernetInterface.h"

const char* MCAST_GRP = "224.1.1.1";
const int MCAST_PORT = 5007;

int main() {
EthernetInterface eth;
eth.init(); //Use DHCP
eth.connect();

UDPSocket sock;
sock.init();

Endpoint multicast_group;
multicast_group.set_address(MCAST_GRP, MCAST_PORT);

char out_buffer[] = "very important data";
while (true) {
printf("Multicast to group: %s\n", MCAST_GRP);
sock.sendTo(multicast_group, out_buffer, sizeof(out_buffer));
Thread::wait(1000);
}
}
9 changes: 9 additions & 0 deletions workspace_tools/host_tests/example/BroadcastReceive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import socket

BROADCAST_PORT = 58083

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('0.0.0.0', BROADCAST_PORT))

while True:
print s.recvfrom(256)
14 changes: 14 additions & 0 deletions workspace_tools/host_tests/example/BroadcastSend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import socket
from time import sleep, time

BROADCAST_PORT = 58083

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', 0))
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

while True:
print "Broadcasting..."
data = 'Hello World: ' + repr(time()) + '\n'
s.sendto(data, ('<broadcast>', BROADCAST_PORT))
sleep(1)
Loading

0 comments on commit a80058d

Please sign in to comment.