#ifndef DEBUG
#ifdef NDEBUG
#define DEBUG(x) /* Debug assertion */
#else
#define DEBUG(x) x
#endif
#endif
/**
* \def DEBUG(x)
*
* Removes x from the source code if NDEBUG is defined.
*/
/**
* Throws an object as an exception if an assertion is not met. Can be used with the
* DEBUG macro to selectively remove assertions from production code. For example:
*
*
* Assert(foo == bar, AssertException("failed!"));
*
* DEBUG(Assert(foo == bar, AssertException("failed!")));
*
*
* The second assertion will be removed if NDEBUG is defined.
*/
namespace aprsd {
template inline void Assert(bool assertion, E e)
{
if (!assertion) throw e;
}
}
#endif // ASSERT_H
aprsd-2.2.5-13/src/ax25socket.cpp 0000644 0000000 0000000 00000022300 07665450331 011772 /*
* $Id: ax25socket.cpp,v 1.8 2003/05/29 18:26:33 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2001 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
/* Based on serial.cpp
Implements the same interface as serial.cpp (as specified
in serial.h), but uses Linux network sockets.
*/
#include "config.h"
#ifdef HAVE_LIBAX25 // if no AX25, do nothing
#include
#include
#include // poll, et el
#include
#include
#include
#include
#include // isprint
#include
#include
#include
#include
#include "osdep.h"
#include "ax25socket.h"
#include "constant.h"
#include "rf.h"
#include "servers.h"
using std::cerr;
using std::endl;
using std::cout;
//---------------------------------------------------------------------
// AX.25 constants
#define ALEN 6
#define AXLEN 7
/* SSID mask and various flags that are stuffed into the SSID byte */
#define SSID 0x1E
#define HDLCAEB 0x01
#define REPEATED 0x80
#define UI 0x03 // unnumbered information (unproto)
#define PID_NO_L3 0xF0 // no level-3 (text)
//---------------------------------------------------------------------
// AX.25 variables
char* ax25port; // Name of port to use
char* ax25dev; // Associated device name
int rx_socket, tx_socket; // RX and TX socket descriptors
int proto = ETH_P_ALL; // Protocol to use for receive
struct full_sockaddr_ax25 tx_dest; // TX destination address
struct full_sockaddr_ax25 tx_src; // TX source address
int tx_src_len, tx_dest_len; // Length of addresses
//---------------------------------------------------------------------
// AX.25 function prototypes
void fmt (const unsigned char*, int, unsigned char**);
char* pax25 (char*, const unsigned char*);
//---------------------------------------------------------------------
// Open the AX.25 sockets
int SocketOpen(const string& rfport, const string& destcall)
{
char* portcall;
if (destcall.size() == 0) {
cerr << "aprsd: no APRSPATH specified, required for sockets" << endl;
return 1;
}
// Open network sockets here
ax25port = strdup(rfport.c_str());
if (ax25_config_load_ports() == 0)
cerr << "aprsd: no AX.25 port data configured" << endl;
if ((ax25dev = ax25_config_get_dev(ax25port)) == NULL) {
cerr << "aprsd: invalid port name - " << ax25port << endl;
return 1;
}
// Create the receive socket
if ((rx_socket = socket(PF_PACKET, SOCK_PACKET, htons(proto))) == -1) {
perror("socket");
return 1;
}
// Create the transmit socket
if ((tx_socket = socket(PF_AX25, SOCK_DGRAM, 0)) == -1) {
perror("socket");
return 1;
}
// Get the port's callsign
if ((portcall = ax25_config_get_addr(ax25port)) == NULL) {
cerr << "invalid AX.25 port setting - " << ax25port << endl;
return 1;
}
// Convert to AX.25 addresses
if ((tx_src_len = ax25_aton(portcall, &tx_src)) == -1) {
cerr << "unable to convert callsign '" << portcall << "'" << endl;
return 1;
}
if ((tx_dest_len = ax25_aton(destcall.c_str(), &tx_dest)) == -1) {
cerr << "unable to convert callsign '" << destcall << "'" << endl;
return 1;
}
// Bind the socket
if (bind(tx_socket, (struct sockaddr *)&tx_src, tx_src_len) == -1) {
perror("bind");
return 1;
}
return 0;
}
//--------------------------------------------------------------------
int SocketClose (void)
{
// nothing to do here
return 0;
}
//--------------------------------------------------------------------
// This is the socket read thread.
// It polls the socket, and returns any data received
// (after reformatting it to raw TNC format).
bool SocketReadWrite(char buf[])
{
bool lineTimeout;
struct pollfd pfd;
struct sockaddr sa;
struct ifreq ifr;
int asize;
int result;
int size = 0;
unsigned char rxbuf[1500];
unsigned char *textbuf;
int rc;
lineTimeout = false;
do {
if (txrdy) { //Check for data to Transmit
//cerr << "DEBUG: SocketReadWrite: Sending " << buf << " to Socket" << endl;
if ((rc = sendto(tx_socket, tx_buffer, strlen(tx_buffer), 0, (struct sockaddr *)&tx_dest, tx_dest_len)) < 0)
cerr << "DEBUG: SocketReadWrite: Error sending to TNC" << endl;
txrdy = false; //Indicate we sent it.
}
pfd.fd = rx_socket;
pfd.events = 0x040; // Read normal data -- should be POLLRDNORM
result = poll(&pfd, 1, 100); // Time-out after 100ms
if (result == 1) {
asize = sizeof(sa);
if ((size = recvfrom(rx_socket, rxbuf, sizeof(rxbuf), 0, &sa, (socklen_t*)&asize)) == -1) {
perror("AX25 Socket recvfrom error");
result = -1;
} else {
if (ax25dev != NULL && strcmp(ax25dev, sa.sa_data) != 0)
result = 0;
if (proto == ETH_P_ALL) { // promiscuous mode?
strcpy(ifr.ifr_name, sa.sa_data);
if (ioctl(rx_socket, SIOCGIFHWADDR, &ifr) < 0
|| ifr.ifr_hwaddr.sa_family != AF_AX25)
result = 0; // not AX25 so ignore this packet
}
if (result == 1) {
fmt(rxbuf, size, &textbuf); // convert to text
strncpy(buf, (char*)textbuf, BUFSIZE);
TotalTncChars += BUFSIZE;
}
}
}
if (result < 0) // input error
lineTimeout = true; // Error has occurred
} while (result == 0);
//cout << "DEBUG: AX25SockReadWrite: " << buf << endl;
return lineTimeout;
}
//---------------------------------------------------------------------
// fmt converts a received packet into a TNC message string
void fmt(const unsigned char *buf, int len, unsigned char **outbuf)
{
static unsigned char buf1[1000];
char from[10], to[10], digis[100];
int i, hadlast, l;
char tmp[15];
*buf1 = '\0';
*outbuf = buf1;
if ((buf[0] & 0xf) != 0) // not a kiss data frame
return;
++buf;
--len;
if (len < (AXLEN + ALEN + 1)) // too short
return;
pax25 (to, buf); // to call
pax25 (from, &buf[AXLEN]); // from call
buf += AXLEN; // skip over the from call now...
len -= AXLEN;
*digis = '\0';
if (!(buf[ALEN] & HDLCAEB)) { // is there a digipeater path?
for (l = 0, buf += AXLEN, len -= AXLEN, i = 0;
i < 6 && len >= 0; i++, len -= AXLEN, buf += AXLEN) {
int nextrept = buf[AXLEN + ALEN] & REPEATED;
if (buf[ALEN] & HDLCAEB)
nextrept = 0;
pax25 (tmp, buf);
if (*tmp) {
sprintf (&digis[l], ",%s%s", tmp, (buf[ALEN] & REPEATED && !nextrept) ? "*" : "");
++hadlast;
l += strlen (&digis[l]);
}
if (buf[ALEN] & HDLCAEB)
break;
}
}
buf += AXLEN;
len -= AXLEN;
if (len <= 0)
return; // no data after callsigns
if (*buf++ == UI && *buf++ == PID_NO_L3) {
len -= 2;
} else {
return; // must have UI text to be useful
}
// No rewriting for mic-e frames because aprsd does this later
sprintf ((char*)buf1, "%s>%s%s:", from, to, digis);
l = strlen ((char*)buf1);
for (i = 0; i < len; i++, l++) {
buf1[l] = (isprint (buf[i])) ? buf[i] : ' '; // keep it clean
}
buf1[l++] = 0x0d;
buf1[l++] = 0x0a;
buf1[l] = '\0';
return;
}
//---------------------------------------------------------------------
// pax25 formats an AX.25 callsign.
char * pax25 (char *buf, const unsigned char *data)
{
int i, ssid;
char *s;
char c;
s = buf;
for (i = 0; i < ALEN; i++) {
c = (data[i] >> 1) & 0x7F;
if (c != ' ')
*s++ = c;
}
if ((ssid = (data[ALEN] & SSID) >> 1) != 0)
sprintf (s, "-%d", ssid);
else
*s = '\0';
return (buf);
}
#endif // HAVE_LIBAX25
aprsd-2.2.5-13/src/ax25socket.h 0000644 0000764 0000764 00000002542 07661563341 011511 /*
* $Id: ax25socket.h,v 1.5 2003/05/18 01:50:25 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2001 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#ifndef AX25SOCKETS_H
#define AX25SOCKETS_H
#include "constant.h"
using namespace aprsd;
// TCP Wrappers
int inet_ptons(int family, const char *strptr, void *addrptr);
int SocketOpen (const string& rfport, const string& destcall);
int SocketClose (void);
int SocketWrite (const char *cp);
int SocketWrite (void);
bool SocketReadWrite (char buf[]);
#endif // AX25SOCKETS_H
aprsd-2.2.5-13/src/constant.h 0000664 0000764 0000764 00000006013 07655343020 011342 /*
* $Id: constant.h,v 1.12 2003/03/31 04:47:54 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#ifndef CONSTANT_H
#define CONSTANT_H
#include
#include "config.h"
//If you really must convert Mic-E packets to traditional APRS
//change this to TRUE and add "ConvertMicE yes" to your aprsd.conf file.
//#define CONVERT_MIC_E FALSE
const bool CONVERT_MIC_E = false;
/* Define this to write 3rd party pkts to debug.log */
// #define DEBUGTHIRDPARTY
//If this is defined the qAc,CallSign construct is added to path
#define INET_TRACE
#define ULONG unsigned long
#define LONG long
#define USHORT unsigned short int
#define INT16 unsigned short int
#define APIRET int
#define INT32 int
#define echomask_t unsigned long
#define LF 0x0a
#define CR 0x0d
#define RXwhite " \t\n\r"
//#define LINK_SERVER_PORT 1313
#define CMD_END_THREAD -1L
#define SRC_TNC -2L
#define SRC_USER -3L
#define SRC_INTERNAL -4L
#define SRC_UDP -5L
#define SRC_IGATE -6L
#define MAXCLIENTS 30
#define MAXLOAD 200000
//This sets the Internet line input buffer size.
//Lines longer than this, including CR,LF,NULL, will be truncated.
//Actually, the data will be truncated but a CR,LF,NULL will always be on the end.
#define BUFSIZE 255
//Defines duplicate detection window time in seconds
#define DUPWINDOW 20
#define RUNTSIZE 0
#define MAXRETRYS 7
#define HOSTIPSIZE 33
#define destINET 1
#define destTNC 2
/* These are for Linux user/pass logons. They define the group used by
/etc/group . You must have these groups and users defined in /etc/group.
The "tnc" group defines which users are allowed direct access to control the TNC.
The "aprs" group defines users which log on with a Linux user/password
instead of the Mac/WinAPRS automatic password. These users are allowed to
insert data into the data stream.
To add a group logon as root and edit the /etc/group file by adding
a line such as: tnc::102:root,wa4dsy,bozo */
#define APRSGROUP "aprs"
#define TNCGROUP "tnc"
/* this is not used in production code*/
//#define TEST "WA4DSY>APRS,WIDE:!3405.31N/08422.46WyWA4DSY APRS Internet Server running on Linux.\r\n"
#endif // CONSTANT_H
aprsd-2.2.5-13/src/cpqueue.cpp 0000664 0000764 0000764 00000011756 07655343021 011526 /*
* $Id: cpqueue.cpp,v 1.19 2003/03/31 04:47:54 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#include
#include
#include
#include
#include
#include
#include
#include "constant.h"
#include "cpqueue.h"
#include "aprsString.h"
using namespace std;
using namespace aprsd;
/*-------------------------------------------------------*/
//Build a Queue object
cpQueue::cpQueue(int n, bool d)
{
overrun = 0;
size = n;
dyn = d;
base_p = new queueData[size];
write_p = 0;
read_p = 0;
itemsQueued = 0;
lock = 0;
inRead = 0;
inWrite = 0;
for (int i = 0; i < size; i++) {
base_p[i].qcp = NULL; // NULL all the pointers
base_p[i].qcmd = 0;
base_p[i].rdy = false; // Clear the ready flags
}
}
//Destroy Queue object
cpQueue::~cpQueue(void)
{
lock = 1;
while(inRead);
while(inWrite);
if (dyn) {
while (read_p != write_p)
if (base_p[read_p].qcp != NULL)
delete (aprsString*)base_p[read_p++].qcp ;
}
delete base_p;
}
//Place a pointer and an Integer in the queue
//returns 0 on success;
int cpQueue::write(char *cp, int n)
{
int rc = 0;
Lock qlock(Q_mutex, false);
if (lock)
return -2; //Lock is only set true in the destructor
inWrite = 1;
qlock.get();
int idx = write_p;
if (base_p[idx].rdy == false) { // Be sure not to overwrite old stuff
base_p[idx].qcp = (void*)cp; // put char* on queue
base_p[idx].qcmd = n; // put int (cmd) on queue
base_p[idx].rdy = true; // Set the ready flag
idx++;
itemsQueued++;
if (idx >= size)
idx = 0;
write_p = idx;
} else {
overrun++ ;
if (dyn) {
delete[] cp; //Added [] brackets 14-July-2001 wa4dsy
cp = NULL; //Added set to NULL 14-July-2001 wa4dsy
}
rc = -1;
}
qlock.release();
inWrite = 0;
return rc;
}
int cpQueue::write(unsigned char *cp, int n)
{
return write((char*)cp, n);
}
int cpQueue::write(const char* cp, int n)
{
return write((char*)cp, n);
}
int cpQueue::write(aprsString* cs, int n)
{
int rc = 0;
Lock qlock(Q_mutex, false);
if (lock)
return -2;
inWrite = 1;
qlock.get();
int idx = write_p;
if (base_p[idx].rdy == false) { // Be sure not to overwrite old stuff
base_p[idx].qcp = (void*)cs; // put String on queue
base_p[idx].qcmd = n; // put int (cmd) on queue
base_p[idx].rdy = true; // Set the ready flag
itemsQueued++;
idx++;
if (idx >= size)
idx = 0;
write_p = idx;
}else {
overrun++ ;
if (dyn){
delete cs; // Delete the object that couldn't be put in the queue
cs = NULL;
}
rc = -1;
}
qlock.release();
inWrite = 0;
return rc;
}
int cpQueue::write(aprsString* cs)
{
return write(cs, cs->sourceSock);
}
//Read a pointer and Integer from the Queue
void* cpQueue::read(int *ip)
{
Lock qlock(Q_mutex, false);
inRead = 1;
qlock.get();
void* cp = base_p[read_p].qcp ; // Read the aprsString*
if (ip)
*ip = base_p[read_p].qcmd ; // read the optional integer command
base_p[read_p].qcp = NULL; // Set the data pointer to NULL
base_p[read_p].rdy = false; // Clear ready flag
read_p++;
itemsQueued--;
if(read_p >= size)
read_p = 0;
inRead = 0;
qlock.release();
return cp;
}
int cpQueue::ready(void) //returns true if data available
{
int rc=false;
Lock qlock(Q_mutex);
//if ((read_p != write_p) || wrap) rc = true ;
if(base_p[read_p].rdy)
rc = true;
//pthread_mutex_unlock(Q_mutex);
return rc;
}
int cpQueue::getWritePtr(void)
{
return write_p;
}
int cpQueue::getReadPtr(void)
{
return read_p;
}
int cpQueue::getItemsQueued(void)
{
return itemsQueued;
}
aprsd-2.2.5-13/src/cpqueue.h 0000664 0000764 0000764 00000003750 07655343021 011166 /*
* $Id: cpqueue.h,v 1.10 2003/03/31 04:47:55 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#ifndef CPQUEUE_H
#define CPQUEUE_H
#include "aprsString.h"
#include "mutex.h"
using namespace aprsd;
class queueData
{
public:
void* qcp; //Pointer to dynamically allocated aprsString or char string.
int qcmd; //Optional interger data command or info
bool rdy;
};
class cpQueue
{
private:
queueData *base_p;
int write_p;
int read_p;
int size, lock, inRead, inWrite;
Mutex Q_mutex;
bool dyn;
public:
int overrun;
int itemsQueued;
cpQueue(int n, bool d); // fifo Queue constructor
~cpQueue(void); // destructor
int write(aprsString* cs, int cmd);
int write(aprsString* cs);
int write(char* cs, int cmd);
int write(unsigned char* cs, int cmd);
int write(const char* cs, int cmd);
void* read(int *cmd);
int ready(void); //return non-zero when queue data is available
int getWritePtr(void); //For debugging
int getReadPtr(void);
int getItemsQueued(void);
};
#endif // CPQUEUE_H
aprsd-2.2.5-13/src/crc32.c 0000664 0000764 0000764 00000020543 07655343021 010425 /* +++Date last modified: 05-Jul-1997 */
/* Crc - 32 BIT ANSI X3.66 CRC checksum files */
#include
#include "crc.h"
/**********************************************************************\
|* Demonstration program to compute the 32-bit CRC used as the frame *|
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|* protocol). The 32-bit FCS was added via the Federal Register, *|
|* 1 June 1982, p.23798. I presume but don't know for certain that *|
|* this polynomial is or will be included in CCITT V.41, which *|
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|* errors by a factor of 10^-5 over 16-bit FCS. *|
\**********************************************************************/
/* Need an unsigned type capable of holding 32 bits; */
typedef DWORD UNS_32_BITS;
/* Copyright (C) 1986 Gary S. Brown. You may use this program, or
code or tables extracted from it, as desired without restriction.*/
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* 1. The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
/* be they sixteen or thirty-two bits wide. You simply choose the */
/* appropriate table. Alternatively, because the table can be */
/* generated at runtime, you can start by generating the table for */
/* the polynomial in question and use exactly the same "updcrc", */
/* if your application needn't simultaneously handle two CRC */
/* polynomials. (Note, however, that XMODEM is strange.) */
/* */
/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
/* of course, 32-bit entries work OK if the high 16 bits are zero. */
/* */
/* 4. The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
static UNS_32_BITS crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
DWORD updateCRC32(unsigned char ch, DWORD crc)
{
return UPDC32(ch, crc);
}
Boolean_T crc32file(char *name, DWORD *crc, long *charcnt)
{
register FILE *fin;
register DWORD oldcrc32;
register int c;
oldcrc32 = 0xFFFFFFFF; *charcnt = 0;
#ifdef MSDOS
if ((fin=fopen(name, "rb"))==NULL)
#else
if ((fin=fopen(name, "r"))==NULL)
#endif
{
perror(name);
return Error_;
}
while ((c=getc(fin))!=EOF)
{
++*charcnt;
oldcrc32 = UPDC32(c, oldcrc32);
}
if (ferror(fin))
{
perror(name);
*charcnt = -1;
}
fclose(fin);
*crc = oldcrc32 = ~oldcrc32;
return Success_;
}
DWORD crc32buf(char *buf, size_t len)
{
register DWORD oldcrc32;
oldcrc32 = 0xFFFFFFFF;
for ( ; len; --len, ++buf)
{
oldcrc32 = UPDC32(*buf, oldcrc32);
}
return ~oldcrc32;
}
#ifdef TEST
main(int argc, char *argv[])
{
DWORD crc;
long charcnt;
register errors = 0;
while(--argc > 0)
{
errors |= crc32file(*++argv, &crc, &charcnt);
printf("%08lX %7ld %s\n", crc, charcnt, *argv);
}
return(errors != 0);
}
#endif /* TEST */
aprsd-2.2.5-13/src/crc.h 0000664 0000764 0000764 00000002035 07655343022 010262 /* +++Date last modified: 05-Jul-1997 */
/*
** CRC.H - header file for SNIPPETS CRC and checksum functions
*/
#ifndef CRC__H
#define CRC__H
#include /* For size_t */
#include "sniptype.h" /* For BYTE, WORD, DWORD */
#ifdef __cplusplus
extern "C" {
#endif
/*
** File: ARCCRC16.C
*/
void init_crc_table(void);
WORD crc_calc(WORD crc, char *buf, unsigned nbytes);
void do_file(char *fn);
/*
** File: CRC-16.C
*/
WORD crc16(char *data_p, WORD length);
/*
** File: CRC-16F.C
*/
WORD updcrc(WORD icrc, BYTE *icp, size_t icnt);
/*
** File: CRC_32.C
*/
#define UPDC32(octet,crc) (crc_32_tab[((crc)\
^ ((BYTE)octet)) & 0xff] ^ ((crc) >> 8))
DWORD updateCRC32(unsigned char ch, DWORD crc);
Boolean_T crc32file(char *name, DWORD *crc, long *charcnt);
DWORD crc32buf(char *buf, size_t len);
/*
** File: CHECKSUM.C
*/
unsigned checksum(void *buffer, size_t len, unsigned int seed);
/*
** File: CHECKEXE.C
*/
void checkexe(char *fname);
#ifdef __cplusplus
}
#endif
#endif /* CRC__H */
aprsd-2.2.5-13/src/dupCheck.cpp 0000664 0000764 0000764 00000006132 07655343022 011576 /*
* $Id: dupCheck.cpp,v 1.10 2003/03/31 04:48:18 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "constant.h"
#include "dupCheck.h"
#include "mutex.h"
#define TABLESIZE 0x10000 /* 64K hash table containing time_t values */
using namespace std;
using namespace aprsd;
dupCheck::dupCheck()
{
hashtime = new time_t[TABLESIZE];
hashhash = new INT16[TABLESIZE];
clear();
time_t t = time(NULL); //Make sure no two aprsd servers user the same seed in the hash function
seed = (unsigned long)t;
if ((hashtime == NULL) || (hashhash == NULL))
cerr << "Dup Filter failed to initialize" << endl;
}
dupCheck::~dupCheck()
{
try {
if (hashtime != NULL) {
delete hashtime;
hashtime = NULL;
}
if (hashhash != NULL) {
delete hashhash;
hashhash = NULL;
}
} catch (...) { }
}
bool dupCheck::check(aprsString* s, int t)
{
bool dup = false;
time_t dt = 0;
static int processed = 0;
static int dupcount = 0;
Lock locker(mutex);
if ((hashtime == NULL) || (hashhash == NULL) || s->allowdup)
return false;
INT32 hash = s->gethash(seed); //Generate hash value from initial seed based on pgm start time.
INT16 hash_lo = hash & 0xffff; //be sure we stay inside the table!
INT16 hash_hi = hash >> 16; //upper 16 bits of hash
hash_hi &= 0xffff;
dt = s->timestamp - hashtime[hash_lo];
if (( dt <= t ) // See if time difference is less than t seconds
&& (hash_hi == hashhash[hash_lo])) { // and hash_hi value is identical
dup = true;
}
hashtime[hash_lo] = s->timestamp; // put this new data in the tables
hashhash[hash_lo] = hash_hi;
if (dup)
dupcount++;
processed++;
return dup;
}
void dupCheck::clear()
{
for (int i = 0; i < TABLESIZE; i++){
if (hashtime)
hashtime[i] = 0; //Initialize tables
if (hashhash)
hashhash[i] = 0;
}
}
aprsd-2.2.5-13/src/dupCheck.h 0000664 0000764 0000764 00000002612 07655343022 011242 /*
* $Id: dupCheck.h,v 1.6 2003/03/31 04:48:18 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#ifndef DUPCHECK_H
#define DUPCHECK_H
#include
#include "constant.h"
#include "aprsString.h"
#include "mutex.h"
using namespace std;
using namespace aprsd;
class dupCheck
{
public:
dupCheck();
~dupCheck();
bool check(aprsString* s, int t);
void clear(void);
private:
Mutex mutex;
time_t* hashtime;
INT16* hashhash;
unsigned long seed;
} ;
#endif // DUPCHECK__H
aprsd-2.2.5-13/src/aprsdexception.cpp 0000664 0000764 0000764 00000011021 07655343016 013074 /*
* $Id: aprsdexception.cpp,v 1.3 2003/04/20 18:34:47 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#include "aprsdexception.h"
namespace aprsd
{
Exception::Exception(const string& arg_message) : m_message(arg_message) { }
Exception::~Exception() throw() { }
string Exception::getMessage() const
{
return m_message;
}
string Exception::toString() const
{
if (getMessage().empty())
return getName();
else
return getName() + ": " + getMessage();
}
const char *Exception::what( void ) const throw()
{
return m_message.c_str();
}
string Exception::getName() const
{
return "aprsd::Exception";
}
AssertException::AssertException(const string& message) :
Exception(message) { }
string AssertException::getName() const
{
return "aprsd::AssertException";
}
UnexpectedException::UnexpectedException(const string& message) :
AssertException(message) { }
string UnexpectedException::getName() const
{
return "aprsd::UnexpectedException";
}
IOException::IOException(const string& message) throw() :
Exception(message) { m_errno = 0; }
IOException::IOException( int ERRNUM ) throw() {
m_message = strerror_r(ERRNUM);
m_errno = ERRNUM;
}
string IOException::getName() const
{
return "aprsd::IOException";
}
UnknownHostException::UnknownHostException(const string& message)
: IOException(message) { }
string UnknownHostException::getName() const
{
return "aprsd::UnknownHostException";
}
TimeoutException::TimeoutException(const string& message) :
IOException(message) { }
string TimeoutException::getName() const
{
return "aprsd::TimeoutException";
}
SocketException::SocketException(const string& message) :
IOException(message) { }
string SocketException::getName() const
{
return "aprsd::SocketException";
}
BindException::BindException(const string& message) :
SocketException(message) { }
string BindException::getName() const
{
return "aprsd::BindException";
}
ConnectException::ConnectException(const string& message) :
SocketException(message) { }
string ConnectException::getName() const
{
return "aprsd::ConnectException";
}
RegexException::RegexException(const string& message) :
Exception(message) { }
string RegexException::getName() const
{
return "aprsd::RegexException";
}
NoSuchElementException::NoSuchElementException(const string& message) :
Exception(message) { }
string NoSuchElementException::getName() const
{
return "aprsd::NoSuchElementException";
}
UnsupportedOperationException::UnsupportedOperationException(const string& message)
: Exception(message) { }
string UnsupportedOperationException::getName() const
{
return "aprsd::UnsupportedOperationException";
}
ParseException::ParseException(const string& message) :
Exception(message) { }
string ParseException::getName() const
{
return "aprsd::ParseException";
}
ThreadControlException::ThreadControlException( const string& message ) :
Exception(message) { }
string ThreadControlException::getName() const
{
return "aprsd::ThreadControlException";
}
RefCountException::RefCountException( const string& message )
: Exception( message ) {}
string RefCountException::getName() const
{
return "aprsd::RefCountException";
}
}
aprsd-2.2.5-13/src/aprsdexception.h 0000664 0000764 0000764 00000015063 07655343017 012554 /*
* $Id: aprsdexception.h,v 1.3 2003/04/20 18:34:47 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#ifndef APRSD_EXCEPTION_H
#define APRSD_EXCEPTION_H
#include "osdep.h"
#include
#include
namespace aprsd
{
using std::string;
using std::exception;
/**
* A base class for exceptions.
*/
class Exception : public std::exception
{
public:
/**
* Constructs an Exception with an optional detail message.
*
* param message a detail message indicating the reason for the
* exception.
*/
explicit Exception(const string& message = "");
/**
* Destructor.
*/
virtual ~Exception() throw();
/**
* return the exception's class name.
*/
virtual string getName() const;
/**
* @return a detail message indicating the reason for the
* exception.
*/
virtual string getMessage() const;
/**
* A concatenation of the exception's class name and its detail
* message, if available.
*/
string toString(void) const;
/**
Return only the message, but following the normal C++ notation !
@return a ziro terminated const char string
*/
const char *what( void ) const throw();
protected:
string m_message;
};
/**
* Indicates that an assertion failed.
*/
class AssertException : public Exception
{
public:
explicit AssertException(const string& message = "");
virtual string getName() const;
};
/**
* Indicates that an unexpected exception was thrown.
*
* see ExceptionGuard
*/
class UnexpectedException : public AssertException
{
public:
explicit UnexpectedException(const string& message = "");
virtual string getName() const;
};
/**
* Indicates that an I/O error has occurred.
*/
class IOException : public Exception
{
public:
explicit IOException( const string& message = "" ) throw();
explicit IOException( int ERRNUM ) throw();
~IOException() throw(){}
virtual string getName() const;
int getErrno( void ) const { return m_errno;}
private:
int m_errno;
};
/**
* Indicates that the IP address of a host could not be resolved.
*/
class UnknownHostException : public IOException
{
public:
explicit UnknownHostException( const string& message = "" );
explicit UnknownHostException( int ERRNUM ) throw() : IOException( ERRNUM ) {}
virtual string getName() const;
};
/**
* Indicates that an operation has timed out.
*/
class TimeoutException : public IOException
{
public:
explicit TimeoutException( const string& message = "" );
explicit TimeoutException( int ERRNUM ) throw() : IOException( ERRNUM ) {}
virtual string getName() const;
};
/**
* Indicates that an error occurred while performing an operation
* on a socket.
*/
class SocketException : public IOException
{
public:
explicit SocketException( const string& message = "" );
explicit SocketException( int ERRNUM ) throw() : IOException( ERRNUM ) {}
virtual string getName() const;
};
/**
* Indicates that an error occurred while attempting to bind a
* socket to a local address and port.
*/
class BindException : public SocketException
{
public:
explicit BindException( const string& message = "" );
explicit BindException( int ERRNUM ) throw() : SocketException( ERRNUM ) {}
virtual string getName() const;
};
/**
* Indicates that an error occurred while attempting to connect a
* socket to a remote address and port.
*/
class ConnectException : public SocketException
{
public:
explicit ConnectException(const string& message = "");
explicit ConnectException( int ERRNUM ) throw() : SocketException( ERRNUM ) {}
virtual string getName() const;
};
/**
* Indicates that the regular expression engine returned an error.
*/
class RegexException : public Exception
{
public:
explicit RegexException(const string& message = "");
virtual string getName() const;
};
/**
* Indicates that the element does not exist.
*/
class NoSuchElementException : public Exception
{
public:
explicit NoSuchElementException(const string& message = "");
virtual string getName() const;
};
/**
* Indicates that the operation is not supported by the library/OS.
*/
class UnsupportedOperationException : public Exception
{
public:
explicit UnsupportedOperationException(const string& message = "");
virtual string getName() const;
};
/**
* Indicates that an error was found while parsing text.
*/
class ParseException : public Exception
{
public:
explicit ParseException(const string& message = "");
virtual string getName() const;
};
/**
* Indicates that an error occurred while trying to control
* a thread or process.
*/
class ThreadControlException : public Exception
{
public:
explicit ThreadControlException(const string& message = "");
virtual string getName() const;
};
/**
This indicate an error occurred while using refcounting.
*/
class RefCountException : public Exception
{
public:
explicit RefCountException(const string& message = "");
virtual string getName() const;
};
}
#endif // APRSD_EXCEPTION_H
aprsd-2.2.5-13/src/exceptionguard.cpp 0000664 0000764 0000764 00000003250 07655343022 013067 /*
* $Id: exceptionguard.cpp,v 1.3 2003/03/31 04:48:33 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#include "exceptionguard.h"
namespace aprsd
{
void assertUnexpected() throw(UnexpectedException)
{
try {
throw;
}
catch (Exception& e) {
throw UnexpectedException(e.toString());
}
catch (exception& e) {
throw UnexpectedException(string("Unexpected system exception: ") + e.what());
}
catch (...) {
throw UnexpectedException("Exception thrown of unknown type");
}
}
ExceptionGuard::ExceptionGuard() throw()
{
old = std::set_unexpected(&assertUnexpected);
}
ExceptionGuard::~ExceptionGuard() throw()
{
std::set_unexpected(old);
}
}
aprsd-2.2.5-13/src/exceptionguard.h 0000664 0000764 0000764 00000004216 07655343023 012540 /*
* $Id: exceptionguard.h,v 1.3 2003/03/31 04:48:33 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#ifndef EXCEPTIONGUARD_H
#define EXCEPTIONGUARD_H
#include "aprsdexception.h"
namespace aprsd
{
using std::unexpected_handler;
extern void assertUnexpected() throw(UnexpectedException);
/**
* Catches unexpected exceptions in a program, and rethrows them as
* UnexpectedException objects. UnexpectedException is derived from AssertException,
* which passes to user code. If the unexpected exception is derived from
* Exception or std::exception, the UnexpectedException object's detail
* message will contain a description of it.
*
* To use this feature, just instantiate an ExceptionGuard as a local variable at the
* beginning of your program's main() method.
*
* This class is not reference-counted.
*
*/
class ExceptionGuard
{
std::unexpected_handler old;
public:
/**
* Sets an unexpected_handler that rethrows exceptions as UnexpectedException
* objects.
*/
ExceptionGuard() throw();
/**
* Restores the original unexpected_handler.
*/
~ExceptionGuard() throw();
};
}
#endif // EXCEPTIONGUARD_H
aprsd-2.2.5-13/src/history.cpp 0000644 0000000 0000000 00000044207 07665450331 011515 /*
* $Id: history.cpp,v 1.28 2003/05/29 18:26:33 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
/*This code maintains a linked list of aprsString objects called the
"History List". It is used to detect and remove duplicate packets
from the APRS stream, provide a 30 minute history of activity to
new users when they log on and determine if the destination of a
3rd party station to station message is "local".
*/
#include
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "history.h"
#include "aprsd.h"
#include "utils.h"
#include "aprsString.h"
#include "servers.h"
#include "mutex.h"
#include "constant.h"
using namespace std;
using namespace aprsd;
struct histRec { //This is for the History Array
int count;
time_t timestamp;
echomask_t EchoMask;
int type;
bool reformatted;
char *data;
};
class HistoryRecord
{
public:
HistoryRecord() throw();
~HistoryRecord() throw();
int count;
time_t timestamp;
echomask_t EchoMask;
int type;
bool reformatted;
char* data;
};
aprsString *pHead, *pTail;
int ItemCount;
Mutex histMutex;
Mutex dupMutex;
int dumpAborts = 0;
//---------------------------------------------------------------------
void CreateHistoryList()
{
pHead = NULL;
pTail = NULL;
ItemCount = 0;
}
//---------------------------------------------------------------------
//Adds aprs packet to history list
//Returns true on success, false on failure
bool AddHistoryItem(aprsString *hp)
{
Lock histLock(histMutex);
if (hp == NULL)
return false;
if (pTail == NULL) { // Starting from empty list
pTail = hp;
pHead = hp;
hp->next = NULL;
hp->last = NULL;
ItemCount++;
} else { // List has at least one item in it.
DeleteItem(hp); // Delete any previously stored items with same call and type
if (ItemCount == 0) { // List is empty, put in first item
pTail = hp;
pHead = hp;
hp->next = NULL;
hp->last = NULL;
} else { // list not empty...
pTail->next = hp; // link the last item to us
hp->last = pTail; // link us to last item
hp->next = NULL; // link us to next item which is NULL
pTail = hp; // link pTail to us
}
ItemCount++;
}
return true;
}
//---------------------------------------------------------------------
//Don't call this from anywhere except DeleteOldItems().
void DeleteHistoryItem(aprsString *hp)
{
if (hp == NULL)
return;
aprsString *li = hp->last;
aprsString *ni = hp->next;
if (hp != NULL) {
if (li != NULL)
li->next = ni;
if (ni != NULL)
ni->last = li;
if (hp == pHead)
pHead = ni;
if (hp == pTail)
pTail = li;
delete hp; // Delete the aprsString object
ItemCount--; // Reduce ItemCount by 1
}
return;
}
//-----------------------------------------------------------------------
//Call this once per 5 minutes
//This reduces the ttl field by x then deletes items when the ttl field is zero or less.
int DeleteOldItems(int x)
{
int delCount = 0;
Lock histLock(histMutex);
if ((pHead == NULL) || (pHead == pTail))
return 0; //empty list
aprsString *hp = pHead;
aprsString *pNext;
while (hp) {
hp->ttl = hp->ttl - x; //update time to live
pNext = hp->next;
if (hp->ttl <= 0 ) {
DeleteHistoryItem(hp);
delCount++;
}
hp = pNext;
}
return delCount;
}
//-------------------------------------------------------------------------
//Deletes an aprsString object matching the ax25Source call sign and packet type
// of the "ref" aprsString. The destination (destTNC or destINET) must also match.
// pmtxHistory mutex must be locked when calling this.
int DeleteItem(aprsString* ref)
{
int delCount = 0;
if ((pHead == NULL) || (pHead == pTail) || (ref == NULL))
return 0;
aprsString *hp = pHead;
aprsString *pNext;
while (hp != NULL) {
pNext = hp->next;
if ((hp->aprsType == ref->aprsType ) && (hp->dest == ref->dest)) {
if (hp->ax25Source.compare(ref->ax25Source) == 0) {
//cerr << "deleteing " << hp->getChar() << flush;
DeleteHistoryItem(hp);
delCount++ ;
}
}
hp = pNext;
}
return delCount;
}
//-------------------------------------------------------------------------
/* Check history list for a packet whose data matches that of "*ref"
that was transmitted less or equal to "t" seconds ago. Returns true
if duplicate exists. Scanning stops when a packet older than "t" seconds
is found.
*/
/*
bool DupCheck(aprsString* ref, time_t t) // Now obsolete and not used in version 2.1.2, June 2000
{ int x = -1;
bool z;
time_t tNow,age;
if (ref->allowdup) return false;
if ((pTail == NULL) || (pHead == NULL)) return false; //Empty list
pthread_mutex_lock(pmtxDupCheck); //Grab semaphore
time(&tNow); //get current time
aprsString *hp = pTail; //Point hp to last item in list
age = tNow - hp->timestamp;
while((hp != NULL) && (x != 0) && (age <= t))
{
age = tNow - hp->timestamp;
if((ref->ax25Source.compare(hp->ax25Source) == 0)
&& (ref->dest == hp->dest)) //check for matching call signs and destination (TNC or Internet)
{
if(ref->data.compare(hp->data) == 0) x = 0; //and matching data
}
hp = hp->last; //Go back in time through list
//Usually less than 10 entrys need checking for 30 sec.
}
if (x == 0) z = true; else z = false;
pthread_mutex_unlock(pmtxDupCheck);
return z;
}
*/
//--------------------------------------------------------------------------
//Scan history list for source callsign which exactly matches *cp .
//If callsign is present and GATE* is not in the path and hops are 3 or less then return true
//The code to scan for "GATE* and hops have been moved to aprsString.queryLocal() .
bool StationLocal(const string& sp, int em)
{
bool retval = false;
Lock histLock(histMutex);
if ((pTail == NULL) || (pHead == NULL))
return retval; // Empty list
if (ItemCount == 0) // if no data then...
return retval; // ...return false
aprsString *hp = pTail; // point to end of history list
while ((!retval) && (hp != NULL)) { // Loop while no match and not at beginning of list
if (hp->EchoMask & em) {
if (hp->ax25Source.compare(sp) == 0) // Find the source call sign
retval = hp->queryLocal(); // then see if it's local
}
hp = hp->last;
}
return retval; // return true or false
}
//------------------------------------------------------------------------
/* Returns number of stations in history list defined as "Local" */
int localCount()
{
int localCounter = 0;
Lock histLock(histMutex);
if ((pTail == NULL) || (pHead == NULL))
return 0; //Empty list
if (ItemCount == 0) // if no data then...
return 0; // ...return zero
aprsString *hp = pTail; // point to end of history list
while (hp != NULL) { // Go through the whole list
if ( hp->queryLocal())
localCounter++; // Increment conter if local
hp = hp->last;
}
return localCounter; // return number of local staitons
}
//------------------------------------------------------------------------
//Returns a new aprsString of the posit packet whose ax25 source call
//matches the "call" arg and echomask bit matches a bit in "em".
//Memory allocated for the returned aprsString must be deleted by the caller.
aprsString* getPosit(const string& call, int em)
{
Lock histLock(histMutex); // create a semaphore object
if ((pTail == NULL) || (pHead == NULL))
return NULL ; // Empty list
aprsString* posit = NULL;
if (ItemCount == 0) // if no data then...
return NULL; // ...return NULL
aprsString *hp = pTail; // point to end of history list
while ((posit == NULL) && (hp != NULL)) { // Loop while no match and not at beginning of list
if (hp->EchoMask & em) {
if ((hp->ax25Source.compare(call) == 0) // Find the source call sign
&& ((hp->aprsType == APRSPOS)
|| hp->aprsType == NMEA)) { // of a posit packet
posit = new aprsString(*hp); // make a copy of the packet
}
}
hp = hp->last;
}
return posit;
}
//-------------------------------------------------------------------------
/* timestamp the timeRF variable in an aprsString object in the history list
given the objects serial number. Return true if object exists. */
bool timestamp(unsigned long sn, time_t t)
{
bool x = false;
Lock histLock(histMutex);
if ((pTail == NULL) || (pHead == NULL))
return false ; //Empty list
if (ItemCount == 0) //if no data then...
return false; // ...return false
aprsString *hp = pTail; //point to end of history list
while ((x == false) && (hp != NULL)) { //Loop while no match and not at beginning of list
if (hp->ID == sn) {
hp->timeRF = t; //time stamp it.
x = true; //indicate we did it.
}
hp = hp->last;
}
return x;
}
//--------------------------------------------------------------------------
/* Deletes the history array and it's data created above */
void deleteHistoryArray(histRec* hr)
{
int i;
if (hr) {
int arraySize = hr[0].count;
for (i = 0;itimestamp;
hr[i].EchoMask = hp->EchoMask;
hr[i].type = hp->aprsType;
hr[i].reformatted = hp->reformatted;
hr[i].data = strdup(hp->getChar()); //Allocate memory and copy data
if (hr[i].data == NULL) {
deleteHistoryArray(hr); //Abort if malloc fails
return NULL;
}
if (hp->next == NULL)
break;
hp = hp->next;
}
return hr;
}
//--------------------------------------------------------------------------
//Send the history items to the user when he connects
//returns number of history items sent or -1 if an error in sending occured
int SendHistory(int session, int em)
{
int rc,count, i=0;
int retrys;
timespec ts;
Lock histLock(histMutex, false);
if (pHead == NULL)
return 0; //Nothing to send
histLock.get();
aprsString *hp = pHead; //Start at the beginning of list
histRec* hr = createHistoryArray(hp); //copy it to an array
histLock.release();
if (hr == NULL)
return 0;
int n = hr[0].count; // n has total number of items
count = 0;
//float throttle = 32; //Initial rate about 250kbaud (1/baud * 8 * 1e6)
/* New smart rate throttle for history dump */
float maxspeed = 1e6/(MaxLoad - serverLoad); //This much BW remaining...
if (maxspeed > 833)
maxspeed = 833; // No slower than 9600 baud
if (maxspeed < 32)
maxspeed = 32; // No faster than 250k baud.
float throttle = maxspeed; //Initial rate is MaxLoad - serverLoad bytes/sec
for (i = 0; i < n; i++) {
if ((hr[i].EchoMask & em) && (hr[i].reformatted == false)) {
//filter data intended for this users port
count++; //Count how many items we actually send
size_t dlen = strlen(hr[i].data);
retrys = 0;
do {
rc = send(session, (const void*)hr[i].data, dlen, 0); //Send history list item to client
ts.tv_sec = 0;
ts.tv_nsec = (int)throttle * dlen * 1000; //Delay time in nano seconds
nanosleep(&ts, NULL); //pace ourself
if (rc < 0) {
ts.tv_sec = 1;
ts.tv_nsec = 0;
nanosleep(&ts, NULL); //Pause output 1 second if resource unavailable
if (retrys == 0) {
throttle = throttle * 2;
} //cut our speed in half
if (throttle > 833)
throttle = 833; //Don't go slower than 9600 baud
retrys++;
} else
if (throttle > maxspeed)
throttle = throttle * 0.98; //Speed up 2%
} while ((errno == EAGAIN) && (rc < 0) && ( retrys <= 180)); //Keep trying for 3 minutes
if (rc < 0) {
cerr << "send() error in SendHistory() errno= " << errno << " retrys= " << retrys
<< " \n[" << strerror(errno) << "]" << endl;
deleteHistoryArray(hr);
histLock.get();
dumpAborts++;
histLock.release();
return -1;
}
}
}
deleteHistoryArray(hr);
return count;
}
//---------------------------------------------------------------------
//Save history list to disk
int SaveHistory(const string& name)
{
int icount = 0;
Lock histLock(histMutex);
if (pHead == NULL)
return icount;
ofstream hf(name.c_str()); // Open the output file
if (hf.good()) { //if no open errors go ahead and write data
aprsString *hp = pHead;
for (;;) {
if (hp->EchoMask){ //Save only items which have a bit set in EchoMask
hf << hp->ttl << " "
<< hp->timestamp << " "
<< hp->EchoMask << " "
<< hp->aprsType << " "
<< hp->getChar() ; //write to file
if (!hf.good()) {
cerr << "Error writing " << SAVE_HISTORY << endl;
break;
}
icount++;
}
if (hp->next == NULL)
break;
hp = hp->next; //go to next item in list
}
hf.close();
}
return icount;
}
//---------------------------------------------------------------------
int ReadHistory(const string& name)
{
int icount = 0;
int expiredCount = 0;
int ttl,EchoMask,aprsType;
char *data = new char[256];
time_t now,timestamp;
ifstream hf(name.c_str()); // Create ifstream instance "hf" and open the input file
if (hf.good()) { //if no open errors go ahead and read data
now = time(NULL);
while (hf.good() ) {
hf >> ttl >> timestamp >> EchoMask >> aprsType;
hf.get(); // skip 1 space
hf.get(data, 252, '\r'); // read the rest of the line as a char string
int i = strlen(data);
data[i++] = '\r';
data[i++] = '\n';
data[i++] = '\0';
aprsString *hist = new aprsString(data);
hist->EchoMask = EchoMask;
hist->timestamp = timestamp;
ttl = ttl - ((now - timestamp) / 60); //Adjust timep-to-live field
if (ttl < 0)
ttl = 0;
hist->ttl = ttl;
hist->aprsType = aprsType;
//Now add to list only items which have NOT expired
if (ttl > 0) {
AddHistoryItem(hist);
icount++;
} else {
delete hist;
expiredCount++;
}
}
hf.close();
}
delete data;
cout << "Read " << icount+expiredCount << " items from "
<< name << endl;
if (expiredCount)
cout << "Ignored " << expiredCount
<< " expired items in "
<< name << endl;
return icount;
}
//-------------------------------------------------------------------------------------
aprsd-2.2.5-13/src/history.h 0000664 0000764 0000764 00000003306 07655343023 011217 /*
* $Id: history.h,v 1.6 2003/03/31 04:49:40 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#ifndef HISTORY_H
#define HISTORY_H
#include "aprsString.h"
extern int dumpAborts; //Number of history dumps aborted
extern int ItemCount; //number of items in History list
void CreateHistoryList();
bool AddHistoryItem(aprsd::aprsString *hp);
void DeleteHistoryItem(aprsd::aprsString *hp);
int DeleteOldItems(int x);
int DeleteItem(aprsd::aprsString* ref);
bool DupCheck(aprsd::aprsString* ref, time_t t);
int SendHistory(int session,int em);
int SaveHistory(const std::string& name);
int ReadHistory(const std::string& name);
bool StationLocal(const std::string& sp, int em);
aprsd::aprsString* getPosit(const std::string& call, int em);
bool timestamp(unsigned long sn, time_t t);
int localCount();
#endif // HISTORY_H
aprsd-2.2.5-13/src/httpserver.cpp 0000644 0000764 0000764 00000060652 07657351712 012272 /*
* $Id: httpserver.cpp,v 1.5 2003/05/11 04:38:34 kg4ijb Exp $
*
* aprsd, Automatic Packet Reporting System Daemon
* Copyright (C) 1997,2002 Dale A. Heatherington, WA4DSY
* Copyright (C) 2001-2002 aprsd Dev Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Look at the README for more information on the program.
*/
#include
#include // send()
#include // send()
#include // close()
#include
#include
#include
#include
#include "osdep.h"
#include "servers.h"
#include "mutex.h"
#include "dupCheck.h"
#include "cpqueue.h"
#include "utils.h"
#include "constant.h"
#include "history.h"
#include "serial.h"
#include "aprsString.h"
#include "validate.h"
#include "queryResp.h"
#include "aprsdexception.h"
using namespace aprsd;
typedef std::list