diff options
Diffstat (limited to 'code/jasmine/udp-common.c')
-rwxr-xr-x | code/jasmine/udp-common.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/code/jasmine/udp-common.c b/code/jasmine/udp-common.c new file mode 100755 index 00000000..c7314226 --- /dev/null +++ b/code/jasmine/udp-common.c @@ -0,0 +1,97 @@ +/*############################################################################## +# Copyright (c) 2017 ZTE Coreporation and others. +# hu.zhijiang@zte.com.cn +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +##############################################################################*/ + +#include <fcntl.h> +#include <net/if.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +#include "buffer.h" +#include "udp-common.h" +#include "misc.h" + +struct mc_info mcinfo; + +int init_mcast_socket(struct in_addr *local_addr, + struct sockaddr_in *maddr) +{ + struct ip_mreqn mreqn; /* multicast request new */ + int ms; /* multicast socket */ + u_short msock_port; + struct sockaddr_in bind_addr; + + int msock_reuse = MCAST_REUSE; + u_char msock_loop = MCAST_LOOP; + u_char msock_ttl = MCAST_TTL; + + if ((ms = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { + crit("socket() failed, error allocating multicast socket"); + } + + // In order to let client and server on same host to use same port + if (setsockopt(ms, SOL_SOCKET, SO_REUSEADDR, + &msock_reuse, sizeof(msock_reuse)) < 0) { + crit("setsockopt() failed, can't set reuse flag"); + } + + if (setsockopt(ms, IPPROTO_IP, IP_MULTICAST_TTL, + &msock_ttl,sizeof(msock_ttl)) < 0) { + crit("setsockopt() failed, can't set ttl value"); + } + + if (setsockopt(ms, IPPROTO_IP, IP_MULTICAST_LOOP, + &msock_loop, sizeof(msock_loop)) < 0) { + crit("setsockopt() failed, can't set multicast packet looping"); + } + + /* TODO: Do we neet non-block? */ + + log(4, "Using multicast address: %s:%d", + inet_ntoa(maddr->sin_addr), ntohs(maddr->sin_port)); + + mreqn.imr_multiaddr = maddr->sin_addr; + mreqn.imr_address = *local_addr; + mreqn.imr_ifindex = 0; + + /* Interface and remote mcast address choosing */ + + /* This tell interface which has mreqn.imr_address to join + mreqn.imr_multiaddr group, it has nothing to do with socket, port, and + mreqn.imr_address. */ + if (setsockopt(ms, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &mreqn, sizeof(mreqn)) < 0) { + crit("setsockopt() failed, %s can't join multicast group", + inet_ntoa(*local_addr)); + } + + /* local address choosing */ + + /* This tell kernel to use interface which has mreqn.imr_address as device + and mreqn.imr_address as source addr when sending any multicast through + socket. */ + if (setsockopt(ms, IPPROTO_IP, IP_MULTICAST_IF, + &mreqn, sizeof(mreqn)) < 0) { + crit("setsockopt() failed to IP_MULTICAST_IF.\n"); + } + + /* Local port choosing, remote port is choosed when calling sendto()! */ + + /* This let us uses specific udp port number as source port when sending + any multicast datagrams. So ip in maddr is useless here and should be + INADDR_ANY, otherwise, bind will return Invalid argument. */ + msock_port = ntohs(maddr->sin_port); + bind_addr = make_addr(0, msock_port); + if (bind(ms, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) < 0) { + crit("bind() error, can't bind mcast port"); + } + + return ms; +} |