0
1
mirror of https://github.com/radio95-rnt/rds95.git synced 2026-02-26 20:33:53 +01:00

udp server

This commit is contained in:
2025-07-12 17:54:52 +02:00
parent e1218542d2
commit eff6a1ff5e
5 changed files with 157 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
{
"port": 13452,
"time": 1751819046475,
"time": 1752334981843,
"version": "0.0.3"
}

2
inih

Submodule inih updated: 57188e8acd...498f34b786

View File

@@ -9,6 +9,7 @@
#include "rds.h"
#include "modulator.h"
#include "control_pipe.h"
#include "udp_server.h"
#include "lib.h"
#include "ascii_cmd.h"
@@ -37,6 +38,16 @@ static void *control_pipe_worker(void* modulator) {
pthread_exit(NULL);
}
static void *udp_server_worker() {
while (!stop_rds) {
poll_udp_server();
msleep(READ_TIMEOUT_MS);
}
close_udp_server();
pthread_exit(NULL);
}
static inline void show_help(char *name) {
printf(
"\n"
@@ -52,27 +63,32 @@ static inline void show_help(char *name) {
typedef struct
{
char control_pipe[51];
uint16_t udp_port;
char rds_device_name[32];
uint8_t num_streams;
} RDS95_Config;
static int config_handler(void* user, const char* section, const char* name, const char* value) {
RDS95_Config* config = (RDS95_Config*)user;
RDS95_Config* config = (RDS95_Config*)user;
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
if(MATCH("rds95", "control_pipe")) {
strncpy(config->control_pipe, value, 49);
config->control_pipe[50] = '\0';
} else if(MATCH("devices", "rds95")) {
strncpy(config->rds_device_name, value, 30);
config->rds_device_name[31] = '\0';
} else if(MATCH("rds95", "streams")) {
config->num_streams = atoi(value);
if(config->num_streams > MAX_STREAMS || config->num_streams == 0) return 1;
} else {
return 0;
}
return 1;
#define MATCH(s, n) (strcmp(section, s) == 0 && strcmp(name, n) == 0)
if (MATCH("rds95", "control_pipe")) {
strncpy(config->control_pipe, value, sizeof(config->control_pipe) - 1);
config->control_pipe[sizeof(config->control_pipe) - 1] = '\0';
} else if (MATCH("rds95", "udp_port")) {
config->udp_port = (uint16_t)atoi(value);
} else if (MATCH("devices", "rds95")) {
strncpy(config->rds_device_name, value, sizeof(config->rds_device_name) - 1);
config->rds_device_name[sizeof(config->rds_device_name) - 1] = '\0';
} else if (MATCH("rds95", "streams")) {
int streams = atoi(value);
if (streams > MAX_STREAMS || streams == 0) return 0;
config->num_streams = (uint8_t)streams;
} else {
return 0; // Unknown config key
}
return 1;
}
int main(int argc, char **argv) {
@@ -81,6 +97,7 @@ int main(int argc, char **argv) {
char config_path[64] = DEFAULT_CONFIG_PATH;
RDS95_Config config = {
.control_pipe = "\0",
.udp_port = 0,
.rds_device_name = RDS_DEVICE,
.num_streams = DEFAULT_STREAMS
};
@@ -91,6 +108,7 @@ int main(int argc, char **argv) {
pthread_attr_t attr;
pthread_t control_pipe_thread;
pthread_t udp_server_thread;
const char *short_opt = "c:h";
@@ -174,6 +192,21 @@ int main(int argc, char **argv) {
}
}
if(config.udp_port) {
if(open_udp_server(config.udp_port, &rdsModulator) == 0) {
fprintf(stderr, "Reading control commands on UDP:%d.\n", config.udp_port);
int r = pthread_create(&udp_server_thread, &attr, udp_server_worker, NULL);
if (r < 0) {
fprintf(stderr, "Could not create UDP server thread.\n");
config.udp_port = 0;
goto exit;
} else fprintf(stderr, "Created UDP server thread.\n");
} else {
fprintf(stderr, "Failed to open UDP server\n");
config.udp_port = 0;
}
}
int pulse_error;
// Dynamically allocate buffer based on stream count
@@ -202,6 +235,11 @@ exit:
pthread_join(control_pipe_thread, NULL);
}
if(config.udp_port) {
fprintf(stderr, "Waiting for UDP thread to shut down.\n");
pthread_join(udp_server_thread, NULL);
}
cleanup_rds_modulator(&rdsModulator); // Clean up dynamically allocated memory
pthread_attr_destroy(&attr);
if (rds_device != NULL) pa_simple_free(rds_device);

83
src/udp_server.c Normal file
View File

@@ -0,0 +1,83 @@
#include "udp_server.h"
#define BUF_SIZE 512
#define UDP_READ_TIMEOUT_MS 500
static int sockfd = -1;
static struct pollfd poller;
static struct sockaddr_in client_addr;
static socklen_t client_len = sizeof(client_addr);
static RDSModulator* mod = NULL; // Store modulator pointer globally or pass it somehow
int open_udp_server(int port, RDSModulator* rds_mod) {
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) return -1;
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
close(sockfd);
sockfd = -1;
return -1;
}
poller.fd = sockfd;
poller.events = POLLIN;
mod = rds_mod; // Save mod pointer
return 0;
}
void poll_udp_server() {
static char buf[BUF_SIZE];
static char cmd_buf[BUF_SIZE];
static char cmd_output[BUF_SIZE]; // Buffer to collect output from process_ascii_cmd
ssize_t bytes_read;
if (poll(&poller, 1, UDP_READ_TIMEOUT_MS) <= 0) return;
if (!(poller.revents & POLLIN)) return;
memset(buf, 0, BUF_SIZE);
client_len = sizeof(client_addr);
bytes_read = recvfrom(sockfd, buf, BUF_SIZE - 1, 0,
(struct sockaddr *)&client_addr, &client_len);
if (bytes_read <= 0) return;
buf[bytes_read] = '\0';
char *token = strtok(buf, "\r\n");
while (token != NULL) {
size_t len = strlen(token);
if (len > 0 && len < BUF_SIZE) {
memset(cmd_buf, 0, BUF_SIZE);
strncpy(cmd_buf, token, BUF_SIZE - 1);
memset(cmd_output, 0, BUF_SIZE);
// Pass cmd_output buffer to collect output from the command processor
process_ascii_cmd(mod, cmd_buf, cmd_output);
// Send cmd_output back to client (even if empty, send it)
size_t out_len = strlen(cmd_output);
if (out_len > 0) {
ssize_t sent = sendto(sockfd, cmd_output, out_len, 0,
(struct sockaddr *)&client_addr, client_len);
if (sent == -1) {
perror("sendto");
}
}
}
token = strtok(NULL, "\r\n");
}
}
void close_udp_server() {
if (sockfd >= 0) close(sockfd);
sockfd = -1;
}

19
src/udp_server.h Normal file
View File

@@ -0,0 +1,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include "modulator.h"
#include "ascii_cmd.h"
int open_udp_server(int port, RDSModulator *rds_mod);
void poll_udp_server();
void close_udp_server();