Second Try...

pull/1/head
Tom Early 8 years ago
parent f6de8014b8
commit 2ca0a0c784

@ -42,8 +42,8 @@ g2_ircddb : $(IRCOBJS) g2_ircddb.o aprs.o
g2_link : g2_link.o g2_link : g2_link.o
g++ $(CPPFLAGS) -o g2_link g2_link.o $(LDFLAGS) -pthread g++ $(CPPFLAGS) -o g2_link g2_link.o $(LDFLAGS) -pthread
mmdvm_modem : mmdvm_modem.o UDPSocket.o mmdvm_modem : mmdvm_modem.o
g++ $(CPPFLAGS) -o mmdvm_modem mmdvm_modem.o UDPSocket.o $(LDFLAGS) g++ $(CPPFLAGS) -o mmdvm_modem mmdvm_modem.o $(LDFLAGS)
dvap_rptr : dvap_rptr.o DVAPDongle.o $(DSTROBJS) dvap_rptr : dvap_rptr.o DVAPDongle.o $(DSTROBJS)
g++ $(CPPFLAGS) -o dvap_rptr dvap_rptr.o DVAPDongle.o $(DSTROBJS) $(LDFLAGS) -pthread g++ $(CPPFLAGS) -o dvap_rptr dvap_rptr.o DVAPDongle.o $(DSTROBJS) $(LDFLAGS) -pthread

@ -1,175 +0,0 @@
/*
* Copyright (C) 2006-2016 by Jonathan Naylor G4KLX
* Copyright (c) 2018 by Thomas A. Early N7TAE
*
* 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 "UDPSocket.h"
#include <cassert>
#include <cstdio>
#include <cerrno>
#include <cstring>
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
m_address(address),
m_port(port),
m_fd(-1)
{
}
CUDPSocket::CUDPSocket(unsigned int port) :
m_address(),
m_port(port),
m_fd(-1)
{
}
CUDPSocket::~CUDPSocket()
{
}
in_addr CUDPSocket::lookup(const std::string& hostname)
{
in_addr addr;
in_addr_t address = ::inet_addr(hostname.c_str());
if (address != in_addr_t(-1)) {
addr.s_addr = address;
return addr;
}
struct hostent* hp = ::gethostbyname(hostname.c_str());
if (hp != NULL) {
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
return addr;
}
printf("Cannot find address for host %s", hostname.c_str());
addr.s_addr = INADDR_NONE;
return addr;
}
bool CUDPSocket::open() // returns true on error
{
m_fd = ::socket(PF_INET, SOCK_DGRAM, 0);
if (m_fd < 0) {
printf("Cannot create the UDP socket, err: %d, %s\n", errno, strerror(errno));
return true;
}
if (m_port > 0U) {
sockaddr_in addr;
::memset(&addr, 0x00, sizeof(sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(m_port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (!m_address.empty()) {
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
if (addr.sin_addr.s_addr == INADDR_NONE) {
printf("The local address is invalid - %s\n", m_address.c_str());
return true;
}
}
int reuse = 1;
if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
printf("Cannot set the UDP socket (port %u) option, err: %d, %s\n", m_port, errno, strerror(errno));
return true;
}
if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
printf("Cannot bind the UDP (port %u) address, err: %d, %s\n", m_port, errno, strerror(errno));
return true;
}
}
return false;
}
int CUDPSocket::read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port)
{
assert(buffer != NULL);
assert(length > 0U);
// Check that the readfrom() won't block
fd_set readFds;
FD_ZERO(&readFds);
FD_SET(m_fd, &readFds);
// Return immediately if there is nothing for this socket
timeval tv;
tv.tv_sec = 0L;
tv.tv_usec = 0L;
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
if (ret < 0) {
printf("Error returned from UDP select, err: %d, %s\n", errno, strerror(errno));
return -1;
}
if (ret == 0)
return 0;
if (! FD_ISSET(m_fd, &readFds))
return 0; // nothing for this socket;
sockaddr_in addr;
socklen_t size = sizeof(sockaddr_in);
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
if (len <= 0) {
printf("Error returned from recvfrom, err: %d, %s\n", errno, strerror(errno));
return -1;
}
address = addr.sin_addr;
port = ntohs(addr.sin_port);
return len;
}
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port)
{
assert(buffer != NULL);
assert(length > 0U);
sockaddr_in addr;
::memset(&addr, 0x00, sizeof(sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr = address;
addr.sin_port = htons(port);
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
if (ret < 0) {
printf("Error returned from sendto, err: %d, %s\n", errno, strerror(errno));
return false;
}
if (ret != ssize_t(length))
return false;
return true;
}
void CUDPSocket::close()
{
::close(m_fd);
}

@ -1,53 +0,0 @@
/*
* Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX
* Copyright (c) 2018 by Thomas A. Early N7TAE
*
* 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.
*/
#pragma once
#include <string>
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
class CUDPSocket {
public:
CUDPSocket(const std::string& address, unsigned int port = 0U);
CUDPSocket(unsigned int port = 0U);
~CUDPSocket();
bool open();
int read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port);
bool write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port);
void close();
static in_addr lookup(const std::string& hostName);
private:
std::string m_address;
unsigned short m_port;
int m_fd;
};

@ -65,50 +65,148 @@ bool CMMDVMModem::Initialize(const char *cfgfile)
return false; return false;
} }
int CMMDVMModem::OpenSocket(const std::string &address, unsigned short port)
{
if (! port) {
printf("ERROR: OpenSocket: non-zero port must be specified.\n");
return -1;
}
int fd = ::socket(PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("Cannot create the UDP socket, err: %d, %s\n", errno, strerror(errno));
return -1;
}
sockaddr_in addr;
::memset(&addr, 0, sizeof(sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (! address.empty()) {
addr.sin_addr.s_addr = ::inet_addr(address.c_str());
if (addr.sin_addr.s_addr == INADDR_NONE) {
printf("The local address is invalid - %s\n", address.c_str());
close(fd);
return -1;
}
}
int reuse = 1;
if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
printf("Cannot set the UDP socket %s:%u option, err: %d, %s\n", m_port, errno, strerror(errno));
close(fd);
return -1;
}
if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
printf("Cannot bind the UDP (port %u) address, err: %d, %s\n", m_port, errno, strerror(errno));
close(fd);
return -1;
}
return fd;
}
void CMMDVMModem::Run(const char *cfgfile) void CMMDVMModem::Run(const char *cfgfile)
{ {
if (Initialize(cfgfile)) if (Initialize(cfgfile))
return; return;
CUDPSocket MMDVMSock(MMDVM_IP, MMDVM_PORT); int msock = OpenSocket(MMDVM_IP, MMDVM_PORT);
if (MMDVMSock.open()) if (msock < 0)
return; return;
CUDPSocket GatewaySock(G2_INTERNAL_IP, G2_INTERNAL_PORT); int gsock = OpenSocket(G2_INTERNAL_IP, G2_INTERNAL_PORT);
if (GatewaySock.open()) { if (gsock < 0) {
MMDVMSock.close(); ::close(fd_m);
return; return;
} }
keep_running = true; keep_running = true;
while (keep_running) { while (keep_running) {
ProcessMMDVM(GatewaySock, MMDVMSock); struct timeval tv;
if (keep_running) fd_set readfds;
ProcessGateway(GatewaySock, MMDVMSock);
tv.tv_sec = 0;
tv.tv_usec = 1000; // wait 1ms for some input
FD_ZERO(&readfds);
FD_SET(msock, &readfds);
FD_SET(gsock, &readfds);
int maxfd = (msock > gsock) ? msock : gsock;
// don't care about writefds and exceptfds:
int ret = ::select(maxfd+1, &readfds, NULL, NULL, &tv);
if (ret < 0)
break;
if (ret == 0)
continue;
// there is something to read!
unsigned char buf[100];
sockaddr_in addr;
memset(&addr, 0, sizeof(sockaddr_in));
ssize_t len;
if (FD_ISSET(msock, &readfds)) {
len = ::recvfrom(msock, buf, 100, 0, (sockaddr *)&addr, sizeof(sockaddr_in);
if (len < 0) {
printf("ERROR: RUN: recvfrom(mmdvm) return error %d, %s\n", errno, strerror(errno));
break;
}
if (addr.sin_port == G2_PORT)
printf("DEBUG: Run: reading from fd_m but port was %d.\n", addr.sin_port);
} else if (FD_ISSET(gsock, &readfds)) {
len = ::recvfrom(fd_g, buf, 100, 0, (sockaddr *)&addr, sizeof(sockaddr_in);
if (len < 0) {
printf("ERROR: RUN: recvfrom(g2) return error %d, %s\n", errno, strerror(errno));
break;
}
if (addr.sin_port == MMDVM_PORT)
printf("DEBUG: Run: reading from fd_g but port was %d.\n", addr.sin_port);
} else {
printf("ERROR: Run: Input from unknown fd!\n");
break;
}
if (len == 0)
continue;
if (addr.sin_port == MMDVM_PORT) {
if (ProcessMMDVM(buf))
break;
} else if (addr.sin_port == G2_PORT) {
if (ProcessGateway(buf))
break;
}
} }
MMDVMSock.close(); ::close(fd_m);
GatewaySock.close(); ::close(fd_g);
} }
void CMMDVMModem::ProcessGateway(CUDPSocket &gsock, CUDPSocket &msock) int CMMDVMModem::SendTo(const int fd, const unsigned char *buf, const int size, const std::string &address, const unsigned short port)
{ {
SPKT buf; sockaddr_in addr;
unsigned int port; ::memset(&addr, 0, sizeof(sockaddr_in);
addr.sin_family = AF_INET;
// read from gateway addr.sin_addr.s_addr = ::inet_addr(address.c_str());
int len = gsock.read(buf.pkt_id, 58, g2_internal_addr, port); addr.sin_port = htons(port);
if (0 == len) return ::sendto(fd, buf, size, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
return; }
if (0 > len) { bool CMMDVMModem::ProcessGateway(const int len, const unsigned char *raw)
printf("ERROR: ProcessGateway: Can't read gateway packet\n"); {
keep_running = false; SPKT buf;
return; ::memcpy(buf.pkt_id, buf, len);
}
// if there is data, translate it and send it to the MMDVM Modem // if there is data, translate it and send it to the MMDVM Modem
if (29==len || 58==len) { //here is dstar data if (29==len || 58==len) { //here is dstar data
@ -125,10 +223,10 @@ void CMMDVMModem::ProcessGateway(CUDPSocket &gsock, CUDPSocket &msock)
printf("DEBUG: ProcessGateway: unexpected voice sequence number %d\n", pkt.voice.seq); printf("DEBUG: ProcessGateway: unexpected voice sequence number %d\n", pkt.voice.seq);
memcpy(pkt.voice.ambe, buf.vpkt.vasd.text, 12); memcpy(pkt.voice.ambe, buf.vpkt.vasd.text, 12);
if (false == msock.write(pkt.title, 21, mmdvm_addr, MMDVM_PORT)) { int ret = SendTo(msock, pkt.title, 21, mmdvm_addr, MMDVM_PORT))
if (ret != 21) {
printf("ERROR: ProcessGateway: Could not write AMBE mmdvm packet\n"); printf("ERROR: ProcessGateway: Could not write AMBE mmdvm packet\n");
keep_running = false; return true;
return;
} }
} else { // write a Header packet } else { // write a Header packet
pkt.tag = 0x20U; pkt.tag = 0x20U;
@ -140,34 +238,21 @@ void CMMDVMModem::ProcessGateway(CUDPSocket &gsock, CUDPSocket &msock)
} }
memcpy(pkt.header.flag, buf.vpkt.hdr.flag, 41); memcpy(pkt.header.flag, buf.vpkt.hdr.flag, 41);
if (false == msock.write(pkt.title, 49, mmdvm_addr, MMDVM_PORT)) { int ret = SendTo(msock, pkt.title, 49, mmdvm_addr, MMDVM_PORT);
if (ret != 49) {
printf("ERROR: ProcessGateway: Could not write Header mmdvm packet\n"); printf("ERROR: ProcessGateway: Could not write Header mmdvm packet\n");
keep_running = false; return true;
} }
} }
} else } else
printf("DEBUG: ProcessGateway: unusual packet size read len=%d\n", len); printf("DEBUG: ProcessGateway: unusual packet size read len=%d\n", len);
return false;
} }
void CMMDVMModem::ProcessMMDVM(CUDPSocket &gsock, CUDPSocket &msock) bool CMMDVMModem::ProcessMMDVM(const int len, const unsigned char *raw)
{ {
SMMDVMPKT mpkt; SMMDVMPKT mpkt;
static SPKT gpkt; // retain some header values for voice data ::memcopy(mpkt.title, raw, len);
unsigned int mmdvm_port = MMDVM_PORT;
in_addr addr;
addr.s_addr = mmdvm_addr.s_addr;
// read from the MMDVM modem
int len = msock.read(mpkt.title, 64, addr, mmdvm_port);
if (0 == len) // no data available
return;
if (0 > len) {
printf("ERROR: ProcessMMDVM: Could not read mmdvm packet\n");
keep_running = false;
return;
}
// if there is data, translate it and send it to the Gateway // if there is data, translate it and send it to the Gateway
if (49 == len) { if (49 == len) {
@ -185,9 +270,10 @@ void CMMDVMModem::ProcessMMDVM(CUDPSocket &gsock, CUDPSocket &msock)
gpkt.vpkt.streamid = (rand_r(&seed) % 65535U) + 1U; gpkt.vpkt.streamid = (rand_r(&seed) % 65535U) + 1U;
gpkt.vpkt.ctrl = mpkt.header.seq; gpkt.vpkt.ctrl = mpkt.header.seq;
memcpy(gpkt.vpkt.hdr.flag, mpkt.header.flag, 41); memcpy(gpkt.vpkt.hdr.flag, mpkt.header.flag, 41);
if (false == gsock.write(gpkt.pkt_id, 58, g2_internal_addr, (unsigned int)G2_INTERNAL_PORT)) { int ret = SendTo(gsock, gpkt.pkt_id, 58, g2_internal_addr, (unsigned int)G2_INTERNAL_PORT);
if (ret != 58) {
printf("ERROR: ProcessMMDVM: Could not write gateway header packet\n"); printf("ERROR: ProcessMMDVM: Could not write gateway header packet\n");
keep_running = false; return true;
} }
} else if (21 == len) { } else if (21 == len) {
// just a few need updating in a voice data frame // just a few need updating in a voice data frame
@ -195,12 +281,14 @@ void CMMDVMModem::ProcessMMDVM(CUDPSocket &gsock, CUDPSocket &msock)
gpkt.remaining = 0x16; gpkt.remaining = 0x16;
gpkt.vpkt.ctrl = mpkt.voice.seq; gpkt.vpkt.ctrl = mpkt.voice.seq;
memcpy(gpkt.vpkt.vasd.text, mpkt.voice.ambe, 12); memcpy(gpkt.vpkt.vasd.text, mpkt.voice.ambe, 12);
if (false == gsock.write(gpkt.pkt_id, 29, g2_internal_addr, (unsigned int)G2_INTERNAL_PORT)) { int ret = SendTo(gsock, gpkt.pkt_id, 29, g2_internal_addr, (unsigned int)G2_INTERNAL_PORT);
if (ret != 29) {
printf("ERROR: ProcessMMDVM: Could not write gateway header packet\n"); printf("ERROR: ProcessMMDVM: Could not write gateway header packet\n");
keep_running = false; return true;
} }
} else } else
printf("DEBUG: ProcessMMDVM: unusual packet size read len=%d\n", len); printf("DEBUG: ProcessMMDVM: unusual packet size read len=%d\n", len);
return false;
} }
bool CMMDVMModem::GetValue(const Config &cfg, const char *path, int &value, const int min, const int max, const int default_value) bool CMMDVMModem::GetValue(const Config &cfg, const char *path, int &value, const int min, const int max, const int default_value)

@ -46,8 +46,10 @@ private:
// functions // functions
bool Initialize(const char *cfgfile); bool Initialize(const char *cfgfile);
static void SignalCatch(int signum); static void SignalCatch(int signum);
void ProcessGateway(CUDPSocket &gsock, CUDPSocket &msock); bool ProcessGateway(const int len, const unsigned char *raw);
void ProcessMMDVM(CUDPSocket &gsock, CUDPSocket &msock); bool ProcessMMDVM(const int len, const unsigned char *raw);
int OpenSocket(const std::string &address, unsigned short port);
int SendTo(cont int fd, const unsigned char *buf, const int size, const std::string &address, const unsigned short port);
// read configuration file // read configuration file
bool ReadConfig(const char *); bool ReadConfig(const char *);
@ -61,13 +63,12 @@ private:
char RPTR[CALL_SIZE + 1]; char RPTR[CALL_SIZE + 1];
char OWNER[CALL_SIZE + 1]; char OWNER[CALL_SIZE + 1];
std::string MMDVM_IP, G2_INTERNAL_IP; std::string MMDVM_IP, G2_INTERNAL_IP;
in_addr mmdvm_addr, g2_internal_addr;
unsigned short MMDVM_PORT, G2_INTERNAL_PORT; unsigned short MMDVM_PORT, G2_INTERNAL_PORT;
int WAIT_FOR_PACKETS, DELAY_BEFORE, DELAY_BETWEEN; int WAIT_FOR_PACKETS, DELAY_BEFORE, DELAY_BETWEEN;
bool RPTR_ACK; bool RPTR_ACK;
// parameters // parameters
int gateway_sock, mmdvm_sock; int gsock, msock;
unsigned int seed; unsigned int seed;
unsigned short COUNTER; unsigned short COUNTER;
}; };

Loading…
Cancel
Save

Powered by TurnKey Linux.