diff options
author | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2016-07-17 19:13:35 +0200 |
---|---|---|
committer | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2016-07-17 19:13:35 +0200 |
commit | 2b13fb969c6a05815c34295afeaffee4d60dc7fd (patch) | |
tree | b73aca948508ef4ea7a2042d4c81571b198f5aa3 | |
parent | 3f0a442799955f56b2c77aabd6bc7aa4458718b4 (diff) | |
download | eficast-2b13fb969c6a05815c34295afeaffee4d60dc7fd.tar.gz eficast-2b13fb969c6a05815c34295afeaffee4d60dc7fd.tar.bz2 eficast-2b13fb969c6a05815c34295afeaffee4d60dc7fd.zip |
Drop msock.h and socket portability.
mcastseed/leech aren't really portable nor useful on M$ Windows™.
-rw-r--r-- | mcastseed/src/Makefile.am | 4 | ||||
-rw-r--r-- | mcastseed/src/mcastleech.c | 12 | ||||
-rw-r--r-- | mcastseed/src/mcastseed.c | 14 | ||||
-rw-r--r-- | mcastseed/src/msock.c | 372 | ||||
-rw-r--r-- | mcastseed/src/msock.h | 74 | ||||
-rw-r--r-- | mcastseed/src/sockets.c | 303 | ||||
-rw-r--r-- | mcastseed/src/sockets.h | 27 |
7 files changed, 346 insertions, 460 deletions
diff --git a/mcastseed/src/Makefile.am b/mcastseed/src/Makefile.am index 7e30a9f..7af38c9 100644 --- a/mcastseed/src/Makefile.am +++ b/mcastseed/src/Makefile.am @@ -10,7 +10,7 @@ AM_CFLAGS =\ bin_PROGRAMS = mcastseed mcastleech random_speed_dd -mcastseed_SOURCES = mcastseed.c msock.c -mcastleech_SOURCES = mcastleech.c msock.c dgrambuf.c +mcastseed_SOURCES = mcastseed.c sockets.c +mcastleech_SOURCES = mcastleech.c sockets.c dgrambuf.c random_speed_dd_SOURCES = random_speed_dd.c diff --git a/mcastseed/src/mcastleech.c b/mcastseed/src/mcastleech.c index df069ac..263bac4 100644 --- a/mcastseed/src/mcastleech.c +++ b/mcastseed/src/mcastleech.c @@ -11,14 +11,14 @@ #include <unistd.h> /* close() */ #include <stdio.h> /* fprintf(), stderr */ #include <stdlib.h> /* EXIT_SUCCESS */ +#include <string.h> /* strncmp() */ #include <fcntl.h> /* fcntl() */ -#include "msock.h" +#include "sockets.h" #include "dgrambuf.h" #define MTU 1500 #define MULTICAST_RECV_BUF (MTU-20-8) #define MULTICAST_SO_RCVBUF_WANTED 425984 -/*XXX Make it dynamic, with the effective value of so_rcvbuf */ #define MAX_IOVEC (MULTICAST_SO_RCVBUF_WANTED / MULTICAST_RECV_BUF) #define DGRAM_HEADER_SIZE 8 @@ -31,8 +31,8 @@ char *mcast_ip = NULL; char *port = NULL; /* Sockets as global, used everywhere, even in die() */ -SOCKET mcast_sock = (SOCKET) -1; /* Multicast socket for receiving data */ -SOCKET ucast_sock = (SOCKET) -1; /* Unicast socket for give feedback to server */ +int mcast_sock = -1; /* Multicast socket for receiving data */ +int ucast_sock = -1; /* Unicast socket for give feedback to server */ /* Buffer used for earch recvfrom() */ char recvbuf[MULTICAST_RECV_BUF]; @@ -100,7 +100,7 @@ int main(int argc, char* argv[]) { if ( mcast_sock > 0 ) { close(mcast_sock); - mcast_sock = (SOCKET) -1; + mcast_sock = -1; } dgrambuf_free(&dgrambuf); @@ -126,7 +126,7 @@ int wait_hello_and_connect_back() { /* Setup mcast_sock */ if ( mcast_sock > 0 ) { close(mcast_sock); - mcast_sock = (SOCKET) -1; + mcast_sock = -1; } mcast_sock = mcast_recv_socket(mcast_ip, port, MULTICAST_SO_RCVBUF_WANTED); if(mcast_sock < 0) { diff --git a/mcastseed/src/mcastseed.c b/mcastseed/src/mcastseed.c index 6440fc6..796e159 100644 --- a/mcastseed/src/mcastseed.c +++ b/mcastseed/src/mcastseed.c @@ -11,7 +11,9 @@ #include <unistd.h> /* close() */ #include <stdio.h> /* fprintf(), stderr */ #include <stdlib.h> /* atoi(), EXIT_SUCCESS */ -#include "msock.h" +#include <string.h> /* strlen() */ +#include <sys/select.h> /* select(), FD_ZERO(), FD_SET() */ +#include "sockets.h" #define READ_BUF_LEN 256 #define MAX_PENDING_CONNECTIONS 256 @@ -28,13 +30,13 @@ char *port = NULL; int mcast_ttl = 0; /* Sockets as global, used everywhere, even in die() */ -SOCKET mcast_sock = (SOCKET) -1; /* Multicast socket for sending data */ -SOCKET ucast_sock = (SOCKET) -1; /* Unicast socket for havee feedback from clients */ +int mcast_sock = -1; /* Multicast socket for sending data */ +int ucast_sock = -1; /* Unicast socket for havee feedback from clients */ /* Socket related data */ struct addrinfo *mcast_addr = NULL; struct client { - SOCKET sock; + int sock; struct sockaddr addr; int state; } clients[MAX_CLIENTS]; @@ -197,7 +199,7 @@ int start_job() { ssize_t nread, nwrite; int all_ready, all_non_dead_ready; int i, res; - SOCKET client_sock; + int client_sock; const char *payload = "start"; int paylen = strlen(payload); @@ -316,7 +318,7 @@ int wait_all_finalize_job() { ssize_t nread, nwrite; int all_non_dead_done; int i, res; - SOCKET client_sock; + int client_sock; char buf[] = "end:XXXX"; int paylen = strlen(buf); diff --git a/mcastseed/src/msock.c b/mcastseed/src/msock.c deleted file mode 100644 index 191611d..0000000 --- a/mcastseed/src/msock.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - msock.c - multicast socket creation routines - - (C) 2016 Christian Beier <dontmind@sdf.org> - -*/ - -#ifndef __MINGW32__ -#include <unistd.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> - -#include "msock.h" - -SOCKET mcast_send_socket(char* multicastIP, char* multicastPort, int multicastTTL, struct addrinfo **multicastAddr) { - - SOCKET sock; - struct addrinfo hints = { 0 }; /* Hints for name lookup */ - int status; - - -#ifdef WIN32 - WSADATA trash; - if(WSAStartup(MAKEWORD(2,0),&trash)!=0) - DieWithError("Couldn't init Windows Sockets\n"); -#endif - - - /* - Resolve destination address for multicast datagrams - */ - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_NUMERICHOST; - if ((status = getaddrinfo(multicastIP, multicastPort, &hints, multicastAddr)) != 0 ) - { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); - return -1; - } - - - - /* - Create socket for sending multicast datagrams - */ - if ( (sock = socket((*multicastAddr)->ai_family, (*multicastAddr)->ai_socktype, 0)) < 0 ) { - perror("socket() failed"); - freeaddrinfo(*multicastAddr); - return -1; - } - - /* - Set TTL of multicast packet - */ - if ( setsockopt(sock, - (*multicastAddr)->ai_family == PF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, - (*multicastAddr)->ai_family == PF_INET6 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL, - (char*) &multicastTTL, sizeof(multicastTTL)) != 0 ) { - perror("setsockopt() failed"); - freeaddrinfo(*multicastAddr); - return -1; - } - - - /* - set the sending interface - */ - if((*multicastAddr)->ai_family == PF_INET) { - in_addr_t iface = INADDR_ANY; /* well, yeah, any */ - if(setsockopt (sock, - IPPROTO_IP, - IP_MULTICAST_IF, - (char*)&iface, sizeof(iface)) != 0) { - perror("interface setsockopt() sending interface"); - freeaddrinfo(*multicastAddr); - return -1; - } - - } - if((*multicastAddr)->ai_family == PF_INET6) { - unsigned int ifindex = 0; /* 0 means 'default interface'*/ - if(setsockopt (sock, - IPPROTO_IPV6, - IPV6_MULTICAST_IF, - (char*)&ifindex, sizeof(ifindex)) != 0) { - perror("interface setsockopt() sending interface"); - freeaddrinfo(*multicastAddr); - return -1; - } - - } - - - return sock; - -} - - - -SOCKET mcast_recv_socket(char* multicastIP, char* multicastPort, int multicastRecvBufSize) { - - SOCKET sock; - struct addrinfo hints = { 0 }; /* Hints for name lookup */ - struct addrinfo* localAddr = 0; /* Local address to bind to */ - struct addrinfo* multicastAddr = 0; /* Multicast Address */ - int yes=1; - int status, optval; - socklen_t optval_len; - int dfltrcvbuf; - -#ifdef WIN32 - WSADATA trash; - if(WSAStartup(MAKEWORD(2,0),&trash)!=0) - DieWithError("Couldn't init Windows Sockets\n"); -#endif - - - /* Resolve the multicast group address */ - hints.ai_family = PF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - if ((status = getaddrinfo(multicastIP, NULL, &hints, &multicastAddr)) != 0) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); - goto error; - } - - - /* - Get a local address with the same family (IPv4 or IPv6) as our multicast group - This is for receiving on a certain port. - */ - hints.ai_family = multicastAddr->ai_family; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_PASSIVE; /* Return an address we can bind to */ - if ( getaddrinfo(NULL, multicastPort, &hints, &localAddr) != 0 ) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); - goto error; - } - - - /* Create socket for receiving datagrams */ - if ( (sock = socket(localAddr->ai_family, localAddr->ai_socktype, 0)) < 0 ) { - perror("socket() failed"); - goto error; - } - - - - /* - * Enable SO_REUSEADDR to allow multiple instances of this - * application to receive copies of the multicast datagrams. - */ - if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(int)) == -1) { - perror("setsockopt"); - goto error; - } - - /* Bind the local address to the multicast port */ - if ( bind(sock, localAddr->ai_addr, localAddr->ai_addrlen) != 0 ) { - perror("bind() failed"); - goto error; - } - - /* get/set socket receive buffer */ - optval=0; - optval_len = sizeof(optval); - if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) !=0) { - perror("getsockopt"); - goto error; - } - dfltrcvbuf = optval; - optval = multicastRecvBufSize; - if(setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char*)&optval,sizeof(optval)) != 0) { - perror("setsockopt"); - goto error; - } - if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) != 0) { - perror("getsockopt"); - goto error; - } - fprintf(stderr, "tried to set socket receive buffer from %d to %d, got %d\n", - dfltrcvbuf, multicastRecvBufSize, optval); - - - - - /* Join the multicast group. We do this seperately depending on whether we - * are using IPv4 or IPv6. - */ - if ( multicastAddr->ai_family == PF_INET && - multicastAddr->ai_addrlen == sizeof(struct sockaddr_in) ) /* IPv4 */ - { - struct ip_mreq multicastRequest; /* Multicast address join structure */ - - /* Specify the multicast group */ - memcpy(&multicastRequest.imr_multiaddr, - &((struct sockaddr_in*)(multicastAddr->ai_addr))->sin_addr, - sizeof(multicastRequest.imr_multiaddr)); - - /* Accept multicast from any interface */ - multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); - - /* Join the multicast address */ - if ( setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 ) { - perror("setsockopt() failed"); - goto error; - } - } - else if ( multicastAddr->ai_family == PF_INET6 && - multicastAddr->ai_addrlen == sizeof(struct sockaddr_in6) ) /* IPv6 */ - { - struct ipv6_mreq multicastRequest; /* Multicast address join structure */ - - /* Specify the multicast group */ - memcpy(&multicastRequest.ipv6mr_multiaddr, - &((struct sockaddr_in6*)(multicastAddr->ai_addr))->sin6_addr, - sizeof(multicastRequest.ipv6mr_multiaddr)); - - /* Accept multicast from any interface */ - multicastRequest.ipv6mr_interface = 0; - - /* Join the multicast address */ - if ( setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 ) { - perror("setsockopt() failed"); - goto error; - } - } - else { - perror("Neither IPv4 or IPv6"); - goto error; - } - - - - if(localAddr) - freeaddrinfo(localAddr); - if(multicastAddr) - freeaddrinfo(multicastAddr); - - return sock; - - error: - if(localAddr) - freeaddrinfo(localAddr); - if(multicastAddr) - freeaddrinfo(multicastAddr); - - return -1; -} - -SOCKET ucast_client_socket(char* serverIP, char* serverPort) { - - SOCKET sock; - struct addrinfo *serverAddr; - struct addrinfo hints = { 0 }; /* Hints for name lookup */ - int status; - - -#ifdef WIN32 - WSADATA trash; - if(WSAStartup(MAKEWORD(2,0),&trash)!=0) - DieWithError("Couldn't init Windows Sockets\n"); -#endif - - - /* - Resolve destination address - */ - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_NUMERICHOST; - if ((status = getaddrinfo(serverIP, serverPort, &hints, &serverAddr)) != 0 ) - { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); - return -1; - } - - /* - Create socket - */ - if ( (sock = socket(serverAddr->ai_family, serverAddr->ai_socktype, 0)) < 0 ) { - perror("socket() failed"); - freeaddrinfo(serverAddr); - return -1; - } - - /* - Connect it to the remote server - */ - if ( connect(sock, serverAddr->ai_addr, serverAddr->ai_addrlen) < 0 ) { - perror("connect() failed"); - close(sock); - freeaddrinfo(serverAddr); - return -1; - } - - freeaddrinfo(serverAddr); - return sock; -} - -SOCKET ucast_server_socket(char* serverPort, int maxPendingConnections) { - - SOCKET sock; - struct addrinfo *serverAddr; - struct addrinfo hints = { 0 }; /* Hints for name lookup */ - int status; - - -#ifdef WIN32 - WSADATA trash; - if(WSAStartup(MAKEWORD(2,0),&trash)!=0) - DieWithError("Couldn't init Windows Sockets\n"); -#endif - - - /* - Prepare an addrinfo struct for a local socket - */ - hints.ai_family = PF_INET6; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - if ((status = getaddrinfo(NULL, serverPort, &hints, &serverAddr)) != 0 ) - { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); - return -1; - } - /* - Create socket - */ - if ( (sock = socket(serverAddr->ai_family, serverAddr->ai_socktype, serverAddr->ai_protocol)) < 0 ) { - perror("socket() failed"); - freeaddrinfo(serverAddr); - return -1; - } - - /* - Accepts also IPv4 traffic if the socket is INET6 - */ - if(serverAddr->ai_family == PF_INET6) { - unsigned int no = 0; - if(setsockopt (sock, - IPPROTO_IPV6, - IPV6_V6ONLY, - (char*)&no, sizeof(no)) != 0) { - perror("setsockopt() !IPV6_V6ONLY failed"); - freeaddrinfo(serverAddr); - return -1; - } - } - - /* - Bind socket to local address/port - */ - if ( bind(sock, serverAddr->ai_addr, serverAddr->ai_addrlen) < 0 ) { - perror("bind() failed"); - close(sock); - freeaddrinfo(serverAddr); - return -1; - } - - freeaddrinfo(serverAddr); - /* - Start listening incoming connections - */ - if ( listen(sock, maxPendingConnections) < 0 ) { - perror("listen() failed"); - close(sock); - } - - return sock; -} diff --git a/mcastseed/src/msock.h b/mcastseed/src/msock.h deleted file mode 100644 index 07e1fad..0000000 --- a/mcastseed/src/msock.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - msock.h - multicast socket creation routines - - (C) 2016 Christian Beier <dontmind@sdf.org> - -*/ - - -#ifndef MSOCK_H -#define MSOCK_H - -/* this is for windows compat */ -#define SOCKET int - -#ifdef __MINGW32__ -#undef SOCKET -#undef socklen_t -#define WINVER 0x0501 -#include <ws2tcpip.h> -#define EWOULDBLOCK WSAEWOULDBLOCK -#define close closesocket -#define socklen_t int -typedef unsigned int in_addr_t; -#else -#include <sys/socket.h> -#include <netinet/in.h> -#include <sys/un.h> -#include <netinet/tcp.h> -#include <arpa/inet.h> -#include <netdb.h> -#endif - -/* Define IPV6_ADD_MEMBERSHIP for FreeBSD and Mac OS X */ -#ifndef IPV6_ADD_MEMBERSHIP -#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#endif - - - -/** - Creates a socket suitable for sending multicast datagrams via sendto(). - - On success, a socket is returned and multicastAddr set with the right info for sendto() calls. - On error, -1 is returned. -*/ -SOCKET mcast_send_socket(char* multicastIP, char* multicastPort, int multicastTTL, struct addrinfo **multicastAddr); - -/** - Creates a socket suitable for receiving multicast datagrams via recvfrom(). Also sets socket recv buffer. - - On success, returns socket. - On fail, returns -1. - */ -SOCKET mcast_recv_socket(char* multicastIP, char* multicastPort, int multicastRecvBufSize); - -/** - Creates a TCP socket that connects to serverIP:serverPort. - Meant to give feedback to a mcast sender. - - On success, returns socket. - On error, -1 is returned. - */ -SOCKET ucast_client_socket(char* serverIP, char* serverPort); - -/** - Creates a TCP socket that binds locally serverPort. - Meant to receive feedback to a mcast sender. - - On success, returns socket. - On error, -1 is returned. - */ -SOCKET ucast_server_socket(char* serverPort, int maxPendingConnections); - -#endif diff --git a/mcastseed/src/sockets.c b/mcastseed/src/sockets.c new file mode 100644 index 0000000..85abb1f --- /dev/null +++ b/mcastseed/src/sockets.c @@ -0,0 +1,303 @@ +/* + * Copyright 2016 by Ludovic Pouzenc <ludovic@pouzenc.fr> + * + * Greatly inspired from msock.h written by Christian Beier <dontmind@sdf.org> + */ +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "sockets.h" + +int mcast_recv_socket(char *mcast_ip, char *port, int wanted_so_rcvbuf) { + + int sock; + struct addrinfo hints = { 0 }; /* Hints for name lookup */ + struct addrinfo *ai_local = NULL; /* Local address to bind to */ + struct addrinfo *mcast_ai = NULL; /* Multicast Address */ + int yes=1; + int status, optval; + socklen_t optval_len; + int dfltrcvbuf; + + /* Resolve the multicast group address */ + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST; + if ((status = getaddrinfo(mcast_ip, NULL, &hints, &mcast_ai)) != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + goto error; + } + + /* + * Get a local address with the same family (IPv4 or IPv6) as our multicast group + * This is for receiving on a certain port. + */ + hints.ai_family = mcast_ai->ai_family; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; /* Return an address we can bind to */ + if ( getaddrinfo(NULL, port, &hints, &ai_local) != 0 ) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + goto error; + } + + /* Create socket for receiving datagrams */ + if ( (sock = socket(ai_local->ai_family, ai_local->ai_socktype, 0)) < 0 ) { + perror("socket() failed"); + goto error; + } + + /* + * Enable SO_REUSEADDR to allow multiple instances of this + * application to receive copies of the multicast datagrams. + */ + if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(int)) == -1) { + perror("setsockopt"); + goto error; + } + + /* Bind the local address to the multicast port */ + if ( bind(sock, ai_local->ai_addr, ai_local->ai_addrlen) != 0 ) { + perror("bind() failed"); + goto error; + } + + /* get/set socket receive buffer */ + optval=0; + optval_len = sizeof(optval); + if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) !=0) { + perror("getsockopt"); + goto error; + } + dfltrcvbuf = optval; + optval = wanted_so_rcvbuf; + if(setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char*)&optval,sizeof(optval)) != 0) { + perror("setsockopt"); + goto error; + } + if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) != 0) { + perror("getsockopt"); + goto error; + } + fprintf(stderr, "tried to set socket receive buffer from %d to %d, got %d\n", + dfltrcvbuf, wanted_so_rcvbuf, optval); + + + /* Join the multicast group. We do this seperately depending on whether we + * are using IPv4 or IPv6. + */ + if ( mcast_ai->ai_family == PF_INET && + mcast_ai->ai_addrlen == sizeof(struct sockaddr_in) ) /* IPv4 */ + { + struct ip_mreq multicastRequest; /* Multicast address join structure */ + + /* Specify the multicast group */ + memcpy(&multicastRequest.imr_multiaddr, + &((struct sockaddr_in*)(mcast_ai->ai_addr))->sin_addr, + sizeof(multicastRequest.imr_multiaddr)); + + /* Accept multicast from any interface */ + multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); + + /* Join the multicast address */ + if ( setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 ) { + perror("setsockopt() failed"); + goto error; + } + } + else if ( mcast_ai->ai_family == PF_INET6 && + mcast_ai->ai_addrlen == sizeof(struct sockaddr_in6) ) /* IPv6 */ + { + struct ipv6_mreq multicastRequest; /* Multicast address join structure */ + + /* Specify the multicast group */ + memcpy(&multicastRequest.ipv6mr_multiaddr, + &((struct sockaddr_in6*)(mcast_ai->ai_addr))->sin6_addr, + sizeof(multicastRequest.ipv6mr_multiaddr)); + + /* Accept multicast from any interface */ + multicastRequest.ipv6mr_interface = 0; + + /* Join the multicast address */ + if ( setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 ) { + perror("setsockopt() failed"); + goto error; + } + } + else { + perror("Neither IPv4 or IPv6"); + goto error; + } + + + if(ai_local) + freeaddrinfo(ai_local); + if(mcast_ai) + freeaddrinfo(mcast_ai); + + return sock; + +error: + if(ai_local) + freeaddrinfo(ai_local); + if(mcast_ai) + freeaddrinfo(mcast_ai); + + return -1; +} + + +int mcast_send_socket(char* mcast_ip, char* port, int multicastTTL, struct addrinfo **mcast_ai) { + + int sock; + struct addrinfo hints = { 0 }; /* Hints for name lookup */ + int status; + + + /* Resolve destination address for multicast datagrams */ + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_NUMERICHOST; + if ((status = getaddrinfo(mcast_ip, port, &hints, mcast_ai)) != 0 ) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + return -1; + } + + /* Create socket for sending multicast datagrams */ + if ( (sock = socket((*mcast_ai)->ai_family, (*mcast_ai)->ai_socktype, 0)) < 0 ) { + perror("socket() failed"); + freeaddrinfo(*mcast_ai); + return -1; + } + + /* Set TTL of multicast packet */ + if ( setsockopt(sock, + (*mcast_ai)->ai_family == PF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, + (*mcast_ai)->ai_family == PF_INET6 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL, + (char*) &multicastTTL, sizeof(multicastTTL)) != 0 ) { + perror("setsockopt() failed"); + freeaddrinfo(*mcast_ai); + return -1; + } + + /* set the sending interface */ + if((*mcast_ai)->ai_family == PF_INET) { + in_addr_t iface = INADDR_ANY; /* well, yeah, any */ + if(setsockopt (sock, + IPPROTO_IP, + IP_MULTICAST_IF, + (char*)&iface, sizeof(iface)) != 0) { + perror("interface setsockopt() sending interface"); + freeaddrinfo(*mcast_ai); + return -1; + } + + } + if((*mcast_ai)->ai_family == PF_INET6) { + unsigned int ifindex = 0; /* 0 means 'default interface'*/ + if(setsockopt (sock, + IPPROTO_IPV6, + IPV6_MULTICAST_IF, + (char*)&ifindex, sizeof(ifindex)) != 0) { + perror("interface setsockopt() sending interface"); + freeaddrinfo(*mcast_ai); + return -1; + } + + } + + return sock; +} + + +int ucast_server_socket(char* port, int max_pending_conn) { + + int sock; + struct addrinfo *serverAddr; + struct addrinfo hints = { 0 }; /* Hints for name lookup */ + int status; + + + /* Prepare an addrinfo struct for a local socket */ + hints.ai_family = PF_INET6; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + if ((status = getaddrinfo(NULL, port, &hints, &serverAddr)) != 0 ) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + return -1; + } + /* Create socket */ + if ( (sock = socket(serverAddr->ai_family, serverAddr->ai_socktype, serverAddr->ai_protocol)) < 0 ) { + perror("socket() failed"); + freeaddrinfo(serverAddr); + return -1; + } + + /* Accepts also IPv4 traffic if the socket is INET6 */ + if(serverAddr->ai_family == PF_INET6) { + unsigned int no = 0; + if(setsockopt (sock, + IPPROTO_IPV6, + IPV6_V6ONLY, + (char*)&no, sizeof(no)) != 0) { + perror("setsockopt() !IPV6_V6ONLY failed"); + freeaddrinfo(serverAddr); + return -1; + } + } + + /* Bind socket to local address/port */ + if ( bind(sock, serverAddr->ai_addr, serverAddr->ai_addrlen) < 0 ) { + perror("bind() failed"); + close(sock); + freeaddrinfo(serverAddr); + return -1; + } + + freeaddrinfo(serverAddr); + + /* Start listening incoming connections */ + if ( listen(sock, max_pending_conn) < 0 ) { + perror("listen() failed"); + close(sock); + } + + return sock; +} + +int ucast_client_socket(char* server_ip, char* port) { + + int sock; + struct addrinfo *serverAddr; + struct addrinfo hints = { 0 }; /* Hints for name lookup */ + int status; + + /* Resolve destination address */ + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST; + if ((status = getaddrinfo(server_ip, port, &hints, &serverAddr)) != 0 ) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + return -1; + } + + /* Create socket */ + if ( (sock = socket(serverAddr->ai_family, serverAddr->ai_socktype, 0)) < 0 ) { + perror("socket() failed"); + freeaddrinfo(serverAddr); + return -1; + } + + /* Connect it to the remote server */ + if ( connect(sock, serverAddr->ai_addr, serverAddr->ai_addrlen) < 0 ) { + perror("connect() failed"); + close(sock); + freeaddrinfo(serverAddr); + return -1; + } + + freeaddrinfo(serverAddr); + return sock; +} + diff --git a/mcastseed/src/sockets.h b/mcastseed/src/sockets.h new file mode 100644 index 0000000..86f7c5b --- /dev/null +++ b/mcastseed/src/sockets.h @@ -0,0 +1,27 @@ +/* + * Copyright 2016 by Ludovic Pouzenc <ludovic@pouzenc.fr> + * + * Greatly inspired from msock.h written by Christian Beier <dontmind@sdf.org> + */ + +#ifndef SOCKETS_H +#define SOCKETS_H + +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> +/* +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/un.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +*/ +int mcast_recv_socket(char *mcast_ip, char *port, int wanted_so_rcvbuf); +int mcast_send_socket(char *mcast_ip, char *port, int mcast_ttl, struct addrinfo **mcast_ai); + +int ucast_server_socket(char *port, int max_pending_conn); +int ucast_client_socket(char *server_ip, char *port); + +#endif /*SOCKETS_H*/ |