From cf93d280af47aea1bf8bdafa30eabb2c2de005b8 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sat, 10 Aug 2019 15:30:48 +0200 Subject: Implement stream client connections in libmmbackend (Fixes #19) --- backends/artnet.c | 2 +- backends/libmmbackend.c | 62 +++++++++++++++++++++++++++++++++++-------------- backends/libmmbackend.h | 22 ++++++++++++++---- backends/lua.md | 2 +- backends/osc.c | 2 +- backends/sacn.c | 2 +- 6 files changed, 67 insertions(+), 25 deletions(-) diff --git a/backends/artnet.c b/backends/artnet.c index a6df4ab..7f3f08c 100644 --- a/backends/artnet.c +++ b/backends/artnet.c @@ -19,7 +19,7 @@ static int artnet_listener(char* host, char* port){ return -1; } - fd = mmbackend_socket(host, port, SOCK_DGRAM, 1); + fd = mmbackend_socket(host, port, SOCK_DGRAM, 1, 1); if(fd < 0){ return -1; } diff --git a/backends/libmmbackend.c b/backends/libmmbackend.c index b27ebc5..2fd3b8b 100644 --- a/backends/libmmbackend.c +++ b/backends/libmmbackend.c @@ -52,7 +52,7 @@ int mmbackend_parse_sockaddr(char* host, char* port, struct sockaddr_storage* ad return 0; } -int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener){ +int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uint8_t mcast){ int fd = -1, status, yes = 1; struct addrinfo hints = { .ai_family = AF_UNSPEC, @@ -80,20 +80,31 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener){ fprintf(stderr, "Failed to enable SO_REUSEADDR on socket\n"); } - yes = 1; - if(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void*)&yes, sizeof(yes)) < 0){ - fprintf(stderr, "Failed to enable SO_BROADCAST on socket\n"); - } + if(mcast){ + yes = 1; + if(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void*)&yes, sizeof(yes)) < 0){ + fprintf(stderr, "Failed to enable SO_BROADCAST on socket\n"); + } - yes = 0; - if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&yes, sizeof(yes)) < 0){ - fprintf(stderr, "Failed to disable IP_MULTICAST_LOOP on socket: %s\n", strerror(errno)); + yes = 0; + if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&yes, sizeof(yes)) < 0){ + fprintf(stderr, "Failed to disable IP_MULTICAST_LOOP on socket: %s\n", strerror(errno)); + } } - status = bind(fd, addr_it->ai_addr, addr_it->ai_addrlen); - if(status < 0){ - close(fd); - continue; + if(listener){ + status = bind(fd, addr_it->ai_addr, addr_it->ai_addrlen); + if(status < 0){ + close(fd); + continue; + } + } + else{ + status = connect(fd, addr_it->ai_addr, addr_it->ai_addrlen); + if(status < 0){ + close(fd); + continue; + } } break; @@ -107,11 +118,11 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener){ //set nonblocking #ifdef _WIN32 - u_long mode = 1; - if(ioctlsocket(fd, FIONBIO, &mode) != NO_ERROR){ - closesocket(fd); - return 1; - } + u_long mode = 1; + if(ioctlsocket(fd, FIONBIO, &mode) != NO_ERROR){ + closesocket(fd); + return 1; + } #else int flags = fcntl(fd, F_GETFL, 0); if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0){ @@ -123,3 +134,20 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener){ return fd; } + +int mmbackend_send(int fd, uint8_t* data, size_t length){ + ssize_t total = 0, sent; + while(total < length){ + sent = send(fd, data + total, length - total, 0); + if(sent < 0){ + fprintf(stderr, "Failed to send: %s\n", strerror(errno)); + return 1; + } + total += sent; + } + return 0; +} + +int mmbackend_send_str(int fd, char* data){ + return mmbackend_send(fd, (uint8_t*) data, strlen(data)); +} diff --git a/backends/libmmbackend.h b/backends/libmmbackend.h index 77cad6a..31c4b96 100644 --- a/backends/libmmbackend.h +++ b/backends/libmmbackend.h @@ -16,7 +16,8 @@ #include #include "../portability.h" -/* Parse spec as host specification in the form +/* + * Parse spec as host specification in the form * host port * into its constituent parts. * Returns offsets into the original string and modifies it. @@ -25,13 +26,26 @@ */ void mmbackend_parse_hostspec(char* spec, char** host, char** port); -/* Parse a given host / port combination into a sockaddr_storage +/* + * Parse a given host / port combination into a sockaddr_storage * suitable for usage with connect / sendto * Returns 0 on success */ int mmbackend_parse_sockaddr(char* host, char* port, struct sockaddr_storage* addr, socklen_t* len); -/* Create a socket of given type and mode for a bind / connect host. +/* + * Create a socket of given type and mode for a bind / connect host. * Returns -1 on failure, a valid file descriptor for the socket on success. */ -int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener); +int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uint8_t mcast); + +/* + * Send arbitrary data over multiple writes if necessary + * Returns 1 on failure, 0 on success. + */ +int mmbackend_send(int fd, uint8_t* data, size_t length); + +/* + * Wraps mmbackend_send for cstrings + */ +int mmbackend_send_str(int fd, char* data); diff --git a/backends/lua.md b/backends/lua.md index 1c67477..6ad5c2a 100644 --- a/backends/lua.md +++ b/backends/lua.md @@ -37,7 +37,7 @@ Input values range between 0.0 and 1.0, output values are clamped to the same ra #### Global configuration -The backend does not take any global configuration. +The `lua` backend does not take any global configuration. #### Instance configuration diff --git a/backends/osc.c b/backends/osc.c index 03e431f..77bbde4 100644 --- a/backends/osc.c +++ b/backends/osc.c @@ -525,7 +525,7 @@ static int osc_configure_instance(instance* inst, char* option, char* value){ return 1; } - data->fd = mmbackend_socket(host, port, SOCK_DGRAM, 1); + data->fd = mmbackend_socket(host, port, SOCK_DGRAM, 1, 1); if(data->fd < 0){ fprintf(stderr, "Failed to bind for instance %s\n", inst->name); return 1; diff --git a/backends/sacn.c b/backends/sacn.c index 6f7d1a5..2f418e5 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -60,7 +60,7 @@ static int sacn_listener(char* host, char* port, uint8_t fd_flags){ return -1; } - fd = mmbackend_socket(host, port, SOCK_DGRAM, 1); + fd = mmbackend_socket(host, port, SOCK_DGRAM, 1, 1); if(fd < 0){ return -1; } -- cgit v1.2.3