mirror of
https://github.com/radio95-rnt/rds95.git
synced 2026-07-29 16:29:17 +02:00
udp server
This commit is contained in:
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"port": 13452,
|
"port": 13452,
|
||||||
"time": 1751819046475,
|
"time": 1752334981843,
|
||||||
"version": "0.0.3"
|
"version": "0.0.3"
|
||||||
}
|
}
|
||||||
+1
-1
Submodule inih updated: 57188e8acd...498f34b786
+53
-15
@@ -9,6 +9,7 @@
|
|||||||
#include "rds.h"
|
#include "rds.h"
|
||||||
#include "modulator.h"
|
#include "modulator.h"
|
||||||
#include "control_pipe.h"
|
#include "control_pipe.h"
|
||||||
|
#include "udp_server.h"
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "ascii_cmd.h"
|
#include "ascii_cmd.h"
|
||||||
|
|
||||||
@@ -37,6 +38,16 @@ static void *control_pipe_worker(void* modulator) {
|
|||||||
pthread_exit(NULL);
|
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) {
|
static inline void show_help(char *name) {
|
||||||
printf(
|
printf(
|
||||||
"\n"
|
"\n"
|
||||||
@@ -52,27 +63,32 @@ static inline void show_help(char *name) {
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char control_pipe[51];
|
char control_pipe[51];
|
||||||
|
uint16_t udp_port;
|
||||||
char rds_device_name[32];
|
char rds_device_name[32];
|
||||||
uint8_t num_streams;
|
uint8_t num_streams;
|
||||||
} RDS95_Config;
|
} RDS95_Config;
|
||||||
|
|
||||||
static int config_handler(void* user, const char* section, const char* name, const char* value) {
|
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
|
#define MATCH(s, n) (strcmp(section, s) == 0 && strcmp(name, n) == 0)
|
||||||
if(MATCH("rds95", "control_pipe")) {
|
|
||||||
strncpy(config->control_pipe, value, 49);
|
if (MATCH("rds95", "control_pipe")) {
|
||||||
config->control_pipe[50] = '\0';
|
strncpy(config->control_pipe, value, sizeof(config->control_pipe) - 1);
|
||||||
} else if(MATCH("devices", "rds95")) {
|
config->control_pipe[sizeof(config->control_pipe) - 1] = '\0';
|
||||||
strncpy(config->rds_device_name, value, 30);
|
} else if (MATCH("rds95", "udp_port")) {
|
||||||
config->rds_device_name[31] = '\0';
|
config->udp_port = (uint16_t)atoi(value);
|
||||||
} else if(MATCH("rds95", "streams")) {
|
} else if (MATCH("devices", "rds95")) {
|
||||||
config->num_streams = atoi(value);
|
strncpy(config->rds_device_name, value, sizeof(config->rds_device_name) - 1);
|
||||||
if(config->num_streams > MAX_STREAMS || config->num_streams == 0) return 1;
|
config->rds_device_name[sizeof(config->rds_device_name) - 1] = '\0';
|
||||||
} else {
|
} else if (MATCH("rds95", "streams")) {
|
||||||
return 0;
|
int streams = atoi(value);
|
||||||
}
|
if (streams > MAX_STREAMS || streams == 0) return 0;
|
||||||
return 1;
|
config->num_streams = (uint8_t)streams;
|
||||||
|
} else {
|
||||||
|
return 0; // Unknown config key
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
@@ -81,6 +97,7 @@ int main(int argc, char **argv) {
|
|||||||
char config_path[64] = DEFAULT_CONFIG_PATH;
|
char config_path[64] = DEFAULT_CONFIG_PATH;
|
||||||
RDS95_Config config = {
|
RDS95_Config config = {
|
||||||
.control_pipe = "\0",
|
.control_pipe = "\0",
|
||||||
|
.udp_port = 0,
|
||||||
.rds_device_name = RDS_DEVICE,
|
.rds_device_name = RDS_DEVICE,
|
||||||
.num_streams = DEFAULT_STREAMS
|
.num_streams = DEFAULT_STREAMS
|
||||||
};
|
};
|
||||||
@@ -91,6 +108,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
pthread_t control_pipe_thread;
|
pthread_t control_pipe_thread;
|
||||||
|
pthread_t udp_server_thread;
|
||||||
|
|
||||||
const char *short_opt = "c:h";
|
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;
|
int pulse_error;
|
||||||
|
|
||||||
// Dynamically allocate buffer based on stream count
|
// Dynamically allocate buffer based on stream count
|
||||||
@@ -202,6 +235,11 @@ exit:
|
|||||||
pthread_join(control_pipe_thread, NULL);
|
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
|
cleanup_rds_modulator(&rdsModulator); // Clean up dynamically allocated memory
|
||||||
pthread_attr_destroy(&attr);
|
pthread_attr_destroy(&attr);
|
||||||
if (rds_device != NULL) pa_simple_free(rds_device);
|
if (rds_device != NULL) pa_simple_free(rds_device);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
Reference in New Issue
Block a user