QO100Tx_Rx/udp/udp.cpp

139 lines
4.0 KiB
C++
Raw Permalink Normal View History

2025-10-20 20:11:21 +02:00
/*
* super simple UDP handler
* ========================
* Author: DJ0ABR
*
* (c) DJ0ABR
* www.dj0abr.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <sys/syscall.h>
#include "udp.h"
void* threadfunction(void* param);
#define MAXUDPTHREADS 20
RXCFG udprxcfg[MAXUDPTHREADS];
int rxcfg_idx = 0;
// start UDP reception
// sock ... pointer to a socket (just a pointer to an int)
// port ... own port, messages only to this port are received
// rxfunc ... pointer to a callback function, will be called for received data
// keeprunning ... pointer to an int. If it is set to 0, the function exits
void UdpRxInit(int *sock, int port, void (*rxfunc)(uint8_t *, int, struct sockaddr_in*), int *keeprunning)
{
if(rxcfg_idx >= MAXUDPTHREADS)
{
printf("max number of UDP threads\n");
exit(0);
}
udprxcfg[rxcfg_idx].sock = sock;
udprxcfg[rxcfg_idx].port = port;
udprxcfg[rxcfg_idx].rxfunc = rxfunc;
udprxcfg[rxcfg_idx].keeprunning = keeprunning;
// bind port
struct sockaddr_in sin;
*sock = socket(PF_INET, SOCK_DGRAM, 0);
if (*sock == -1){
printf("Failed to create Socket\n");
exit(0);
}
char enable = 1;
setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = INADDR_ANY;
if (bind(*sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) != 0)
{
printf("Failed to bind socket, port:%d\n",port);
close(*sock);
exit(0);
}
//printf("port %d sucessfully bound\n", port);
// port sucessfully bound
// create the receive thread
pthread_t rxthread;
pthread_create(&rxthread, NULL, threadfunction, &(udprxcfg[rxcfg_idx]));
rxcfg_idx++;
}
void* threadfunction(void* param)
{
socklen_t fromlen;
pthread_detach(pthread_self());
RXCFG rxcfg;
memcpy((uint8_t *)(&rxcfg), (uint8_t *)param, sizeof(RXCFG));
int recvlen;
const int maxUDPpacketsize = 100000;
char rxbuf[maxUDPpacketsize];
struct sockaddr_in fromSock;
fromlen = sizeof(struct sockaddr_in);
printf("entering UDP thread, *** PID:%ld ***\n",syscall(SYS_gettid));
while(*rxcfg.keeprunning)
{
recvlen = recvfrom(*rxcfg.sock, rxbuf, maxUDPpacketsize, 0, (struct sockaddr *)&fromSock, &fromlen);
if (recvlen > 0)
{
// data received, send it to callback function
(*rxcfg.rxfunc)((uint8_t *)rxbuf,recvlen, &fromSock);
}
if (recvlen < 0)
{
}
}
pthread_exit(NULL); // self terminate this thread
return NULL;
}
// send UDP message
// this function can always be used without any initialisation
void sendUDP(char *destIP, int destPort, uint8_t *pdata, int len)
{
int sockfd;
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(destPort);
servaddr.sin_addr.s_addr=inet_addr(destIP);
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
printf("sendUDP: socket creation failed\n");
exit(0);
}
ssize_t sent = sendto(sockfd, (char *)pdata, len, 0, (const struct sockaddr *) &servaddr, sizeof(servaddr));
if((int)sent != len)
{
printf("UDP tx error %d\n",(int)sent);
}
close(sockfd);
}