Skip to content

Commit c411cd7

Browse files
committed
Add multicast implementation for UDPSocket
1 parent acdd7dd commit c411cd7

File tree

4 files changed

+90
-13
lines changed

4 files changed

+90
-13
lines changed

features/FEATURE_LWIP/lwip-interface/lwip_stack.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "lwip/mld6.h"
3535
#include "lwip/dns.h"
3636
#include "lwip/udp.h"
37+
#include "lwip_errno.h"
3738
#include "netif/lwip_ethernet.h"
3839
#include "emac_api.h"
3940
#include "ppp_lwip.h"
@@ -980,6 +981,25 @@ static nsapi_size_or_error_t mbed_lwip_socket_recvfrom(nsapi_stack_t *stack, nsa
980981
return recv;
981982
}
982983

984+
static nsapi_error_t nsapi_addr_to_ip_addr(ip_addr_t *lwip_ip, nsapi_addr_t *nsapi_addr_ip) {
985+
struct in_addr inet_addr_convert;
986+
// nsapi_addr_t stores IP address in byte array
987+
// Convert byte aray -> uint32_t for lwip inet IP representation
988+
ip_addr_t multiaddr_ip;
989+
if (!convert_mbed_addr_to_lwip(&multiaddr_ip, nsapi_addr_ip)) {
990+
return NSAPI_ERROR_PARAMETER;
991+
}
992+
993+
inet_addr_convert.s_addr = multiaddr_ip.addr;
994+
995+
#if LWIP_IPV4
996+
// LWIP inet IP representation (in_addr) to ip_addr_t, both structs containing
997+
// uint32_t, this step just remaps the ip address for the igmp calls
998+
lwip_ip->addr = inet_addr_convert.s_addr;
999+
#endif
1000+
return NSAPI_ERROR_OK;
1001+
}
1002+
9831003
static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)
9841004
{
9851005
struct lwip_socket *s = (struct lwip_socket *)handle;
@@ -1023,6 +1043,36 @@ static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t h
10231043
}
10241044
return 0;
10251045

1046+
case NSAPI_ADD_MEMBERSHIP:
1047+
case NSAPI_DROP_MEMBERSHIP: {
1048+
#if LWIP_IPV6
1049+
return NSAPI_ERROR_UNSUPPORTED;
1050+
#else
1051+
if (optlen != sizeof(nsapi_ip_mreq_t)) {
1052+
return NSAPI_ERROR_UNSUPPORTED;
1053+
}
1054+
1055+
err_t igmp_err;
1056+
nsapi_ip_mreq_t *imr = (nsapi_ip_mreq_t *)optval;
1057+
1058+
ip_addr_t if_addr;
1059+
ip_addr_t multi_addr;
1060+
1061+
nsapi_addr_to_ip_addr(&multi_addr, &imr->imr_multiaddr);
1062+
nsapi_addr_to_ip_addr(&if_addr, &imr->imr_interface);
1063+
1064+
if (optname == NSAPI_ADD_MEMBERSHIP) {
1065+
igmp_err = igmp_joingroup(&if_addr, &multi_addr);
1066+
} else {
1067+
igmp_err = igmp_leavegroup(&if_addr, &multi_addr);
1068+
}
1069+
if (igmp_err != ERR_OK) {
1070+
return EADDRNOTAVAIL;
1071+
}
1072+
return 0;
1073+
#endif
1074+
}
1075+
10261076
default:
10271077
return NSAPI_ERROR_UNSUPPORTED;
10281078
}

features/netsocket/UDPSocket.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ nsapi_protocol_t UDPSocket::get_proto()
3333
return NSAPI_UDP;
3434
}
3535

36+
int UDPSocket::join_multicast_group(const SocketAddress &address)
37+
{
38+
nsapi_ip_mreq_t mreq;
39+
40+
// Set up group address
41+
mreq.imr_multiaddr = address.get_addr();
42+
mreq.imr_interface = SocketAddress().get_addr(); // 0.0.0.0 INADDR_ANY
43+
44+
return this->setsockopt(0, NSAPI_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
45+
}
46+
3647
nsapi_size_or_error_t UDPSocket::sendto(const char *host, uint16_t port, const void *data, nsapi_size_t size)
3748
{
3849
SocketAddress address;

features/netsocket/UDPSocket.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ class UDPSocket : public Socket {
5656
*/
5757
virtual ~UDPSocket();
5858

59+
/** Subscribes to an IP multicast group
60+
*
61+
* @param address Multicast group IP address
62+
* @return Negative error code on failure
63+
*/
64+
int join_multicast_group(const SocketAddress &address);
65+
5966
/** Send a packet over a UDP socket
6067
*
6168
* Sends data to the specified address specified by either a domain name

features/netsocket/nsapi_types.h

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ typedef void *nsapi_socket_t;
158158
/** Enum of socket protocols
159159
*
160160
* The socket protocol specifies a particular protocol to
161-
* be used with a newly created socket.
161+
* be used with a newly created socket.
162162
*
163163
* @enum nsapi_protocol
164164
*/
@@ -207,13 +207,15 @@ typedef enum nsapi_socket_level {
207207
* @enum nsapi_socket_option
208208
*/
209209
typedef enum nsapi_socket_option {
210-
NSAPI_REUSEADDR, /*!< Allow bind to reuse local addresses */
211-
NSAPI_KEEPALIVE, /*!< Enables sending of keepalive messages */
212-
NSAPI_KEEPIDLE, /*!< Sets timeout value to initiate keepalive */
213-
NSAPI_KEEPINTVL, /*!< Sets timeout value for keepalive */
214-
NSAPI_LINGER, /*!< Keeps close from returning until queues empty */
215-
NSAPI_SNDBUF, /*!< Sets send buffer size */
216-
NSAPI_RCVBUF, /*!< Sets recv buffer size */
210+
NSAPI_REUSEADDR, /*!< Allow bind to reuse local addresses */
211+
NSAPI_KEEPALIVE, /*!< Enables sending of keepalive messages */
212+
NSAPI_KEEPIDLE, /*!< Sets timeout value to initiate keepalive */
213+
NSAPI_KEEPINTVL, /*!< Sets timeout value for keepalive */
214+
NSAPI_LINGER, /*!< Keeps close from returning until queues empty */
215+
NSAPI_SNDBUF, /*!< Sets send buffer size */
216+
NSAPI_RCVBUF, /*!< Sets recv buffer size */
217+
NSAPI_ADD_MEMBERSHIP, /*!< Add membership to multicast address */
218+
NSAPI_DROP_MEMBERSHIP, /*!< Drop membership to multicast address */
217219
} nsapi_socket_option_t;
218220

219221
/* Backwards compatibility - previously didn't distinguish stack and socket options */
@@ -254,6 +256,13 @@ typedef struct nsapi_stack {
254256
unsigned _stack_buffer[16];
255257
} nsapi_stack_t;
256258

259+
/** nsapi_ip_mreq structure
260+
*/
261+
typedef struct nsapi_ip_mreq {
262+
nsapi_addr_t imr_multiaddr; /* IP multicast address of group */
263+
nsapi_addr_t imr_interface; /* local IP address of interface */
264+
} nsapi_ip_mreq_t;
265+
257266
/** nsapi_stack_api structure
258267
*
259268
* Common api structure for network stack operations. A network stack
@@ -275,9 +284,9 @@ typedef struct nsapi_stack_api
275284
*
276285
* The hostname may be either a domain name or an IP address. If the
277286
* hostname is an IP address, no network transactions will be performed.
278-
*
287+
*
279288
* If no stack-specific DNS resolution is provided, the hostname
280-
* will be resolve using a UDP socket on the stack.
289+
* will be resolve using a UDP socket on the stack.
281290
*
282291
* @param stack Stack handle
283292
* @param addr Destination for the host IP address
@@ -322,7 +331,7 @@ typedef struct nsapi_stack_api
322331
* @param optval Destination for option value
323332
* @param optlen Length of the option value
324333
* @return 0 on success, negative error code on failure
325-
*/
334+
*/
326335
nsapi_error_t (*getstackopt)(nsapi_stack_t *stack, int level,
327336
int optname, void *optval, unsigned *optlen);
328337

@@ -523,7 +532,7 @@ typedef struct nsapi_stack_api
523532
* @param optval Option value
524533
* @param optlen Length of the option value
525534
* @return 0 on success, negative error code on failure
526-
*/
535+
*/
527536
nsapi_error_t (*setsockopt)(nsapi_stack_t *stack, nsapi_socket_t socket, int level,
528537
int optname, const void *optval, unsigned optlen);
529538

@@ -540,7 +549,7 @@ typedef struct nsapi_stack_api
540549
* @param optval Destination for option value
541550
* @param optlen Length of the option value
542551
* @return 0 on success, negative error code on failure
543-
*/
552+
*/
544553
nsapi_error_t (*getsockopt)(nsapi_stack_t *stack, nsapi_socket_t socket, int level,
545554
int optname, void *optval, unsigned *optlen);
546555
} nsapi_stack_api_t;

0 commit comments

Comments
 (0)