121 lines
2.6 KiB
C
121 lines
2.6 KiB
C
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <poll.h>
|
|
|
|
#include "../include/logger.h"
|
|
#include "../include/fader.h"
|
|
|
|
#include "../include/udpproto.h"
|
|
|
|
#define SET_COLOUR 0
|
|
#define FADE_COLOUR 1
|
|
#define ADD_COLOUR 2
|
|
#define SET_FADESTEP 3
|
|
|
|
int sock;
|
|
|
|
int udpproto_init(uint16_t port)
|
|
{
|
|
struct sockaddr_in listen_addr;
|
|
|
|
// initialize UDP server socket
|
|
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
if(sock == -1) {
|
|
LOG(LVL_ERR, "udpproto: Could not initialize UDP socket: %s.", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
memset(&listen_addr, 0, sizeof(listen_addr));
|
|
listen_addr.sin_family = AF_INET;
|
|
listen_addr.sin_port = htons(port);
|
|
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
if(bind(sock, (struct sockaddr*)&listen_addr, sizeof(listen_addr)) == -1) {
|
|
LOG(LVL_ERR, "udpproto: Could not bind socket to port %i: %s.", port, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int udpproto_process(void)
|
|
{
|
|
socklen_t remote_addr_len;
|
|
struct sockaddr remote_addr;
|
|
uint8_t pkgbuf[65536];
|
|
ssize_t rcvbytes, offset = 0;
|
|
|
|
uint8_t r, g, b, action, module;
|
|
int fds_ready;
|
|
|
|
// check if there is data to be read (to prevent blocking)
|
|
struct pollfd pfd = {
|
|
.fd = sock,
|
|
.events = POLLIN,
|
|
.revents = 0
|
|
};
|
|
|
|
fds_ready = poll(&pfd, 1, 0);
|
|
if(fds_ready == -1) {
|
|
LOG(LVL_ERR, "udpproto: poll() failed: %s.", strerror(errno));
|
|
return -1;
|
|
} else if(fds_ready == 0) {
|
|
// there's nothing to be read
|
|
return 0;
|
|
}
|
|
|
|
// receive the data
|
|
remote_addr_len = sizeof(remote_addr);
|
|
rcvbytes = recvfrom(sock, pkgbuf, 65536, 0, (struct sockaddr*)&remote_addr, &remote_addr_len);
|
|
if(rcvbytes == -1) {
|
|
LOG(LVL_ERR, "udpproto: recvfrom() failed: %s.", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
pkgbuf[rcvbytes] = 0;
|
|
|
|
// parse commands from packet
|
|
offset = 0;
|
|
while(offset <= rcvbytes - 4) {
|
|
action = pkgbuf[offset + 0];
|
|
module = pkgbuf[offset + 1];
|
|
r = pkgbuf[offset + 2];
|
|
g = pkgbuf[offset + 3];
|
|
b = pkgbuf[offset + 4];
|
|
offset += 5;
|
|
|
|
switch(action) {
|
|
case SET_COLOUR:
|
|
fader_set_colour(module, r, g, b);
|
|
break;
|
|
|
|
case FADE_COLOUR:
|
|
fader_fade_colour(module, r, g, b);
|
|
break;
|
|
|
|
case ADD_COLOUR:
|
|
fader_add_colour(module, r, g, b);
|
|
break;
|
|
|
|
case SET_FADESTEP:
|
|
fader_set_fadestep(r); // red channel contains the fadestep in this case
|
|
break;
|
|
|
|
default:
|
|
LOG(LVL_DEBUG, "udpproto: Action %u not implemented yet.", action);
|
|
}
|
|
}
|
|
|
|
return rcvbytes / 5; // number of commands in packet
|
|
}
|
|
|
|
void udpproto_shutdown(void)
|
|
{
|
|
close(sock);
|
|
}
|