/* * High Speed modem to transfer data in a 2,7kHz SSB channel * ========================================================= * 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 "hsmodem.h" #ifdef _LINUX_ void* threadfunction(void* param); #endif #ifdef _WIN32_ void threadfunction(void* param); #endif #define MAXUDPTHREADS 20 RXCFG rxcfg[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); } rxcfg[rxcfg_idx].sock = sock; rxcfg[rxcfg_idx].port = port; rxcfg[rxcfg_idx].rxfunc = rxfunc; rxcfg[rxcfg_idx].keeprunning = keeprunning; // bind port struct sockaddr_in sin; #ifdef _WIN32_ WSADATA wsaData = { 0 }; int ires = WSAStartup(MAKEWORD(2, 2), &wsaData); if (ires != 0) printf("WSAStartup failed: %d\n", ires); #endif *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); #ifdef _LINUX_ close(*sock); #endif #ifdef _WIN32_ closesocket(*sock); #endif exit(0); } printf("port %d sucessfully bound\n", port); // port sucessfully bound // create the receive thread #ifdef _LINUX_ pthread_t rxthread; pthread_create(&rxthread, NULL, threadfunction, &(rxcfg[rxcfg_idx])); #endif #ifdef _WIN32_ _beginthread(threadfunction, 0, &(rxcfg[rxcfg_idx])); #endif rxcfg_idx++; } #ifdef _LINUX_ void* threadfunction(void* param) { socklen_t fromlen; pthread_detach(pthread_self()); #endif #ifdef _WIN32_ void threadfunction(void* param) { int fromlen; #endif RXCFG rxcfg; memcpy((uint8_t *)(&rxcfg), (uint8_t *)param, sizeof(RXCFG)); int recvlen; const int maxUDPpacketsize = 2048; char rxbuf[maxUDPpacketsize]; struct sockaddr_in fromSock; fromlen = sizeof(struct sockaddr_in); 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) { #ifdef _WIN32_ printf("recvfrom error: %d", WSAGetLastError()); #endif } } #ifdef _LINUX_ pthread_exit(NULL); // self terminate this thread return NULL; #endif } // send UDP message void sendUDP(char *destIP, int destPort, uint8_t *pdata, int len) { int sockfd; struct sockaddr_in servaddr; // Creating socket file descriptor if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { printf("sendUDP: socket creation failed\n"); exit(0); } memset(&servaddr, 0, sizeof(servaddr)); // Filling server information servaddr.sin_family = AF_INET; servaddr.sin_port = htons(destPort); //printf("Send to <%s><%d> Len:%d\n",destIP,destPort,len); servaddr.sin_addr.s_addr=inet_addr(destIP); sendto(sockfd, (char *)pdata, len, 0, (const struct sockaddr *) &servaddr, sizeof(servaddr)); #ifdef _LINUX_ close(sockfd); #endif #ifdef _WIN32_ closesocket(sockfd); #endif }