diff --git a/IRCApplication.h b/IRCApplication.h index 4089ab9..ee2194d 100644 --- a/IRCApplication.h +++ b/IRCApplication.h @@ -28,25 +28,25 @@ along with this program. If not, see . class IRCApplication { - public: - - virtual void userJoin (const wxString& nick, const wxString& name, const wxString& host) = 0; - virtual void userLeave (const wxString& nick) = 0; - virtual void userChanOp (const wxString& nick, bool op) = 0; - virtual void userListReset(void) = 0; - - virtual void msgChannel (IRCMessage * m) = 0; - virtual void msgQuery (IRCMessage * m) = 0; - - virtual void setCurrentNick(const wxString& nick) = 0; - virtual void setTopic(const wxString& topic) = 0; - - virtual void setBestServer(const wxString& ircUser) = 0; - - virtual void setSendQ( IRCMessageQueue * s ) = 0; - virtual IRCMessageQueue * getSendQ (void) = 0; - - virtual ~IRCApplication() {} +public: + + virtual void userJoin (const wxString& nick, const wxString& name, const wxString& host) = 0; + virtual void userLeave (const wxString& nick) = 0; + virtual void userChanOp (const wxString& nick, bool op) = 0; + virtual void userListReset(void) = 0; + + virtual void msgChannel (IRCMessage * m) = 0; + virtual void msgQuery (IRCMessage * m) = 0; + + virtual void setCurrentNick(const wxString& nick) = 0; + virtual void setTopic(const wxString& topic) = 0; + + virtual void setBestServer(const wxString& ircUser) = 0; + + virtual void setSendQ( IRCMessageQueue * s ) = 0; + virtual IRCMessageQueue * getSendQ (void) = 0; + + virtual ~IRCApplication() {} }; diff --git a/IRCClient.cpp b/IRCClient.cpp index 4e00e88..15013c3 100644 --- a/IRCClient.cpp +++ b/IRCClient.cpp @@ -52,458 +52,395 @@ along with this program. If not, see . IRCClient::IRCClient( IRCApplication * app, const wxString& update_channel, - const wxString& hostName, unsigned int port, const wxString& callsign, const wxString& password, - const wxString& versionInfo, const wxString& localAddr ) - : wxThread(wxTHREAD_JOINABLE) + const wxString& hostName, unsigned int port, const wxString& callsign, const wxString& password, + const wxString& versionInfo, const wxString& localAddr ) + : wxThread(wxTHREAD_JOINABLE) { - safeStringCopy(host_name, hostName.mb_str(), sizeof host_name); + safeStringCopy(host_name, hostName.mb_str(), sizeof host_name); - this -> callsign = callsign.Lower(); - this -> port = port; - this -> password = password; + this -> callsign = callsign.Lower(); + this -> port = port; + this -> password = password; - this -> app = app; - - if (localAddr.IsEmpty()) - { - safeStringCopy(local_addr, "0.0.0.0", sizeof local_addr); - } - else - { - safeStringCopy(local_addr, localAddr.mb_str(), sizeof local_addr); - } + this -> app = app; - proto = new IRCProtocol ( app, this->callsign, password, update_channel, versionInfo ); + if (localAddr.IsEmpty()) { + safeStringCopy(local_addr, "0.0.0.0", sizeof local_addr); + } else { + safeStringCopy(local_addr, localAddr.mb_str(), sizeof local_addr); + } + + proto = new IRCProtocol ( app, this->callsign, password, update_channel, versionInfo ); - recvQ = NULL; - sendQ = NULL; + recvQ = NULL; + sendQ = NULL; - recv = NULL; + recv = NULL; } IRCClient::~IRCClient() { - delete proto; + delete proto; } bool IRCClient::startWork() { - if (Create() != wxTHREAD_NO_ERROR) - { - wxLogError(wxT("IRCClient::startWork: Could not create the worker thread!")); - return false; - } + if (Create() != wxTHREAD_NO_ERROR) { + wxLogError(wxT("IRCClient::startWork: Could not create the worker thread!")); + return false; + } - terminateThread = false; + terminateThread = false; - if (Run() != wxTHREAD_NO_ERROR) - { - wxLogError(wxT("IRCClient::startWork: Could not run the worker thread!")); - return false; - } + if (Run() != wxTHREAD_NO_ERROR) { + wxLogError(wxT("IRCClient::startWork: Could not run the worker thread!")); + return false; + } - return true; + return true; } void IRCClient::stopWork() { - terminateThread = true; + terminateThread = true; - Wait(); + Wait(); } wxThread::ExitCode IRCClient::Entry () { - unsigned int numAddr; + unsigned int numAddr; #define MAXIPV4ADDR 10 - struct sockaddr_in addr[MAXIPV4ADDR]; - - struct sockaddr_in myaddr; + struct sockaddr_in addr[MAXIPV4ADDR]; - int state = 0; - int timer = 0; - int sock = 0; - unsigned int currentAddr = 0; + struct sockaddr_in myaddr; - int result; + int state = 0; + int timer = 0; + int sock = 0; + unsigned int currentAddr = 0; + int result; - numAddr = 0; - result = getAllIPV4Addresses(local_addr, 0, &numAddr, &myaddr, 1); + numAddr = 0; - if ((result != 0) || (numAddr != 1)) - { - wxLogVerbose(wxT("IRCClient::Entry: local address not parseable, using 0.0.0.0")); - memset(&myaddr, 0x00, sizeof(struct sockaddr_in)); - } + result = getAllIPV4Addresses(local_addr, 0, &numAddr, &myaddr, 1); - while (true) - { + if ((result != 0) || (numAddr != 1)) { + wxLogVerbose(wxT("IRCClient::Entry: local address not parseable, using 0.0.0.0")); + memset(&myaddr, 0x00, sizeof(struct sockaddr_in)); + } - if (timer > 0) - { - timer --; - } + while (true) { - switch (state) - { - case 0: - if (terminateThread) - { - wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state); - return 0; - } - - if (timer == 0) - { - timer = 30; - - if (getAllIPV4Addresses(host_name, port, &numAddr, addr, MAXIPV4ADDR) == 0) - { - wxLogVerbose(wxT("IRCClient::Entry: number of DNS entries %d"), numAddr); - if (numAddr > 0) - { - currentAddr = 0; - state = 1; - timer = 0; - } - } - } - break; + if (timer > 0) { + timer --; + } - case 1: - if (terminateThread) - { - wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state); - return 0; - } - - if (timer == 0) - { - sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP); - - if (sock < 0) - { - wxLogSysError(wxT("IRCClient::Entry: socket")); - timer = 30; - state = 0; - } - else - { + switch (state) { + case 0: + if (terminateThread) { + wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state); + return 0; + } + + if (timer == 0) { + timer = 30; + + if (getAllIPV4Addresses(host_name, port, &numAddr, addr, MAXIPV4ADDR) == 0) { + wxLogVerbose(wxT("IRCClient::Entry: number of DNS entries %d"), numAddr); + if (numAddr > 0) { + currentAddr = 0; + state = 1; + timer = 0; + } + } + } + break; + + case 1: + if (terminateThread) { + wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state); + return 0; + } + + if (timer == 0) { + sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (sock < 0) { + wxLogSysError(wxT("IRCClient::Entry: socket")); + timer = 30; + state = 0; + } else { #if defined(__WINDOWS__) - u_long nonBlock = 1UL; - if (ioctlsocket( sock, FIONBIO, &nonBlock ) != 0) - { - wxLogSysError(wxT("IRCClient::Entry: ioctlsocket")); - closesocket(sock); - timer = 30; - state = 0; - } + u_long nonBlock = 1UL; + if (ioctlsocket( sock, FIONBIO, &nonBlock ) != 0) { + wxLogSysError(wxT("IRCClient::Entry: ioctlsocket")); + closesocket(sock); + timer = 30; + state = 0; + } #else - if (fcntl( sock, F_SETFL, O_NONBLOCK ) < 0) - { - wxLogSysError(wxT("IRCClient::Entry: fcntl")); - close(sock); - timer = 30; - state = 0; - } + if (fcntl( sock, F_SETFL, O_NONBLOCK ) < 0) { + wxLogSysError(wxT("IRCClient::Entry: fcntl")); + close(sock); + timer = 30; + state = 0; + } #endif - else - { - unsigned char * h = (unsigned char *) &(myaddr.sin_addr); - int res; + else { + unsigned char * h = (unsigned char *) &(myaddr.sin_addr); + int res; - if ((h[0] != 0) || (h[1] != 0) || (h[2] != 0) || (h[3] != 0)) - { - wxLogVerbose(wxT("IRCClient::Entry: bind: local address %d.%d.%d.%d"), - h[0], h[1], h[2], h[3]); - } + if ((h[0] != 0) || (h[1] != 0) || (h[2] != 0) || (h[3] != 0)) { + wxLogVerbose(wxT("IRCClient::Entry: bind: local address %d.%d.%d.%d"), + h[0], h[1], h[2], h[3]); + } - res = bind(sock, (struct sockaddr *) &myaddr, sizeof (struct sockaddr_in)); + res = bind(sock, (struct sockaddr *) &myaddr, sizeof (struct sockaddr_in)); - if (res != 0) - { + if (res != 0) { - wxLogSysError(wxT("IRCClient::Entry: bind")); + wxLogSysError(wxT("IRCClient::Entry: bind")); #if defined(__WINDOWS__) - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif - state = 0; - timer = 30; - break; - } - - - h = (unsigned char *) &(addr[currentAddr].sin_addr); - wxLogVerbose(wxT("IRCClient::Entry: trying to connect to %d.%d.%d.%d"), - h[0], h[1], h[2], h[3]); - - res = connect(sock, (struct sockaddr *) (addr + currentAddr), sizeof (struct sockaddr_in)); - - if (res == 0) - { - wxLogVerbose(wxT("IRCClient::Entry: connected")); - state = 4; - } - else - { + state = 0; + timer = 30; + break; + } + + + h = (unsigned char *) &(addr[currentAddr].sin_addr); + wxLogVerbose(wxT("IRCClient::Entry: trying to connect to %d.%d.%d.%d"), + h[0], h[1], h[2], h[3]); + + res = connect(sock, (struct sockaddr *) (addr + currentAddr), sizeof (struct sockaddr_in)); + + if (res == 0) { + wxLogVerbose(wxT("IRCClient::Entry: connected")); + state = 4; + } else { #if defined(__WINDOWS__) - if (WSAGetLastError() == WSAEWOULDBLOCK) + if (WSAGetLastError() == WSAEWOULDBLOCK) #else - if (errno == EINPROGRESS) + if (errno == EINPROGRESS) #endif - { - wxLogVerbose(wxT("IRCClient::Entry: connect in progress")); - state = 3; - timer = 10; // 5 second timeout - } - else - { - wxLogSysError(wxT("IRCClient::Entry: connect")); + { + wxLogVerbose(wxT("IRCClient::Entry: connect in progress")); + state = 3; + timer = 10; // 5 second timeout + } else { + wxLogSysError(wxT("IRCClient::Entry: connect")); #if defined(__WINDOWS__) - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif - currentAddr ++; - if (currentAddr >= numAddr) - { - state = 0; - timer = 30; - } - else - { - state = 1; - timer = 4; - } - } - } - } // connect - } - } - break; - - case 3: - { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - fd_set myset; - FD_ZERO(&myset); - FD_SET(sock, &myset); - int res; - res = select(sock+1, NULL, &myset, NULL, &tv); - - if (res < 0) - { - wxLogSysError(wxT("IRCClient::Entry: select")); + currentAddr ++; + if (currentAddr >= numAddr) { + state = 0; + timer = 30; + } else { + state = 1; + timer = 4; + } + } + } + } // connect + } + } + break; + + case 3: { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + fd_set myset; + FD_ZERO(&myset); + FD_SET(sock, &myset); + int res; + res = select(sock+1, NULL, &myset, NULL, &tv); + + if (res < 0) { + wxLogSysError(wxT("IRCClient::Entry: select")); #if defined(__WINDOWS__) - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif - state = 0; - timer = 30; - } - else if (res > 0) // connect is finished - { + state = 0; + timer = 30; + } else if (res > 0) { // connect is finished #if defined(__WINDOWS__) - int val_len; + int val_len; #else - socklen_t val_len; + socklen_t val_len; #endif - int value; + int value; - val_len = sizeof value; + val_len = sizeof value; - if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *) &value, &val_len) < 0) - { - wxLogSysError(wxT("IRCClient::Entry: getsockopt")); + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *) &value, &val_len) < 0) { + wxLogSysError(wxT("IRCClient::Entry: getsockopt")); #if defined(__WINDOWS__) - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif - state = 0; - timer = 30; - } - else - { - if (value != 0) - { - wxLogWarning(wxT("IRCClient::Entry: SO_ERROR=%d"), value); + state = 0; + timer = 30; + } else { + if (value != 0) { + wxLogWarning(wxT("IRCClient::Entry: SO_ERROR=%d"), value); #if defined(__WINDOWS__) - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif - currentAddr ++; - if (currentAddr >= numAddr) - { - state = 0; - timer = 30; - } - else - { - state = 1; - timer = 2; - } - } - else - { - wxLogVerbose(wxT("IRCClient::Entry: connected2")); - state = 4; - } - } - - } - else if (timer == 0) - { // select timeout and timer timeout - wxLogVerbose(wxT("IRCClient::Entry: connect timeout")); + currentAddr ++; + if (currentAddr >= numAddr) { + state = 0; + timer = 30; + } else { + state = 1; + timer = 2; + } + } else { + wxLogVerbose(wxT("IRCClient::Entry: connected2")); + state = 4; + } + } + + } else if (timer == 0) { + // select timeout and timer timeout + wxLogVerbose(wxT("IRCClient::Entry: connect timeout")); #if defined(__WINDOWS__) - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif - currentAddr ++; - if (currentAddr >= numAddr) - { - state = 0; - timer = 30; - } - else - { - state = 1; // open new socket - timer = 2; - } - } + currentAddr ++; + if (currentAddr >= numAddr) { + state = 0; + timer = 30; + } else { + state = 1; // open new socket + timer = 2; + } + } - } - break; + } + break; - case 4: - { - recvQ = new IRCMessageQueue(); - sendQ = new IRCMessageQueue(); + case 4: { + recvQ = new IRCMessageQueue(); + sendQ = new IRCMessageQueue(); - recv = new IRCReceiver(sock, recvQ); - recv->startWork(); + recv = new IRCReceiver(sock, recvQ); + recv->startWork(); - proto->setNetworkReady(true); - state = 5; - timer = 0; + proto->setNetworkReady(true); + state = 5; + timer = 0; - } - break; + } + break; - case 5: - if (terminateThread) - { - state = 6; - } - else - { + case 5: + if (terminateThread) { + state = 6; + } else { - if (recvQ -> isEOF()) - { - timer = 0; - state = 6; - } - else if (proto -> processQueues(recvQ, sendQ) == false) - { - timer = 0; - state = 6; - } + if (recvQ -> isEOF()) { + timer = 0; + state = 6; + } else if (proto -> processQueues(recvQ, sendQ) == false) { + timer = 0; + state = 6; + } - while ((state == 5) && sendQ->messageAvailable()) - { - IRCMessage * m = sendQ -> getMessage(); + while ((state == 5) && sendQ->messageAvailable()) { + IRCMessage * m = sendQ -> getMessage(); - wxString out; + wxString out; - m -> composeMessage ( out ); + m -> composeMessage ( out ); - char buf[200]; - safeStringCopy(buf, out.mb_str(wxConvUTF8), sizeof buf); - int len = strlen(buf); + char buf[200]; + safeStringCopy(buf, out.mb_str(wxConvUTF8), sizeof buf); + int len = strlen(buf); - if (buf[len - 1] == 10) // is there a NL char at the end? - { - int r = send(sock, buf, len, 0); + if (buf[len - 1] == 10) { // is there a NL char at the end? + int r = send(sock, buf, len, 0); - if (r != len) - { - wxLogVerbose(wxT("IRCClient::Entry: short write %d < %d"), r, len); + if (r != len) { + wxLogVerbose(wxT("IRCClient::Entry: short write %d < %d"), r, len); - timer = 0; - state = 6; - } -/* else - { - wxLogVerbose(wxT("write %d bytes (") + out + wxT(")"), len ); - } */ - } - else - { - wxLogVerbose(wxT("IRCClient::Entry: no NL at end, len=%d"), len); + timer = 0; + state = 6; + } + /* else + { + wxLogVerbose(wxT("write %d bytes (") + out + wxT(")"), len ); + } */ + } else { + wxLogVerbose(wxT("IRCClient::Entry: no NL at end, len=%d"), len); - timer = 0; - state = 6; - } + timer = 0; + state = 6; + } - delete m; - } - } - break; - - case 6: - { - if (app != NULL) - { - app->setSendQ(NULL); - app->userListReset(); - } + delete m; + } + } + break; + + case 6: { + if (app != NULL) { + app->setSendQ(NULL); + app->userListReset(); + } - proto->setNetworkReady(false); - recv->stopWork(); + proto->setNetworkReady(false); + recv->stopWork(); - wxThread::Sleep(2000); + wxThread::Sleep(2000); - delete recv; - delete recvQ; - delete sendQ; + delete recv; + delete recvQ; + delete sendQ; #if defined(__WINDOWS__) - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif - if (terminateThread) // request to end the thread - { - wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state); - return 0; - } + if (terminateThread) { // request to end the thread + wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state); + return 0; + } - timer = 30; - state = 0; // reconnect to IRC server - } - break; + timer = 30; + state = 0; // reconnect to IRC server + } + break; - } + } - wxThread::Sleep(500); + wxThread::Sleep(500); - } + } - return 0; + return 0; } diff --git a/IRCClient.h b/IRCClient.h index c8d215c..0738404 100644 --- a/IRCClient.h +++ b/IRCClient.h @@ -33,44 +33,44 @@ along with this program. If not, see . class IRCClient : public wxThread { - public: +public: - IRCClient( IRCApplication * app, const wxString& update_channel, - const wxString& hostName, unsigned int port, const wxString& callsign, const wxString& password, - const wxString& versionInfo, const wxString& localAddr ); + IRCClient( IRCApplication * app, const wxString& update_channel, + const wxString& hostName, unsigned int port, const wxString& callsign, const wxString& password, + const wxString& versionInfo, const wxString& localAddr ); - ~IRCClient(); + ~IRCClient(); - bool startWork(); + bool startWork(); - void stopWork(); + void stopWork(); - protected: +protected: - virtual wxThread::ExitCode Entry(); + virtual wxThread::ExitCode Entry(); - private: +private: - char host_name[100]; - char local_addr[100]; - unsigned int port; - wxString callsign; - wxString password; + char host_name[100]; + char local_addr[100]; + unsigned int port; + wxString callsign; + wxString password; - bool terminateThread; + bool terminateThread; - IRCReceiver * recv; - IRCMessageQueue * recvQ; - IRCMessageQueue * sendQ; - IRCProtocol * proto; + IRCReceiver * recv; + IRCMessageQueue * recvQ; + IRCMessageQueue * sendQ; + IRCProtocol * proto; - IRCApplication * app; + IRCApplication * app; }; -#endif +#endif diff --git a/IRCDDB.cpp b/IRCDDB.cpp index 45ef3ed..4246362 100644 --- a/IRCDDB.cpp +++ b/IRCDDB.cpp @@ -28,269 +28,237 @@ along with this program. If not, see . #include -struct CIRCDDBPrivate -{ - IRCClient * client; - IRCDDBApp * app; +struct CIRCDDBPrivate { + IRCClient * client; + IRCDDBApp * app; }; CIRCDDB::CIRCDDB(const wxString& hostName, unsigned int port, - const wxString& callsign, const wxString& password, - const wxString& versionInfo, const wxString& localAddr ) : d( new CIRCDDBPrivate ) + const wxString& callsign, const wxString& password, + const wxString& versionInfo, const wxString& localAddr ) : d( new CIRCDDBPrivate ) { - wxString update_channel = wxT("#dstar"); + wxString update_channel = wxT("#dstar"); - d->app = new IRCDDBApp(update_channel); + d->app = new IRCDDBApp(update_channel); - d->client = new IRCClient( d->app, update_channel, hostName, port, callsign, - password, versionInfo, localAddr ); + d->client = new IRCClient( d->app, update_channel, hostName, port, callsign, + password, versionInfo, localAddr ); } CIRCDDB::~CIRCDDB() { - delete d->client; - delete d->app; - delete d; + delete d->client; + delete d->app; + delete d; } - // A false return implies a network error, or unable to log in +// A false return implies a network error, or unable to log in bool CIRCDDB::open() { - wxLogVerbose(wxT("start")); - return d->client -> startWork() && d->app->startWork(); + wxLogVerbose(wxT("start")); + return d->client -> startWork() && d->app->startWork(); } int CIRCDDB::getConnectionState() { - return d->app->getConnectionState(); + return d->app->getConnectionState(); } void CIRCDDB::rptrQTH( double latitude, double longitude, const wxString& desc1, - const wxString& desc2, const wxString& infoURL ) + const wxString& desc2, const wxString& infoURL ) { - d->app->rptrQTH(latitude, longitude, desc1, desc2, infoURL); + d->app->rptrQTH(latitude, longitude, desc1, desc2, infoURL); } void CIRCDDB::rptrQRG( const wxString& module, double txFrequency, double duplexShift, - double range, double agl ) + double range, double agl ) { - d->app->rptrQRG(module, txFrequency, duplexShift, range, agl); + d->app->rptrQRG(module, txFrequency, duplexShift, range, agl); } void CIRCDDB::kickWatchdog ( const wxString& wdInfo ) { - d->app->kickWatchdog( wdInfo ); + d->app->kickWatchdog( wdInfo ); } // Send heard data, a false return implies a network error bool CIRCDDB::sendHeard( const wxString& myCall, const wxString& myCallExt, - const wxString& yourCall, const wxString& rpt1, - const wxString& rpt2, unsigned char flag1, - unsigned char flag2, unsigned char flag3 ) + const wxString& yourCall, const wxString& rpt1, + const wxString& rpt2, unsigned char flag1, + unsigned char flag2, unsigned char flag3 ) { - if (myCall.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:myCall: len != 8")); - return false; - } - - if (myCallExt.Len() != 4) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:myCallExt: len != 4")); - return false; - } - - if (yourCall.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:yourCall: len != 8")); - return false; - } - - if (rpt1.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt1: len != 8")); - return false; - } - - if (rpt2.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt2: len != 8")); - return false; - } - - return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, - wxT(" "), wxT(""), wxT("")); + if (myCall.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:myCall: len != 8")); + return false; + } + + if (myCallExt.Len() != 4) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:myCallExt: len != 4")); + return false; + } + + if (yourCall.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:yourCall: len != 8")); + return false; + } + + if (rpt1.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt1: len != 8")); + return false; + } + + if (rpt2.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt2: len != 8")); + return false; + } + + return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, + wxT(" "), wxT(""), wxT("")); } // Send heard data, a false return implies a network error bool CIRCDDB::sendHeardWithTXMsg( const wxString& myCall, const wxString& myCallExt, - const wxString& yourCall, const wxString& rpt1, - const wxString& rpt2, unsigned char flag1, - unsigned char flag2, unsigned char flag3, - const wxString& network_destination, - const wxString& tx_message ) + const wxString& yourCall, const wxString& rpt1, + const wxString& rpt2, unsigned char flag1, + unsigned char flag2, unsigned char flag3, + const wxString& network_destination, + const wxString& tx_message ) { - if (myCall.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:myCall: len != 8")); - return false; - } - - if (myCallExt.Len() != 4) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:myCallExt: len != 4")); - return false; - } - - if (yourCall.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:yourCall: len != 8")); - return false; - } - - if (rpt1.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt1: len != 8")); - return false; - } - - if (rpt2.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt2: len != 8")); - return false; - } - - wxString dest = network_destination; - - if (dest.Len() == 0) - { - dest = wxT(" "); - } - - if (dest.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:network_destination: len != 8")); - return false; - } - - wxString msg; - - if (tx_message.Len() == 20) - { - unsigned int i; - for (i=0; i < tx_message.Len(); i++) - { - wxChar ch = tx_message.GetChar(i); - - if ((ch > 32) && (ch < 127)) - { - msg.Append(ch); - } - else - { - msg.Append(wxT('_')); - } - } - } - - return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, - dest, msg, wxT("")); + if (myCall.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:myCall: len != 8")); + return false; + } + + if (myCallExt.Len() != 4) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:myCallExt: len != 4")); + return false; + } + + if (yourCall.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:yourCall: len != 8")); + return false; + } + + if (rpt1.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt1: len != 8")); + return false; + } + + if (rpt2.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt2: len != 8")); + return false; + } + + wxString dest = network_destination; + + if (dest.Len() == 0) { + dest = wxT(" "); + } + + if (dest.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:network_destination: len != 8")); + return false; + } + + wxString msg; + + if (tx_message.Len() == 20) { + unsigned int i; + for (i=0; i < tx_message.Len(); i++) { + wxChar ch = tx_message.GetChar(i); + + if ((ch > 32) && (ch < 127)) { + msg.Append(ch); + } else { + msg.Append(wxT('_')); + } + } + } + + return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, + dest, msg, wxT("")); } bool CIRCDDB::sendHeardWithTXStats( const wxString& myCall, const wxString& myCallExt, - const wxString& yourCall, const wxString& rpt1, - const wxString& rpt2, unsigned char flag1, - unsigned char flag2, unsigned char flag3, - int num_dv_frames, - int num_dv_silent_frames, - int num_bit_errors ) + const wxString& yourCall, const wxString& rpt1, + const wxString& rpt2, unsigned char flag1, + unsigned char flag2, unsigned char flag3, + int num_dv_frames, + int num_dv_silent_frames, + int num_bit_errors ) { - if ((num_dv_frames <= 0) || (num_dv_frames > 65535)) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:num_dv_frames not in range 1-65535")); - return false; - } - - if (num_dv_silent_frames > num_dv_frames) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:num_dv_silent_frames > num_dv_frames")); - return false; - } - - if (num_bit_errors > (4*num_dv_frames)) // max 4 bit errors per frame - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:num_bit_errors > (4*num_dv_frames)")); - return false; - } - - if (myCall.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:myCall: len != 8")); - return false; - } - - if (myCallExt.Len() != 4) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:myCallExt: len != 4")); - return false; - } - - if (yourCall.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:yourCall: len != 8")); - return false; - } - - if (rpt1.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt1: len != 8")); - return false; - } - - if (rpt2.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt2: len != 8")); - return false; - } - - wxString stats = wxString::Format(wxT("%04x"), num_dv_frames); - - if (num_dv_silent_frames >= 0) - { - wxString s = wxString::Format(wxT("%02x"), (num_dv_silent_frames * 100) / num_dv_frames); - stats.Append(s); - - if (num_bit_errors >= 0) - { - s = wxString::Format(wxT("%02x"), (num_bit_errors * 125) / (num_dv_frames * 3)); - stats.Append(s); - } - else - { - stats.Append(wxT("__")); - } - } - else - { - stats.Append(wxT("____")); - } - - stats.Append(wxT("____________")); // stats string should have 20 chars - - return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, - wxT(" "), wxT(""), stats); + if ((num_dv_frames <= 0) || (num_dv_frames > 65535)) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:num_dv_frames not in range 1-65535")); + return false; + } + + if (num_dv_silent_frames > num_dv_frames) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:num_dv_silent_frames > num_dv_frames")); + return false; + } + + if (num_bit_errors > (4*num_dv_frames)) { // max 4 bit errors per frame + wxLogVerbose(wxT("CIRCDDB::sendHeard:num_bit_errors > (4*num_dv_frames)")); + return false; + } + + if (myCall.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:myCall: len != 8")); + return false; + } + + if (myCallExt.Len() != 4) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:myCallExt: len != 4")); + return false; + } + + if (yourCall.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:yourCall: len != 8")); + return false; + } + + if (rpt1.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt1: len != 8")); + return false; + } + + if (rpt2.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt2: len != 8")); + return false; + } + + wxString stats = wxString::Format(wxT("%04x"), num_dv_frames); + + if (num_dv_silent_frames >= 0) { + wxString s = wxString::Format(wxT("%02x"), (num_dv_silent_frames * 100) / num_dv_frames); + stats.Append(s); + + if (num_bit_errors >= 0) { + s = wxString::Format(wxT("%02x"), (num_bit_errors * 125) / (num_dv_frames * 3)); + stats.Append(s); + } else { + stats.Append(wxT("__")); + } + } else { + stats.Append(wxT("____")); + } + + stats.Append(wxT("____________")); // stats string should have 20 chars + + return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, + wxT(" "), wxT(""), stats); } @@ -298,37 +266,34 @@ bool CIRCDDB::sendHeardWithTXStats( const wxString& myCall, const wxString& myCa // Send query for a gateway/reflector, a false return implies a network error bool CIRCDDB::findGateway(const wxString& gatewayCallsign) { - if (gatewayCallsign.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::findGateway: len != 8")); - return false; - } + if (gatewayCallsign.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::findGateway: len != 8")); + return false; + } - return d->app->findGateway( gatewayCallsign.Upper()); + return d->app->findGateway( gatewayCallsign.Upper()); } bool CIRCDDB::findRepeater(const wxString& repeaterCallsign) { - if (repeaterCallsign.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::findRepeater: len != 8")); - return false; - } + if (repeaterCallsign.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::findRepeater: len != 8")); + return false; + } - return d->app->findRepeater( repeaterCallsign.Upper()); + return d->app->findRepeater( repeaterCallsign.Upper()); } // Send query for a user, a false return implies a network error bool CIRCDDB::findUser(const wxString& userCallsign) { - if (userCallsign.Len() != 8) - { - wxLogVerbose(wxT("CIRCDDB::findUser: len != 8")); - return false; - } + if (userCallsign.Len() != 8) { + wxLogVerbose(wxT("CIRCDDB::findUser: len != 8")); + return false; + } - return d->app->findUser( userCallsign.Upper()); + return d->app->findUser( userCallsign.Upper()); } // The following functions are for processing received messages @@ -336,143 +301,131 @@ bool CIRCDDB::findUser(const wxString& userCallsign) // Get the waiting message type IRCDDB_RESPONSE_TYPE CIRCDDB::getMessageType() { - return d->app->getReplyMessageType(); + return d->app->getReplyMessageType(); } // Get a gateway message, as a result of IDRT_REPEATER returned from getMessageType() // A false return implies a network error -bool CIRCDDB::receiveRepeater(wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address, DSTAR_PROTOCOL& protocol) +bool CIRCDDB::receiveRepeater(wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address, DSTAR_PROTOCOL& /*protocol*/) { - IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); + IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); - if (rt != IDRT_REPEATER) - { - wxLogError(wxT("CIRCDDB::receiveRepeater: unexpected response type")); - return false; - } + if (rt != IDRT_REPEATER) { + wxLogError(wxT("CIRCDDB::receiveRepeater: unexpected response type")); + return false; + } - IRCMessage * m = d->app->getReplyMessage(); + IRCMessage * m = d->app->getReplyMessage(); - if (m == NULL) - { - wxLogError(wxT("CIRCDDB::receiveRepeater: no message")); - return false; - } + if (m == NULL) { + wxLogError(wxT("CIRCDDB::receiveRepeater: no message")); + return false; + } - if (!m->getCommand().IsSameAs(wxT("IDRT_REPEATER"))) - { - wxLogError(wxT("CIRCDDB::receiveRepeater: wrong message type")); - return false; - } + if (!m->getCommand().IsSameAs(wxT("IDRT_REPEATER"))) { + wxLogError(wxT("CIRCDDB::receiveRepeater: wrong message type")); + return false; + } - if (m->getParamCount() != 3) - { - wxLogError(wxT("CIRCDDB::receiveRepeater: unexpected number of message parameters")); - return false; - } + if (m->getParamCount() != 3) { + wxLogError(wxT("CIRCDDB::receiveRepeater: unexpected number of message parameters")); + return false; + } - repeaterCallsign = m->getParam(0); - gatewayCallsign = m->getParam(1); - address = m->getParam(2); + repeaterCallsign = m->getParam(0); + gatewayCallsign = m->getParam(1); + address = m->getParam(2); - delete m; + delete m; - return true; + return true; } // Get a gateway message, as a result of IDRT_GATEWAY returned from getMessageType() // A false return implies a network error -bool CIRCDDB::receiveGateway(wxString& gatewayCallsign, wxString& address, DSTAR_PROTOCOL& protocol) +bool CIRCDDB::receiveGateway(wxString& gatewayCallsign, wxString& address, DSTAR_PROTOCOL& /*protocol*/) { - IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); + IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); - if (rt != IDRT_GATEWAY) - { - wxLogError(wxT("CIRCDDB::receiveGateway: unexpected response type")); - return false; - } + if (rt != IDRT_GATEWAY) { + wxLogError(wxT("CIRCDDB::receiveGateway: unexpected response type")); + return false; + } - IRCMessage * m = d->app->getReplyMessage(); + IRCMessage * m = d->app->getReplyMessage(); - if (m == NULL) - { - wxLogError(wxT("CIRCDDB::receiveGateway: no message")); - return false; - } + if (m == NULL) { + wxLogError(wxT("CIRCDDB::receiveGateway: no message")); + return false; + } - if (!m->getCommand().IsSameAs(wxT("IDRT_GATEWAY"))) - { - wxLogError(wxT("CIRCDDB::receiveGateway: wrong message type")); - return false; - } + if (!m->getCommand().IsSameAs(wxT("IDRT_GATEWAY"))) { + wxLogError(wxT("CIRCDDB::receiveGateway: wrong message type")); + return false; + } - if (m->getParamCount() != 2) - { - wxLogError(wxT("CIRCDDB::receiveGateway: unexpected number of message parameters")); - return false; - } + if (m->getParamCount() != 2) { + wxLogError(wxT("CIRCDDB::receiveGateway: unexpected number of message parameters")); + return false; + } - gatewayCallsign = m->getParam(0); - address = m->getParam(1); + gatewayCallsign = m->getParam(0); + address = m->getParam(1); - delete m; + delete m; - return true; + return true; } // Get a user message, as a result of IDRT_USER returned from getMessageType() // A false return implies a network error bool CIRCDDB::receiveUser(wxString& userCallsign, wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address) { - wxString dummy; - return receiveUser(userCallsign, repeaterCallsign, gatewayCallsign, address, dummy); + wxString dummy; + return receiveUser(userCallsign, repeaterCallsign, gatewayCallsign, address, dummy); } bool CIRCDDB::receiveUser(wxString& userCallsign, wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address, - wxString& timeStamp) + wxString& timeStamp) { - IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); - - if (rt != IDRT_USER) - { - wxLogError(wxT("CIRCDDB::receiveUser: unexpected response type")); - return false; - } - - IRCMessage * m = d->app->getReplyMessage(); - - if (m == NULL) - { - wxLogError(wxT("CIRCDDB::receiveUser: no message")); - return false; - } - - if (!m->getCommand().IsSameAs(wxT("IDRT_USER"))) - { - wxLogError(wxT("CIRCDDB::receiveUser: wrong message type")); - return false; - } - - if (m->getParamCount() != 5) - { - wxLogError(wxT("CIRCDDB::receiveUser: unexpected number of message parameters")); - return false; - } - - userCallsign = m->getParam(0); - repeaterCallsign = m->getParam(1); - gatewayCallsign = m->getParam(2); - address = m->getParam(3); - timeStamp = m->getParam(4); - - delete m; - - return true; + IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); + + if (rt != IDRT_USER) { + wxLogError(wxT("CIRCDDB::receiveUser: unexpected response type")); + return false; + } + + IRCMessage * m = d->app->getReplyMessage(); + + if (m == NULL) { + wxLogError(wxT("CIRCDDB::receiveUser: no message")); + return false; + } + + if (!m->getCommand().IsSameAs(wxT("IDRT_USER"))) { + wxLogError(wxT("CIRCDDB::receiveUser: wrong message type")); + return false; + } + + if (m->getParamCount() != 5) { + wxLogError(wxT("CIRCDDB::receiveUser: unexpected number of message parameters")); + return false; + } + + userCallsign = m->getParam(0); + repeaterCallsign = m->getParam(1); + gatewayCallsign = m->getParam(2); + address = m->getParam(3); + timeStamp = m->getParam(4); + + delete m; + + return true; } void CIRCDDB::close() // Implictely kills any threads in the IRC code { - d->client -> stopWork(); - d->app -> stopWork(); + d->client -> stopWork(); + d->app -> stopWork(); } diff --git a/IRCDDB.h b/IRCDDB.h index d58a748..0f9dc56 100644 --- a/IRCDDB.h +++ b/IRCDDB.h @@ -41,10 +41,11 @@ enum DSTAR_PROTOCOL { struct CIRCDDBPrivate; -class CIRCDDB { +class CIRCDDB +{ public: CIRCDDB(const wxString& hostName, unsigned int port, const wxString& callsign, const wxString& password, - const wxString& versionInfo, const wxString& localAddr = wxEmptyString ); + const wxString& versionInfo, const wxString& localAddr = wxEmptyString ); ~CIRCDDB(); // A false return implies a network error, or unable to log in @@ -58,7 +59,7 @@ public: // infoURL URL of a web page with information about the repeater void rptrQTH( double latitude, double longitude, const wxString& desc1, - const wxString& desc2, const wxString& infoURL ); + const wxString& desc2, const wxString& infoURL ); @@ -95,9 +96,9 @@ public: // Send heard data, a false return implies a network error bool sendHeard(const wxString& myCall, const wxString& myCallExt, - const wxString& yourCall, const wxString& rpt1, - const wxString& rpt2, unsigned char flag1, - unsigned char flag2, unsigned char flag3 ); + const wxString& yourCall, const wxString& rpt1, + const wxString& rpt2, unsigned char flag1, + unsigned char flag2, unsigned char flag3 ); // same as sendHeard with two new fields: @@ -106,11 +107,11 @@ public: // tx_message: 20-char TX message or empty string, if the user did not // send a TX message bool sendHeardWithTXMsg(const wxString& myCall, const wxString& myCallExt, - const wxString& yourCall, const wxString& rpt1, - const wxString& rpt2, unsigned char flag1, - unsigned char flag2, unsigned char flag3, - const wxString& network_destination, - const wxString& tx_message ); + const wxString& yourCall, const wxString& rpt1, + const wxString& rpt2, unsigned char flag1, + unsigned char flag2, unsigned char flag3, + const wxString& network_destination, + const wxString& tx_message ); // this method should be called at the end of a transmission // num_dv_frames: number of DV frames sent out (96 bit frames, 20ms) @@ -123,12 +124,12 @@ public: // BER = num_bit_errors / (num_dv_frames * 24) // Set num_bit_errors = -1, if the error information is not available. bool sendHeardWithTXStats(const wxString& myCall, const wxString& myCallExt, - const wxString& yourCall, const wxString& rpt1, - const wxString& rpt2, unsigned char flag1, - unsigned char flag2, unsigned char flag3, - int num_dv_frames, - int num_dv_silent_frames, - int num_bit_errors ); + const wxString& yourCall, const wxString& rpt1, + const wxString& rpt2, unsigned char flag1, + unsigned char flag2, unsigned char flag3, + int num_dv_frames, + int num_dv_silent_frames, + int num_bit_errors ); // The following three functions don't block waiting for a reply, they just send the data @@ -142,7 +143,7 @@ public: bool findUser(const wxString& userCallsign); // The following functions are for processing received messages - + // Get the waiting message type IRCDDB_RESPONSE_TYPE getMessageType(); @@ -159,7 +160,7 @@ public: bool receiveUser(wxString& userCallsign, wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address); bool receiveUser(wxString& userCallsign, wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address, - wxString& timeStamp ); + wxString& timeStamp ); void close(); // Implictely kills any threads in the IRC code diff --git a/IRCDDBApp.cpp b/IRCDDBApp.cpp index 6bb8a1c..8ad58db 100644 --- a/IRCDDBApp.cpp +++ b/IRCDDBApp.cpp @@ -44,30 +44,28 @@ along with this program. If not, see . class IRCDDBAppUserObject { - public: - - wxString nick; - wxString name; - wxString host; - bool op; - unsigned int usn; - - IRCDDBAppUserObject () - { - IRCDDBAppUserObject (wxT(""), wxT(""), wxT("")); - } - - IRCDDBAppUserObject ( const wxString& n, const wxString& nm, const wxString& h ) - { - nick = n; - name = nm; - host = h; - op = false; - usn = counter; - counter ++; - } - - static unsigned int counter; +public: + + wxString nick; + wxString name; + wxString host; + bool op; + unsigned int usn; + + IRCDDBAppUserObject () { + IRCDDBAppUserObject (wxT(""), wxT(""), wxT("")); + } + + IRCDDBAppUserObject ( const wxString& n, const wxString& nm, const wxString& h ) { + nick = n; + name = nm; + host = h; + op = false; + usn = counter; + counter ++; + } + + static unsigned int counter; }; unsigned int IRCDDBAppUserObject::counter = 0; @@ -78,30 +76,27 @@ WX_DECLARE_STRING_HASH_MAP( IRCDDBAppUserObject, IRCDDBAppUserMap ); class IRCDDBAppRptrObject { - public: +public: - wxString arearp_cs; - wxDateTime lastChanged; - wxString zonerp_cs; + wxString arearp_cs; + wxDateTime lastChanged; + wxString zonerp_cs; - IRCDDBAppRptrObject () - { - } + IRCDDBAppRptrObject () { + } - IRCDDBAppRptrObject (wxDateTime& dt, wxString& repeaterCallsign, wxString& gatewayCallsign) - { - arearp_cs = repeaterCallsign; - lastChanged = dt; - zonerp_cs = gatewayCallsign; + IRCDDBAppRptrObject (wxDateTime& dt, wxString& repeaterCallsign, wxString& gatewayCallsign) { + arearp_cs = repeaterCallsign; + lastChanged = dt; + zonerp_cs = gatewayCallsign; - if (dt.IsLaterThan(maxTime)) - { - maxTime = dt; - } - } + if (dt.IsLaterThan(maxTime)) { + maxTime = dt; + } + } - static wxDateTime maxTime; -}; + static wxDateTime maxTime; +}; wxDateTime IRCDDBAppRptrObject::maxTime((time_t) 950000000); // February 2000 @@ -112,207 +107,195 @@ WX_DECLARE_STRING_HASH_MAP( wxString, IRCDDBAppModuleMap ); class IRCDDBAppPrivate { - public: - - IRCDDBAppPrivate() - : tablePattern(wxT("^[0-9]$")), - datePattern(wxT("^20[0-9][0-9]-((1[0-2])|(0[1-9]))-((3[01])|([12][0-9])|(0[1-9]))$")), - timePattern(wxT("^((2[0-3])|([01][0-9])):[0-5][0-9]:[0-5][0-9]$")), - dbPattern(wxT("^[0-9A-Z_]{8}$")), - modulePattern(wxT("^[ABCD]D?$")) - { - wdTimer = 0; - wdCounter = 0; - } +public: + + IRCDDBAppPrivate() + : tablePattern(wxT("^[0-9]$")), + datePattern(wxT("^20[0-9][0-9]-((1[0-2])|(0[1-9]))-((3[01])|([12][0-9])|(0[1-9]))$")), + timePattern(wxT("^((2[0-3])|([01][0-9])):[0-5][0-9]:[0-5][0-9]$")), + dbPattern(wxT("^[0-9A-Z_]{8}$")), + modulePattern(wxT("^[ABCD]D?$")) { + wdTimer = 0; + wdCounter = 0; + } - IRCMessageQueue * sendQ; + IRCMessageQueue * sendQ; - IRCDDBAppUserMap user; - wxMutex userMapMutex; + IRCDDBAppUserMap user; + wxMutex userMapMutex; - wxString currentServer; - wxString myNick; + wxString currentServer; + wxString myNick; - wxRegEx tablePattern; - wxRegEx datePattern; - wxRegEx timePattern; - wxRegEx dbPattern; - wxRegEx modulePattern; + wxRegEx tablePattern; + wxRegEx datePattern; + wxRegEx timePattern; + wxRegEx dbPattern; + wxRegEx modulePattern; - int state; - int timer; - int infoTimer; + int state; + int timer; + int infoTimer; - wxString updateChannel; - wxString channelTopic; - wxString bestServer; + wxString updateChannel; + wxString channelTopic; + wxString bestServer; - bool initReady; + bool initReady; - bool terminateThread; + bool terminateThread; - IRCDDBAppRptrMap rptrMap; - wxMutex rptrMapMutex; + IRCDDBAppRptrMap rptrMap; + wxMutex rptrMapMutex; - IRCMessageQueue replyQ; + IRCMessageQueue replyQ; - IRCDDBAppModuleMap moduleMap; - wxMutex moduleMapMutex; + IRCDDBAppModuleMap moduleMap; + wxMutex moduleMapMutex; - wxString rptrLocation; - wxString rptrInfoURL; + wxString rptrLocation; + wxString rptrInfoURL; - wxString wdInfo; - int wdTimer; - int wdCounter; + wxString wdInfo; + int wdTimer; + int wdCounter; }; - + IRCDDBApp::IRCDDBApp( const wxString& u_chan ) - : wxThread(wxTHREAD_JOINABLE), - d(new IRCDDBAppPrivate) + : wxThread(wxTHREAD_JOINABLE), + d(new IRCDDBAppPrivate) { - d->sendQ = NULL; - d->initReady = false; + d->sendQ = NULL; + d->initReady = false; + + userListReset(); - userListReset(); - - d->state = 0; - d->timer = 0; - d->myNick = wxT("none"); - - d->updateChannel = u_chan; + d->state = 0; + d->timer = 0; + d->myNick = wxT("none"); + + d->updateChannel = u_chan; + + d->terminateThread = false; - d->terminateThread = false; - } IRCDDBApp::~IRCDDBApp() { - if (d->sendQ != NULL) - { - delete d->sendQ; - } - delete d; + if (d->sendQ != NULL) { + delete d->sendQ; + } + delete d; } void IRCDDBApp::rptrQTH( double latitude, double longitude, const wxString& desc1, - const wxString& desc2, const wxString& infoURL ) + const wxString& desc2, const wxString& infoURL ) { - wxString pos = wxString::Format(wxT("%+09.5f %+010.5f"), latitude, longitude); + wxString pos = wxString::Format(wxT("%+09.5f %+010.5f"), latitude, longitude); - wxString d1 = desc1; - wxString d2 = desc2; + wxString d1 = desc1; + wxString d2 = desc2; - d1.Append(wxT(' '), 20); - d2.Append(wxT(' '), 20); + d1.Append(wxT(' '), 20); + d2.Append(wxT(' '), 20); - wxRegEx nonValid(wxT("[^a-zA-Z0-9 +&(),./'-]")); + wxRegEx nonValid(wxT("[^a-zA-Z0-9 +&(),./'-]")); - nonValid.Replace(&d1, wxEmptyString); - nonValid.Replace(&d2, wxEmptyString); + nonValid.Replace(&d1, wxEmptyString); + nonValid.Replace(&d2, wxEmptyString); - pos.Replace( wxT(","), wxT(".")); - d1.Replace(wxT(" "), wxT("_")); - d2.Replace(wxT(" "), wxT("_")); + pos.Replace( wxT(","), wxT(".")); + d1.Replace(wxT(" "), wxT("_")); + d2.Replace(wxT(" "), wxT("_")); - d->rptrLocation = pos + wxT(" ") + d1.Mid(0, 20) + wxT(" ") + d2.Mid(0, 20); + d->rptrLocation = pos + wxT(" ") + d1.Mid(0, 20) + wxT(" ") + d2.Mid(0, 20); - wxLogVerbose(wxT("QTH: ") + d->rptrLocation); + wxLogVerbose(wxT("QTH: ") + d->rptrLocation); - wxRegEx urlNonValid(wxT("[^[:graph:]]")); + wxRegEx urlNonValid(wxT("[^[:graph:]]")); - d->rptrInfoURL = infoURL; + d->rptrInfoURL = infoURL; - urlNonValid.Replace( & d->rptrInfoURL, wxEmptyString ); + urlNonValid.Replace( & d->rptrInfoURL, wxEmptyString ); - wxLogVerbose(wxT("URL: ") + d->rptrInfoURL.Mid(0, 120)); + wxLogVerbose(wxT("URL: ") + d->rptrInfoURL.Mid(0, 120)); - d->infoTimer = 5; // send info in 5 seconds + d->infoTimer = 5; // send info in 5 seconds } void IRCDDBApp::rptrQRG( const wxString& module, double txFrequency, double duplexShift, - double range, double agl ) + double range, double agl ) { - if (d->modulePattern.Matches(module)) - { - wxString f = module + wxT(" ") + wxString::Format(wxT("%011.5f %+010.5f %06.2f %06.1f"), - txFrequency, duplexShift, range / 1609.344, agl ); + if (d->modulePattern.Matches(module)) { + wxString f = module + wxT(" ") + wxString::Format(wxT("%011.5f %+010.5f %06.2f %06.1f"), + txFrequency, duplexShift, range / 1609.344, agl ); - f.Replace( wxT(","), wxT(".")); + f.Replace( wxT(","), wxT(".")); - wxMutexLocker lock(d->moduleMapMutex); - d->moduleMap[module] = f; + wxMutexLocker lock(d->moduleMapMutex); + d->moduleMap[module] = f; - wxLogVerbose(wxT("QRG: ") + f); + wxLogVerbose(wxT("QRG: ") + f); - d->infoTimer = 5; // send info in 5 seconds - } + d->infoTimer = 5; // send info in 5 seconds + } } void IRCDDBApp::kickWatchdog( const wxString& s ) { - if (s.Len() > 0) - { - wxRegEx nonValid(wxT("[^[:graph:]]")); - d->wdInfo = s; - nonValid.Replace(& d->wdInfo, wxEmptyString); - - if (d->wdInfo.Len() > 0) - { - if (d->wdTimer == 0) - { - d->wdTimer ++; - } - - d->wdCounter ++; - } - } + if (s.Len() > 0) { + wxRegEx nonValid(wxT("[^[:graph:]]")); + d->wdInfo = s; + nonValid.Replace(& d->wdInfo, wxEmptyString); + + if (d->wdInfo.Len() > 0) { + if (d->wdTimer == 0) { + d->wdTimer ++; + } + + d->wdCounter ++; + } + } } int IRCDDBApp::getConnectionState() { - return d->state; + return d->state; } IRCDDB_RESPONSE_TYPE IRCDDBApp::getReplyMessageType() { - IRCMessage * m = d->replyQ.peekFirst(); - if (m == NULL) - { - return IDRT_NONE; - } - - wxString msgType = m->getCommand(); - - if (msgType.IsSameAs(wxT("IDRT_USER"))) - { - return IDRT_USER; - } - else if (msgType.IsSameAs(wxT("IDRT_REPEATER"))) - { - return IDRT_REPEATER; - } - else if (msgType.IsSameAs(wxT("IDRT_GATEWAY"))) - { - return IDRT_GATEWAY; - } - - wxLogError(wxT("IRCDDBApp::getMessageType: unknown msg type")); - - return IDRT_NONE; + IRCMessage * m = d->replyQ.peekFirst(); + if (m == NULL) { + return IDRT_NONE; + } + + wxString msgType = m->getCommand(); + + if (msgType.IsSameAs(wxT("IDRT_USER"))) { + return IDRT_USER; + } else if (msgType.IsSameAs(wxT("IDRT_REPEATER"))) { + return IDRT_REPEATER; + } else if (msgType.IsSameAs(wxT("IDRT_GATEWAY"))) { + return IDRT_GATEWAY; + } + + wxLogError(wxT("IRCDDBApp::getMessageType: unknown msg type")); + + return IDRT_NONE; } IRCMessage * IRCDDBApp::getReplyMessage() { - return d->replyQ.getMessage(); + return d->replyQ.getMessage(); } @@ -320,67 +303,62 @@ IRCMessage * IRCDDBApp::getReplyMessage() bool IRCDDBApp::startWork() { - if (Create() != wxTHREAD_NO_ERROR) - { - wxLogError(wxT("IRCClient::startWork: Could not create the worker thread!")); - return false; - } + if (Create() != wxTHREAD_NO_ERROR) { + wxLogError(wxT("IRCClient::startWork: Could not create the worker thread!")); + return false; + } - d->terminateThread = false; + d->terminateThread = false; - if (Run() != wxTHREAD_NO_ERROR) - { - wxLogError(wxT("IRCClient::startWork: Could not run the worker thread!")); - return false; - } + if (Run() != wxTHREAD_NO_ERROR) { + wxLogError(wxT("IRCClient::startWork: Could not run the worker thread!")); + return false; + } - return true; + return true; } void IRCDDBApp::stopWork() { - d->terminateThread = true; + d->terminateThread = true; - Wait(); + Wait(); } - + void IRCDDBApp::userJoin (const wxString& nick, const wxString& name, const wxString& host) { - wxMutexLocker lock(d->userMapMutex); + wxMutexLocker lock(d->userMapMutex); - wxString lnick = nick; - lnick.MakeLower(); + wxString lnick = nick; + lnick.MakeLower(); - IRCDDBAppUserObject u( lnick, name, host ); - - d->user[lnick] = u; + IRCDDBAppUserObject u( lnick, name, host ); - // wxLogVerbose(wxT("add %d: (") + u.nick + wxT(") (") + u.host + wxT(")"), d->user.size()); + d->user[lnick] = u; - if (d->initReady) - { - int hyphenPos = nick.Find(wxT('-')); + // wxLogVerbose(wxT("add %d: (") + u.nick + wxT(") (") + u.host + wxT(")"), d->user.size()); - if ((hyphenPos >= 4) && (hyphenPos <= 6)) - { - wxString gatewayCallsign = nick.Mid(0, hyphenPos).Upper(); + if (d->initReady) { + int hyphenPos = nick.Find(wxT('-')); - while (gatewayCallsign.Length() < 7) - { - gatewayCallsign.Append(wxT(' ')); - } + if ((hyphenPos >= 4) && (hyphenPos <= 6)) { + wxString gatewayCallsign = nick.Mid(0, hyphenPos).Upper(); - gatewayCallsign.Append(wxT('G')); + while (gatewayCallsign.Length() < 7) { + gatewayCallsign.Append(wxT(' ')); + } - IRCMessage * m2 = new IRCMessage(wxT( "IDRT_GATEWAY")); - m2->addParam(gatewayCallsign); - m2->addParam(host); - d->replyQ.putMessage(m2); - } - } + gatewayCallsign.Append(wxT('G')); + + IRCMessage * m2 = new IRCMessage(wxT( "IDRT_GATEWAY")); + m2->addParam(gatewayCallsign); + m2->addParam(host); + d->replyQ.putMessage(m2); + } + } - // wxLogVerbose(wxT("user %d"), u.usn ); + // wxLogVerbose(wxT("user %d"), u.usn ); } @@ -388,135 +366,123 @@ void IRCDDBApp::userJoin (const wxString& nick, const wxString& name, const wxSt void IRCDDBApp::userLeave (const wxString& nick) { - wxMutexLocker lock(d->userMapMutex); - - wxString lnick = nick; - lnick.MakeLower(); - - d->user.erase(lnick); - - // wxLogVerbose(wxT("rm %d: ") + nick, d->user.size()); - - if (d->currentServer.Len() > 0) - { - if (d->user.count(d->myNick) != 1) - { - wxLogVerbose(wxT("IRCDDBApp::userLeave: could not find own nick")); - return; - } - - IRCDDBAppUserObject me = d->user[d->myNick]; - - if (me.op == false) - { - // if I am not op, then look for new server - - if (d->currentServer.IsSameAs(lnick)) - { - // currentServer = null; - d->state = 2; // choose new server - d->timer = 200; - d->initReady = false; - } - } - } + wxMutexLocker lock(d->userMapMutex); + + wxString lnick = nick; + lnick.MakeLower(); + + d->user.erase(lnick); + + // wxLogVerbose(wxT("rm %d: ") + nick, d->user.size()); + + if (d->currentServer.Len() > 0) { + if (d->user.count(d->myNick) != 1) { + wxLogVerbose(wxT("IRCDDBApp::userLeave: could not find own nick")); + return; + } + + IRCDDBAppUserObject me = d->user[d->myNick]; + + if (me.op == false) { + // if I am not op, then look for new server + + if (d->currentServer.IsSameAs(lnick)) { + // currentServer = null; + d->state = 2; // choose new server + d->timer = 200; + d->initReady = false; + } + } + } } void IRCDDBApp::userListReset() { - wxMutexLocker lock(d->userMapMutex); + wxMutexLocker lock(d->userMapMutex); - d->user.clear(); + d->user.clear(); } void IRCDDBApp::setCurrentNick(const wxString& nick) { - d->myNick = nick; - wxLogVerbose(wxT("IRCDDBApp::setCurrentNick ") + nick); + d->myNick = nick; + wxLogVerbose(wxT("IRCDDBApp::setCurrentNick ") + nick); } void IRCDDBApp::setBestServer(const wxString& ircUser) { - d->bestServer = ircUser; - wxLogVerbose(wxT("IRCDDBApp::setBestServer ") + ircUser); + d->bestServer = ircUser; + wxLogVerbose(wxT("IRCDDBApp::setBestServer ") + ircUser); } void IRCDDBApp::setTopic(const wxString& topic) { - d->channelTopic = topic; + d->channelTopic = topic; } bool IRCDDBApp::findServerUser() { - wxMutexLocker lock(d->userMapMutex); - - bool found = false; - - IRCDDBAppUserMap::iterator it; - - for( it = d->user.begin(); it != d->user.end(); ++it ) - { - IRCDDBAppUserObject u = it->second; - - if (u.nick.StartsWith(wxT("s-")) && u.op && !d->myNick.IsSameAs(u.nick) - && u.nick.IsSameAs(d->bestServer)) - { - d->currentServer = u.nick; - found = true; - break; - } - } - - if (found) - return true; - - if (d->bestServer.Len() == 8) - { - for( it = d->user.begin(); it != d->user.end(); ++it ) - { - IRCDDBAppUserObject u = it->second; - - if (u.nick.StartsWith(d->bestServer.Mid(0,7)) && u.op && - !d->myNick.IsSameAs(u.nick) ) - { - d->currentServer = u.nick; - found = true; - break; - } - } - } - - if (found) - return true; - - for( it = d->user.begin(); it != d->user.end(); ++it ) - { - IRCDDBAppUserObject u = it->second; - - if (u.nick.StartsWith(wxT("s-")) && u.op && !d->myNick.IsSameAs(u.nick)) - { - d->currentServer = u.nick; - found = true; - break; - } - } - - return found; + wxMutexLocker lock(d->userMapMutex); + + bool found = false; + + IRCDDBAppUserMap::iterator it; + + for( it = d->user.begin(); it != d->user.end(); ++it ) { + IRCDDBAppUserObject u = it->second; + + if (u.nick.StartsWith(wxT("s-")) && u.op && !d->myNick.IsSameAs(u.nick) + && u.nick.IsSameAs(d->bestServer)) { + d->currentServer = u.nick; + found = true; + break; + } + } + + if (found) + return true; + + if (d->bestServer.Len() == 8) { + for( it = d->user.begin(); it != d->user.end(); ++it ) { + IRCDDBAppUserObject u = it->second; + + if (u.nick.StartsWith(d->bestServer.Mid(0,7)) && u.op && + !d->myNick.IsSameAs(u.nick) ) { + d->currentServer = u.nick; + found = true; + break; + } + } + } + + if (found) + return true; + + for( it = d->user.begin(); it != d->user.end(); ++it ) { + IRCDDBAppUserObject u = it->second; + + if (u.nick.StartsWith(wxT("s-")) && u.op && !d->myNick.IsSameAs(u.nick)) { + d->currentServer = u.nick; + found = true; + break; + } + } + + return found; } - + void IRCDDBApp::userChanOp (const wxString& nick, bool op) { - wxMutexLocker lock(d->userMapMutex); + wxMutexLocker lock(d->userMapMutex); - wxString lnick = nick; - lnick.MakeLower(); + wxString lnick = nick; + lnick.MakeLower(); - if (d->user.count(lnick) == 1) - { - d->user[lnick].op = op; - } + if (d->user.count(lnick) == 1) { + d->user[lnick].op = op; + } } - + static const int numberOfTables = 2; @@ -527,807 +493,694 @@ static const int numberOfTables = 2; wxString IRCDDBApp::getIPAddress(wxString& zonerp_cs) { - wxMutexLocker lock(d->userMapMutex); - wxString gw = zonerp_cs; + wxMutexLocker lock(d->userMapMutex); + wxString gw = zonerp_cs; - gw.Replace(wxT("_"), wxT(" ")); - gw.MakeLower(); + gw.Replace(wxT("_"), wxT(" ")); + gw.MakeLower(); - unsigned int max_usn = 0; - wxString ipAddr; + unsigned int max_usn = 0; + wxString ipAddr; - int j; + int j; - for (j=1; j <= 4; j++) - { - // int i = 0; - wxString ircUser = gw.Strip() + wxString::Format(wxT("-%d"), j); + for (j=1; j <= 4; j++) { + // int i = 0; + wxString ircUser = gw.Strip() + wxString::Format(wxT("-%d"), j); - if (d->user.count(ircUser) == 1) - { - IRCDDBAppUserObject o = d->user[ ircUser ]; + if (d->user.count(ircUser) == 1) { + IRCDDBAppUserObject o = d->user[ ircUser ]; - if (o.usn >= max_usn) - { - max_usn = o.usn; - ipAddr = o.host; - } - // i = 1; - } - // wxLogVerbose(wxT("getIP %d (") + ircUser + wxT(") (") + ipAddr + wxT(")"), i); + if (o.usn >= max_usn) { + max_usn = o.usn; + ipAddr = o.host; + } + // i = 1; + } + // wxLogVerbose(wxT("getIP %d (") + ircUser + wxT(") (") + ipAddr + wxT(")"), i); - } + } - return ipAddr; + return ipAddr; } bool IRCDDBApp::findGateway(const wxString& gwCall) { - wxString s = gwCall.Mid(0,6); + wxString s = gwCall.Mid(0,6); - IRCMessage * m2 = new IRCMessage(wxT( "IDRT_GATEWAY")); - m2->addParam(gwCall); - m2->addParam(getIPAddress(s)); - d->replyQ.putMessage(m2); + IRCMessage * m2 = new IRCMessage(wxT( "IDRT_GATEWAY")); + m2->addParam(gwCall); + m2->addParam(getIPAddress(s)); + d->replyQ.putMessage(m2); - return true; + return true; } static void findReflector( const wxString& rptrCall, IRCDDBAppPrivate * d ) { - wxString zonerp_cs; - wxString ipAddr; + wxString zonerp_cs; + wxString ipAddr; #define MAXIPV4ADDR 5 - struct sockaddr_in addr[MAXIPV4ADDR]; - unsigned int numAddr = 0; + struct sockaddr_in addr[MAXIPV4ADDR]; + unsigned int numAddr = 0; - char host_name[80]; + char host_name[80]; - wxString host = rptrCall.Mid(0,6) + wxT(".reflector.ircddb.net"); + wxString host = rptrCall.Mid(0,6) + wxT(".reflector.ircddb.net"); - safeStringCopy(host_name, host.mb_str(wxConvUTF8), sizeof host_name); + safeStringCopy(host_name, host.mb_str(wxConvUTF8), sizeof host_name); - if (getAllIPV4Addresses(host_name, 0, &numAddr, addr, MAXIPV4ADDR) == 0) - { - if (numAddr > 0) - { - unsigned char * a = (unsigned char *) &addr[0].sin_addr; + if (getAllIPV4Addresses(host_name, 0, &numAddr, addr, MAXIPV4ADDR) == 0) { + if (numAddr > 0) { + unsigned char * a = (unsigned char *) &addr[0].sin_addr; + + ipAddr = wxString::Format(wxT("%d.%d.%d.%d"), a[0], a[1], a[2], a[3]); + zonerp_cs = rptrCall; + zonerp_cs.SetChar(7, wxT('G')); + } + } - ipAddr = wxString::Format(wxT("%d.%d.%d.%d"), a[0], a[1], a[2], a[3]); - zonerp_cs = rptrCall; - zonerp_cs.SetChar(7, wxT('G')); - } - } - - IRCMessage * m2 = new IRCMessage(wxT("IDRT_REPEATER")); - m2->addParam(rptrCall); - m2->addParam(zonerp_cs); - m2->addParam(ipAddr); - d->replyQ.putMessage(m2); + IRCMessage * m2 = new IRCMessage(wxT("IDRT_REPEATER")); + m2->addParam(rptrCall); + m2->addParam(zonerp_cs); + m2->addParam(ipAddr); + d->replyQ.putMessage(m2); } bool IRCDDBApp::findRepeater(const wxString& rptrCall) { - if (rptrCall.StartsWith(wxT("XRF")) || rptrCall.StartsWith(wxT("REF"))) - { - findReflector(rptrCall, d); - return true; - } - - wxString arearp_cs = rptrCall; - arearp_cs.Replace(wxT(" "), wxT("_")); - - wxString zonerp_cs; - - wxMutexLocker lock(d->rptrMapMutex); - - wxString s = wxT("NONE"); - - if (d->rptrMap.count(arearp_cs) == 1) - { - IRCDDBAppRptrObject o = d->rptrMap[arearp_cs]; - zonerp_cs = o.zonerp_cs; - zonerp_cs.Replace(wxT("_"), wxT(" ")); - zonerp_cs.SetChar(7, wxT('G')); - s = o.zonerp_cs; - } - - IRCMessage * m2 = new IRCMessage(wxT("IDRT_REPEATER")); - m2->addParam(rptrCall); - m2->addParam(zonerp_cs); - m2->addParam(getIPAddress(s)); - d->replyQ.putMessage(m2); - - return true; + if (rptrCall.StartsWith(wxT("XRF")) || rptrCall.StartsWith(wxT("REF"))) { + findReflector(rptrCall, d); + return true; + } + + wxString arearp_cs = rptrCall; + arearp_cs.Replace(wxT(" "), wxT("_")); + + wxString zonerp_cs; + + wxMutexLocker lock(d->rptrMapMutex); + + wxString s = wxT("NONE"); + + if (d->rptrMap.count(arearp_cs) == 1) { + IRCDDBAppRptrObject o = d->rptrMap[arearp_cs]; + zonerp_cs = o.zonerp_cs; + zonerp_cs.Replace(wxT("_"), wxT(" ")); + zonerp_cs.SetChar(7, wxT('G')); + s = o.zonerp_cs; + } + + IRCMessage * m2 = new IRCMessage(wxT("IDRT_REPEATER")); + m2->addParam(rptrCall); + m2->addParam(zonerp_cs); + m2->addParam(getIPAddress(s)); + d->replyQ.putMessage(m2); + + return true; } bool IRCDDBApp::sendHeard(const wxString& myCall, const wxString& myCallExt, - const wxString& yourCall, const wxString& rpt1, - const wxString& rpt2, unsigned char flag1, - unsigned char flag2, unsigned char flag3, - const wxString& destination, const wxString& tx_msg, - const wxString& tx_stats ) + const wxString& yourCall, const wxString& rpt1, + const wxString& rpt2, unsigned char flag1, + unsigned char flag2, unsigned char flag3, + const wxString& destination, const wxString& tx_msg, + const wxString& tx_stats ) { - wxString my = myCall; - wxString myext = myCallExt; - wxString ur = yourCall; - wxString r1 = rpt1; - wxString r2 = rpt2; - wxString dest = destination; - - wxRegEx nonValid(wxT("[^A-Z0-9/]")); - wxString underScore = wxT("_"); - - nonValid.Replace(&my, underScore); - nonValid.Replace(&myext, underScore); - nonValid.Replace(&ur, underScore); - nonValid.Replace(&r1, underScore); - nonValid.Replace(&r2, underScore); - nonValid.Replace(&dest, underScore); - - bool statsMsg = (tx_stats.Len() > 0); - - wxString srv = d->currentServer; - IRCMessageQueue * q = getSendQ(); - - if ((srv.Len() > 0) && (d->state >= 6) && (q != NULL)) - { - wxString cmd = wxT("UPDATE "); - - cmd.Append( getCurrentTime() ); - - cmd.Append(wxT(" ")); - - cmd.Append(my); - cmd.Append(wxT(" ")); - cmd.Append(r1); - cmd.Append(wxT(" ")); - if (!statsMsg) - { - cmd.Append(wxT("0 ")); - } - cmd.Append(r2); - cmd.Append(wxT(" ")); - cmd.Append(ur); - cmd.Append(wxT(" ")); - - wxString flags = wxString::Format(wxT("%02X %02X %02X"), flag1, flag2, flag3); - - cmd.Append(flags); - cmd.Append(wxT(" ")); - cmd.Append(myext); - - if (statsMsg) - { - cmd.Append(wxT(" # ")); - cmd.Append(tx_stats); - } - else - { - cmd.Append(wxT(" 00 ")); - cmd.Append(dest); - - if (tx_msg.Len() == 20) - { - cmd.Append(wxT(" ")); - cmd.Append(tx_msg); - } - } - - - IRCMessage * m = new IRCMessage(srv, cmd); - - q->putMessage(m); - return true; - } - else - { - return false; - } + wxString my = myCall; + wxString myext = myCallExt; + wxString ur = yourCall; + wxString r1 = rpt1; + wxString r2 = rpt2; + wxString dest = destination; + + wxRegEx nonValid(wxT("[^A-Z0-9/]")); + wxString underScore = wxT("_"); + + nonValid.Replace(&my, underScore); + nonValid.Replace(&myext, underScore); + nonValid.Replace(&ur, underScore); + nonValid.Replace(&r1, underScore); + nonValid.Replace(&r2, underScore); + nonValid.Replace(&dest, underScore); + + bool statsMsg = (tx_stats.Len() > 0); + + wxString srv = d->currentServer; + IRCMessageQueue * q = getSendQ(); + + if ((srv.Len() > 0) && (d->state >= 6) && (q != NULL)) { + wxString cmd = wxT("UPDATE "); + + cmd.Append( getCurrentTime() ); + + cmd.Append(wxT(" ")); + + cmd.Append(my); + cmd.Append(wxT(" ")); + cmd.Append(r1); + cmd.Append(wxT(" ")); + if (!statsMsg) { + cmd.Append(wxT("0 ")); + } + cmd.Append(r2); + cmd.Append(wxT(" ")); + cmd.Append(ur); + cmd.Append(wxT(" ")); + + wxString flags = wxString::Format(wxT("%02X %02X %02X"), flag1, flag2, flag3); + + cmd.Append(flags); + cmd.Append(wxT(" ")); + cmd.Append(myext); + + if (statsMsg) { + cmd.Append(wxT(" # ")); + cmd.Append(tx_stats); + } else { + cmd.Append(wxT(" 00 ")); + cmd.Append(dest); + + if (tx_msg.Len() == 20) { + cmd.Append(wxT(" ")); + cmd.Append(tx_msg); + } + } + + + IRCMessage * m = new IRCMessage(srv, cmd); + + q->putMessage(m); + return true; + } else { + return false; + } } bool IRCDDBApp::findUser(const wxString& usrCall) { - wxString srv = d->currentServer; - IRCMessageQueue * q = getSendQ(); - - if ((srv.Len() > 0) && (d->state >= 6) && (q != NULL)) - { - wxString usr = usrCall; - - usr.Replace(wxT(" "), wxT("_")); - - IRCMessage * m = new IRCMessage(srv, - wxT("FIND ") + usr ); - - q->putMessage(m); - } - else - { - IRCMessage * m2 = new IRCMessage(wxT("IDRT_USER")); - m2->addParam(usrCall); - m2->addParam(wxT("")); - m2->addParam(wxT("")); - m2->addParam(wxT("")); - m2->addParam(wxT("")); - d->replyQ.putMessage(m2); - } - - return true; + wxString srv = d->currentServer; + IRCMessageQueue * q = getSendQ(); + + if ((srv.Len() > 0) && (d->state >= 6) && (q != NULL)) { + wxString usr = usrCall; + + usr.Replace(wxT(" "), wxT("_")); + + IRCMessage * m = new IRCMessage(srv, + wxT("FIND ") + usr ); + + q->putMessage(m); + } else { + IRCMessage * m2 = new IRCMessage(wxT("IDRT_USER")); + m2->addParam(usrCall); + m2->addParam(wxT("")); + m2->addParam(wxT("")); + m2->addParam(wxT("")); + m2->addParam(wxT("")); + d->replyQ.putMessage(m2); + } + + return true; } void IRCDDBApp::msgChannel (IRCMessage * m) { - if (m->getPrefixNick().StartsWith(wxT("s-")) && (m->numParams >= 2)) // server msg - { - doUpdate(m->params[1]); - } + if (m->getPrefixNick().StartsWith(wxT("s-")) && (m->numParams >= 2)) { // server msg + doUpdate(m->params[1]); + } } void IRCDDBApp::doNotFound ( wxString& msg, wxString& retval ) { - int tableID = 0; - - wxStringTokenizer tkz(msg); - - if (!tkz.HasMoreTokens()) - { - return; // no text in message - } - - wxString tk = tkz.GetNextToken(); - - - if (d->tablePattern.Matches(tk)) - { - long i; - - if (tk.ToLong(&i)) - { - tableID = i; - if ((tableID < 0) || (tableID >= numberOfTables)) - { - wxLogVerbose(wxT("invalid table ID %d"), tableID); - return; - } - } - else - { - return; // not a valid number - } - - if (!tkz.HasMoreTokens()) - { - return; // received nothing but the tableID - } - - tk = tkz.GetNextToken(); - } - - if (tableID == 0) - { - if (! d->dbPattern.Matches(tk)) - { - return; // no valid key - } - - retval = tk; - } -} + int tableID = 0; -void IRCDDBApp::doUpdate ( wxString& msg ) -{ - int tableID = 0; + wxStringTokenizer tkz(msg); + + if (!tkz.HasMoreTokens()) { + return; // no text in message + } - wxStringTokenizer tkz(msg); + wxString tk = tkz.GetNextToken(); - if (!tkz.HasMoreTokens()) - { - return; // no text in message - } - wxString tk = tkz.GetNextToken(); + if (d->tablePattern.Matches(tk)) { + long i; + if (tk.ToLong(&i)) { + tableID = i; + if ((tableID < 0) || (tableID >= numberOfTables)) { + wxLogVerbose(wxT("invalid table ID %d"), tableID); + return; + } + } else { + return; // not a valid number + } - if (d->tablePattern.Matches(tk)) - { - long i; + if (!tkz.HasMoreTokens()) { + return; // received nothing but the tableID + } - if (tk.ToLong(&i)) - { - tableID = i; - if ((tableID < 0) || (tableID >= numberOfTables)) - { - wxLogVerbose(wxT("invalid table ID %d"), tableID); - return; - } - } - else - { - return; // not a valid number - } - - if (!tkz.HasMoreTokens()) - { - return; // received nothing but the tableID - } - - tk = tkz.GetNextToken(); - } - - if (d->datePattern.Matches(tk)) - { - if (!tkz.HasMoreTokens()) - { - return; // nothing after date string - } - - wxString timeToken = tkz.GetNextToken(); - - if (! d->timePattern.Matches(timeToken)) - { - return; // no time string after date string - } - - wxDateTime dt; - - if (dt.ParseFormat(tk + wxT(" ") + timeToken, wxT("%Y-%m-%d %H:%M:%S")) == NULL) - { - return; // date+time parsing failed - } - - if ((tableID == 0) || (tableID == 1)) - { - if (!tkz.HasMoreTokens()) - { - return; // nothing after time string + tk = tkz.GetNextToken(); } - wxString key = tkz.GetNextToken(); + if (tableID == 0) { + if (! d->dbPattern.Matches(tk)) { + return; // no valid key + } - if (! d->dbPattern.Matches(key)) - { - return; // no valid key + retval = tk; } +} + +void IRCDDBApp::doUpdate ( wxString& msg ) +{ + int tableID = 0; - if (!tkz.HasMoreTokens()) - { - return; // nothing after time string + wxStringTokenizer tkz(msg); + + if (!tkz.HasMoreTokens()) { + return; // no text in message } - wxString value = tkz.GetNextToken(); + wxString tk = tkz.GetNextToken(); + + + if (d->tablePattern.Matches(tk)) { + long i; + + if (tk.ToLong(&i)) { + tableID = i; + if ((tableID < 0) || (tableID >= numberOfTables)) { + wxLogVerbose(wxT("invalid table ID %d"), tableID); + return; + } + } else { + return; // not a valid number + } - if (! d->dbPattern.Matches(value)) - { - return; // no valid key + if (!tkz.HasMoreTokens()) { + return; // received nothing but the tableID + } + + tk = tkz.GetNextToken(); } - //wxLogVerbose(wxT("TABLE %d ") + key + wxT(" ") + value, tableID ); + if (d->datePattern.Matches(tk)) { + if (!tkz.HasMoreTokens()) { + return; // nothing after date string + } + wxString timeToken = tkz.GetNextToken(); - if (tableID == 1) - { - wxMutexLocker lock(d->rptrMapMutex); + if (! d->timePattern.Matches(timeToken)) { + return; // no time string after date string + } - IRCDDBAppRptrObject newRptr(dt, key, value); + wxDateTime dt; - d->rptrMap[key] = newRptr; + if (dt.ParseFormat(tk + wxT(" ") + timeToken, wxT("%Y-%m-%d %H:%M:%S")) == NULL) { + return; // date+time parsing failed + } - if (d->initReady) - { - wxString arearp_cs = key; - wxString zonerp_cs = value; + if ((tableID == 0) || (tableID == 1)) { + if (!tkz.HasMoreTokens()) { + return; // nothing after time string + } - arearp_cs.Replace(wxT("_"), wxT(" ")); - zonerp_cs.Replace(wxT("_"), wxT(" ")); - zonerp_cs.SetChar(7, wxT('G')); + wxString key = tkz.GetNextToken(); - IRCMessage * m2 = new IRCMessage(wxT("IDRT_REPEATER")); - m2->addParam(arearp_cs); - m2->addParam(zonerp_cs); - m2->addParam(getIPAddress(value)); - d->replyQ.putMessage(m2); - } - } - else if ((tableID == 0) && d->initReady) - { - wxMutexLocker lock(d->rptrMapMutex); - - wxString userCallsign = key; - wxString arearp_cs = value; - wxString zonerp_cs; - wxString ip_addr; - - userCallsign.Replace(wxT("_"), wxT(" ")); - arearp_cs.Replace(wxT("_"), wxT(" ")); - - if (d->rptrMap.count(value) == 1) - { - IRCDDBAppRptrObject o = d->rptrMap[value]; - zonerp_cs = o.zonerp_cs; - zonerp_cs.Replace(wxT("_"), wxT(" ")); - zonerp_cs.SetChar(7, wxT('G')); - - ip_addr = getIPAddress(o.zonerp_cs); - } - - IRCMessage * m2 = new IRCMessage(wxT("IDRT_USER")); - m2->addParam(userCallsign); - m2->addParam(arearp_cs); - m2->addParam(zonerp_cs); - m2->addParam(ip_addr); - m2->addParam(tk + wxT(" ") + timeToken); - d->replyQ.putMessage(m2); + if (! d->dbPattern.Matches(key)) { + return; // no valid key + } - } + if (!tkz.HasMoreTokens()) { + return; // nothing after time string + } + + wxString value = tkz.GetNextToken(); + + if (! d->dbPattern.Matches(value)) { + return; // no valid key + } + + //wxLogVerbose(wxT("TABLE %d ") + key + wxT(" ") + value, tableID ); + + + if (tableID == 1) { + wxMutexLocker lock(d->rptrMapMutex); + + IRCDDBAppRptrObject newRptr(dt, key, value); + + d->rptrMap[key] = newRptr; + + if (d->initReady) { + wxString arearp_cs = key; + wxString zonerp_cs = value; + + arearp_cs.Replace(wxT("_"), wxT(" ")); + zonerp_cs.Replace(wxT("_"), wxT(" ")); + zonerp_cs.SetChar(7, wxT('G')); + IRCMessage * m2 = new IRCMessage(wxT("IDRT_REPEATER")); + m2->addParam(arearp_cs); + m2->addParam(zonerp_cs); + m2->addParam(getIPAddress(value)); + d->replyQ.putMessage(m2); + } + } else if ((tableID == 0) && d->initReady) { + wxMutexLocker lock(d->rptrMapMutex); - } - } + wxString userCallsign = key; + wxString arearp_cs = value; + wxString zonerp_cs; + wxString ip_addr; + + userCallsign.Replace(wxT("_"), wxT(" ")); + arearp_cs.Replace(wxT("_"), wxT(" ")); + + if (d->rptrMap.count(value) == 1) { + IRCDDBAppRptrObject o = d->rptrMap[value]; + zonerp_cs = o.zonerp_cs; + zonerp_cs.Replace(wxT("_"), wxT(" ")); + zonerp_cs.SetChar(7, wxT('G')); + + ip_addr = getIPAddress(o.zonerp_cs); + } + + IRCMessage * m2 = new IRCMessage(wxT("IDRT_USER")); + m2->addParam(userCallsign); + m2->addParam(arearp_cs); + m2->addParam(zonerp_cs); + m2->addParam(ip_addr); + m2->addParam(tk + wxT(" ") + timeToken); + d->replyQ.putMessage(m2); + + } + + + } + } } static wxString getTableIDString( int tableID, bool spaceBeforeNumber ) { - if (tableID == 0) - { - return wxT(""); - } - else if ((tableID > 0) && (tableID < numberOfTables)) - { - if (spaceBeforeNumber) - { - return wxString::Format(wxT(" %d"),tableID); - } - else - { - return wxString::Format(wxT("%d "),tableID); - } - } - else - { - return wxT(" TABLE_ID_OUT_OF_RANGE "); - } + if (tableID == 0) { + return wxT(""); + } else if ((tableID > 0) && (tableID < numberOfTables)) { + if (spaceBeforeNumber) { + return wxString::Format(wxT(" %d"),tableID); + } else { + return wxString::Format(wxT("%d "),tableID); + } + } else { + return wxT(" TABLE_ID_OUT_OF_RANGE "); + } } void IRCDDBApp::msgQuery (IRCMessage * m) { - if (m->getPrefixNick().StartsWith(wxT("s-")) && (m->numParams >= 2)) // server msg - { - wxString msg = m->params[1]; - wxStringTokenizer tkz(msg); - - if (!tkz.HasMoreTokens()) - { - return; // no text in message - } - - wxString cmd = tkz.GetNextToken(); - - if (cmd.IsSameAs(wxT("UPDATE"))) - { - wxString restOfLine = tkz.GetString(); - doUpdate(restOfLine); - } - else if (cmd.IsSameAs(wxT("LIST_END"))) - { - if (d->state == 5) // if in sendlist processing state - { - d->state = 3; // get next table - } - } - else if (cmd.IsSameAs(wxT("LIST_MORE"))) - { - if (d->state == 5) // if in sendlist processing state - { - d->state = 4; // send next SENDLIST - } - } - else if (cmd.IsSameAs(wxT("NOT_FOUND"))) - { - wxString callsign; - wxString restOfLine = tkz.GetString(); - doNotFound(restOfLine, callsign); - - if (callsign.Len() > 0) - { - callsign.Replace(wxT("_"), wxT(" ")); - - IRCMessage * m2 = new IRCMessage(wxT("IDRT_USER")); - m2->addParam(callsign); - m2->addParam(wxT("")); - m2->addParam(wxT("")); - m2->addParam(wxT("")); - m2->addParam(wxT("")); - d->replyQ.putMessage(m2); - } - } - } + if (m->getPrefixNick().StartsWith(wxT("s-")) && (m->numParams >= 2)) { // server msg + wxString msg = m->params[1]; + wxStringTokenizer tkz(msg); + + if (!tkz.HasMoreTokens()) { + return; // no text in message + } + + wxString cmd = tkz.GetNextToken(); + + if (cmd.IsSameAs(wxT("UPDATE"))) { + wxString restOfLine = tkz.GetString(); + doUpdate(restOfLine); + } else if (cmd.IsSameAs(wxT("LIST_END"))) { + if (d->state == 5) { // if in sendlist processing state + d->state = 3; // get next table + } + } else if (cmd.IsSameAs(wxT("LIST_MORE"))) { + if (d->state == 5) { // if in sendlist processing state + d->state = 4; // send next SENDLIST + } + } else if (cmd.IsSameAs(wxT("NOT_FOUND"))) { + wxString callsign; + wxString restOfLine = tkz.GetString(); + doNotFound(restOfLine, callsign); + + if (callsign.Len() > 0) { + callsign.Replace(wxT("_"), wxT(" ")); + + IRCMessage * m2 = new IRCMessage(wxT("IDRT_USER")); + m2->addParam(callsign); + m2->addParam(wxT("")); + m2->addParam(wxT("")); + m2->addParam(wxT("")); + m2->addParam(wxT("")); + d->replyQ.putMessage(m2); + } + } + } } - - + + void IRCDDBApp::setSendQ( IRCMessageQueue * s ) { - d->sendQ = s; + d->sendQ = s; } - + IRCMessageQueue * IRCDDBApp::getSendQ() { - return d->sendQ; + return d->sendQ; } - - + + static wxString getLastEntryTime(int tableID) { - if (tableID == 1) - { - wxString max = IRCDDBAppRptrObject::maxTime.Format( wxT("%Y-%m-%d %H:%M:%S") ); - return max; - } + if (tableID == 1) { + wxString max = IRCDDBAppRptrObject::maxTime.Format( wxT("%Y-%m-%d %H:%M:%S") ); + return max; + } - return wxT("DBERROR"); + return wxT("DBERROR"); } static bool needsDatabaseUpdate( int tableID ) { - return (tableID == 1); + return (tableID == 1); } - - + + wxThread::ExitCode IRCDDBApp::Entry() { - int sendlistTableID = 0; - - while (!d->terminateThread) - { - - if (d->timer > 0) - { - d->timer --; - } - - switch(d->state) - { - case 0: // wait for network to start - - if (getSendQ() != NULL) - { - d->state = 1; - } - break; - - case 1: - // connect to db - d->state = 2; - d->timer = 200; - break; - - case 2: // choose server - wxLogVerbose(wxT("IRCDDBApp: state=2 choose new 's-'-user")); - if (getSendQ() == NULL) - { - d->state = 10; - } - else - { - if (findServerUser()) - { - sendlistTableID = numberOfTables; - - d->state = 3; // next: send "SENDLIST" - } - else if (d->timer == 0) - { - d->state = 10; - IRCMessage * m = new IRCMessage(wxT("QUIT")); - - m->addParam(wxT("no op user with 's-' found.")); - - IRCMessageQueue * q = getSendQ(); - if (q != NULL) - { - q->putMessage(m); - } - } - } - break; - - case 3: - if (getSendQ() == NULL) - { - d->state = 10; // disconnect DB - } - else - { - sendlistTableID --; - if (sendlistTableID < 0) - { - d->state = 6; // end of sendlist - } - else - { - wxLogVerbose(wxT("IRCDDBApp: state=3 tableID=%d"), sendlistTableID); - d->state = 4; // send "SENDLIST" - d->timer = 900; // 15 minutes max for update - } - } - break; - - case 4: - if (getSendQ() == NULL) - { - d->state = 10; // disconnect DB - } - else - { - if (needsDatabaseUpdate(sendlistTableID)) - { - IRCMessage * m = new IRCMessage(d->currentServer, - wxT("SENDLIST") + getTableIDString(sendlistTableID, true) - + wxT(" ") + getLastEntryTime(sendlistTableID) ); - - IRCMessageQueue * q = getSendQ(); - if (q != NULL) - { - q->putMessage(m); - } - - d->state = 5; // wait for answers - } - else - { - d->state = 3; // don't send SENDLIST for this table, go to next table - } - } - break; - - case 5: // sendlist processing - if (getSendQ() == NULL) - { - d->state = 10; // disconnect DB - } - else if (d->timer == 0) - { - d->state = 10; // disconnect DB - IRCMessage * m = new IRCMessage(wxT("QUIT")); - - m->addParam(wxT("timeout SENDLIST")); - - IRCMessageQueue * q = getSendQ(); - if (q != NULL) - { - q->putMessage(m); - } - - } - break; - - case 6: - if (getSendQ() == NULL) - { - d->state = 10; // disconnect DB - } - else - { - wxLogVerbose(wxT( "IRCDDBApp: state=6 initialization completed")); - - d->infoTimer = 2; - - d->initReady = true; - d->state = 7; - } - break; - - - case 7: // standby state after initialization - if (getSendQ() == NULL) - { - d->state = 10; // disconnect DB - } - - if (d->infoTimer > 0) - { - d->infoTimer --; - - if (d->infoTimer == 0) - { - if (d->rptrLocation.Len() > 0) - { - IRCMessage * m = new IRCMessage(d->currentServer, - wxT("IRCDDB QTH: ") + d->rptrLocation); - - IRCMessageQueue * q = getSendQ(); - if (q != NULL) - { - q->putMessage(m); - } - } + int sendlistTableID = 0; + + while (!d->terminateThread) { + + if (d->timer > 0) { + d->timer --; + } + + switch(d->state) { + case 0: // wait for network to start + + if (getSendQ() != NULL) { + d->state = 1; + } + break; + + case 1: + // connect to db + d->state = 2; + d->timer = 200; + break; + + case 2: // choose server + wxLogVerbose(wxT("IRCDDBApp: state=2 choose new 's-'-user")); + if (getSendQ() == NULL) { + d->state = 10; + } else { + if (findServerUser()) { + sendlistTableID = numberOfTables; + + d->state = 3; // next: send "SENDLIST" + } else if (d->timer == 0) { + d->state = 10; + IRCMessage * m = new IRCMessage(wxT("QUIT")); + + m->addParam(wxT("no op user with 's-' found.")); + + IRCMessageQueue * q = getSendQ(); + if (q != NULL) { + q->putMessage(m); + } + } + } + break; + + case 3: + if (getSendQ() == NULL) { + d->state = 10; // disconnect DB + } else { + sendlistTableID --; + if (sendlistTableID < 0) { + d->state = 6; // end of sendlist + } else { + wxLogVerbose(wxT("IRCDDBApp: state=3 tableID=%d"), sendlistTableID); + d->state = 4; // send "SENDLIST" + d->timer = 900; // 15 minutes max for update + } + } + break; + + case 4: + if (getSendQ() == NULL) { + d->state = 10; // disconnect DB + } else { + if (needsDatabaseUpdate(sendlistTableID)) { + IRCMessage * m = new IRCMessage(d->currentServer, + wxT("SENDLIST") + getTableIDString(sendlistTableID, true) + + wxT(" ") + getLastEntryTime(sendlistTableID) ); + + IRCMessageQueue * q = getSendQ(); + if (q != NULL) { + q->putMessage(m); + } + + d->state = 5; // wait for answers + } else { + d->state = 3; // don't send SENDLIST for this table, go to next table + } + } + break; + + case 5: // sendlist processing + if (getSendQ() == NULL) { + d->state = 10; // disconnect DB + } else if (d->timer == 0) { + d->state = 10; // disconnect DB + IRCMessage * m = new IRCMessage(wxT("QUIT")); + + m->addParam(wxT("timeout SENDLIST")); + + IRCMessageQueue * q = getSendQ(); + if (q != NULL) { + q->putMessage(m); + } + + } + break; + + case 6: + if (getSendQ() == NULL) { + d->state = 10; // disconnect DB + } else { + wxLogVerbose(wxT( "IRCDDBApp: state=6 initialization completed")); + + d->infoTimer = 2; + + d->initReady = true; + d->state = 7; + } + break; + + + case 7: // standby state after initialization + if (getSendQ() == NULL) { + d->state = 10; // disconnect DB + } + + if (d->infoTimer > 0) { + d->infoTimer --; + + if (d->infoTimer == 0) { + if (d->rptrLocation.Len() > 0) { + IRCMessage * m = new IRCMessage(d->currentServer, + wxT("IRCDDB QTH: ") + d->rptrLocation); + + IRCMessageQueue * q = getSendQ(); + if (q != NULL) { + q->putMessage(m); + } + } + + if (d->rptrInfoURL.Len() > 0) { + IRCMessage * m = new IRCMessage(d->currentServer, + wxT("IRCDDB URL: ") + d->rptrInfoURL); + + IRCMessageQueue * q = getSendQ(); + if (q != NULL) { + q->putMessage(m); + } + } + + wxMutexLocker lock(d->moduleMapMutex); + + IRCDDBAppModuleMap::iterator it; + for( it = d->moduleMap.begin(); it != d->moduleMap.end(); ++it ) { + wxString value = it->second; + IRCMessage * m = new IRCMessage(d->currentServer, + wxT("IRCDDB QRG: ") + value); + + IRCMessageQueue * q = getSendQ(); + if (q != NULL) { + q->putMessage(m); + } + } + } + } + + if (d->wdTimer > 0) { + d->wdTimer --; + if (d->wdTimer == 0) { + d->wdTimer = 900; // 15 minutes + + IRCMessage * m = new IRCMessage(d->currentServer, + wxT("IRCDDB WATCHDOG: ") + getCurrentTime() + + wxT(" ") + d->wdInfo.Mid(0,120) + + wxString::Format(wxT(" %d"), d->wdCounter )); + + IRCMessageQueue * q = getSendQ(); + if (q != NULL) { + q->putMessage(m); + d->wdCounter = 0; + } + } + } + break; + + case 10: + // disconnect db + d->state = 0; + d->timer = 0; + d->initReady = false; + break; - if (d->rptrInfoURL.Len() > 0) - { - IRCMessage * m = new IRCMessage(d->currentServer, - wxT("IRCDDB URL: ") + d->rptrInfoURL); + } - IRCMessageQueue * q = getSendQ(); - if (q != NULL) - { - q->putMessage(m); - } - } + wxThread::Sleep(1000); - wxMutexLocker lock(d->moduleMapMutex); - IRCDDBAppModuleMap::iterator it; - for( it = d->moduleMap.begin(); it != d->moduleMap.end(); ++it ) - { - wxString value = it->second; - IRCMessage * m = new IRCMessage(d->currentServer, - wxT("IRCDDB QRG: ") + value); - IRCMessageQueue * q = getSendQ(); - if (q != NULL) - { - q->putMessage(m); - } - } - } - } - - if (d->wdTimer > 0) - { - d->wdTimer --; - if (d->wdTimer == 0) - { - d->wdTimer = 900; // 15 minutes - - IRCMessage * m = new IRCMessage(d->currentServer, - wxT("IRCDDB WATCHDOG: ") + getCurrentTime() + - wxT(" ") + d->wdInfo.Mid(0,120) + - wxString::Format(wxT(" %d"), d->wdCounter )); - - IRCMessageQueue * q = getSendQ(); - if (q != NULL) - { - q->putMessage(m); - d->wdCounter = 0; - } - } - } - break; - - case 10: - // disconnect db - d->state = 0; - d->timer = 0; - d->initReady = false; - break; - - } - - wxThread::Sleep(1000); - - - - - } // while - - return 0; + + } // while + + return 0; } // Entry() - + diff --git a/IRCDDBApp.h b/IRCDDBApp.h index fc5c7d8..2d3087a 100644 --- a/IRCDDBApp.h +++ b/IRCDDBApp.h @@ -32,66 +32,66 @@ class IRCDDBAppPrivate; class IRCDDBApp : public IRCApplication, wxThread { - public: - IRCDDBApp(const wxString& update_channel); +public: + IRCDDBApp(const wxString& update_channel); - virtual ~IRCDDBApp(); + virtual ~IRCDDBApp(); - virtual void userJoin (const wxString& nick, const wxString& name, const wxString& host); + virtual void userJoin (const wxString& nick, const wxString& name, const wxString& host); - virtual void userLeave (const wxString& nick); + virtual void userLeave (const wxString& nick); - virtual void userChanOp (const wxString& nick, bool op); - virtual void userListReset(); + virtual void userChanOp (const wxString& nick, bool op); + virtual void userListReset(); - virtual void msgChannel (IRCMessage * m); - virtual void msgQuery (IRCMessage * m); + virtual void msgChannel (IRCMessage * m); + virtual void msgQuery (IRCMessage * m); - virtual void setCurrentNick(const wxString& nick); - virtual void setTopic(const wxString& topic); + virtual void setCurrentNick(const wxString& nick); + virtual void setTopic(const wxString& topic); - virtual void setBestServer(const wxString& ircUser); + virtual void setBestServer(const wxString& ircUser); - virtual void setSendQ( IRCMessageQueue * s ); - virtual IRCMessageQueue * getSendQ (); + virtual void setSendQ( IRCMessageQueue * s ); + virtual IRCMessageQueue * getSendQ (); - bool startWork(); - void stopWork(); + bool startWork(); + void stopWork(); - IRCDDB_RESPONSE_TYPE getReplyMessageType(); + IRCDDB_RESPONSE_TYPE getReplyMessageType(); - IRCMessage * getReplyMessage(); + IRCMessage * getReplyMessage(); - bool findUser ( const wxString& s ); - bool findRepeater ( const wxString& s ); - bool findGateway ( const wxString& s ); + bool findUser ( const wxString& s ); + bool findRepeater ( const wxString& s ); + bool findGateway ( const wxString& s ); - bool sendHeard(const wxString& myCall, const wxString& myCallExt, - const wxString& yourCall, const wxString& rpt1, - const wxString& rpt2, unsigned char flag1, - unsigned char flag2, unsigned char flag3, - const wxString& destination, const wxString& tx_msg, - const wxString& tx_stats); + bool sendHeard(const wxString& myCall, const wxString& myCallExt, + const wxString& yourCall, const wxString& rpt1, + const wxString& rpt2, unsigned char flag1, + unsigned char flag2, unsigned char flag3, + const wxString& destination, const wxString& tx_msg, + const wxString& tx_stats); - int getConnectionState(); + int getConnectionState(); - void rptrQRG( const wxString& module, double txFrequency, double duplexShift, - double range, double agl ); + void rptrQRG( const wxString& module, double txFrequency, double duplexShift, + double range, double agl ); - void rptrQTH( double latitude, double longitude, const wxString& desc1, - const wxString& desc2, const wxString& infoURL ); + void rptrQTH( double latitude, double longitude, const wxString& desc1, + const wxString& desc2, const wxString& infoURL ); - void kickWatchdog( const wxString& wdInfo ); + void kickWatchdog( const wxString& wdInfo ); - protected: - virtual wxThread::ExitCode Entry(); +protected: + virtual wxThread::ExitCode Entry(); - private: - void doUpdate ( wxString& msg ); - void doNotFound ( wxString& msg, wxString& retval ); - wxString getIPAddress( wxString& zonerp_cs ); - bool findServerUser(); - IRCDDBAppPrivate * d; +private: + void doUpdate ( wxString& msg ); + void doNotFound ( wxString& msg, wxString& retval ); + wxString getIPAddress( wxString& zonerp_cs ); + bool findServerUser(); + IRCDDBAppPrivate * d; }; diff --git a/IRCMessage.cpp b/IRCMessage.cpp index b8a9ebd..d4a3b75 100644 --- a/IRCMessage.cpp +++ b/IRCMessage.cpp @@ -25,24 +25,24 @@ along with this program. If not, see . IRCMessage::IRCMessage () { - numParams = 0; - prefixParsed = false; + numParams = 0; + prefixParsed = false; } IRCMessage::IRCMessage ( const wxString& toNick, const wxString& msg ) { - command = wxT("PRIVMSG"); - numParams = 2; - params.Add( toNick ); - params.Add( msg ); - prefixParsed = false; + command = wxT("PRIVMSG"); + numParams = 2; + params.Add( toNick ); + params.Add( msg ); + prefixParsed = false; } IRCMessage::IRCMessage ( const wxString& cmd ) { - command = cmd; - numParams = 0; - prefixParsed = false; + command = cmd; + numParams = 0; + prefixParsed = false; } IRCMessage::~IRCMessage() @@ -52,126 +52,114 @@ IRCMessage::~IRCMessage() void IRCMessage::addParam( const wxString& p ) { - params.Add( p ); - numParams = params.GetCount(); + params.Add( p ); + numParams = params.GetCount(); } int IRCMessage::getParamCount() { - return params.GetCount(); + return params.GetCount(); } wxString IRCMessage::getParam( int pos ) { - return params[pos]; + return params[pos]; } wxString IRCMessage::getCommand() { - return command; + return command; } - + void IRCMessage::parsePrefix() { - unsigned int i; - - for (i=0; i < 3; i++) - { - prefixComponents.Add(wxT("")); - } - - int state = 0; - - for (i=0; i < prefix.Len(); i++) - { - wxChar c = prefix.GetChar(i); - - switch (c) - { - case wxT('!'): - state = 1; // next is name - break; - - case wxT('@'): - state = 2; // next is host - break; - - default: - prefixComponents[state].Append(c); - break; - } - } - - prefixParsed = true; + unsigned int i; + + for (i=0; i < 3; i++) { + prefixComponents.Add(wxT("")); + } + + int state = 0; + + for (i=0; i < prefix.Len(); i++) { + wxChar c = prefix.GetChar(i); + + switch (c) { + case wxT('!'): + state = 1; // next is name + break; + + case wxT('@'): + state = 2; // next is host + break; + + default: + prefixComponents[state].Append(c); + break; + } + } + + prefixParsed = true; } wxString& IRCMessage::getPrefixNick() { - if (!prefixParsed) - { - parsePrefix(); - } - - return prefixComponents[0]; + if (!prefixParsed) { + parsePrefix(); + } + + return prefixComponents[0]; } wxString& IRCMessage::getPrefixName() { - if (!prefixParsed) - { - parsePrefix(); - } - - return prefixComponents[1]; + if (!prefixParsed) { + parsePrefix(); + } + + return prefixComponents[1]; } wxString& IRCMessage::getPrefixHost() { - if (!prefixParsed) - { - parsePrefix(); - } - - return prefixComponents[2]; + if (!prefixParsed) { + parsePrefix(); + } + + return prefixComponents[2]; } void IRCMessage::composeMessage ( wxString& output ) { #if defined(DEBUG_IRC) - wxString d = wxT("T [") + prefix + wxT("] [") + command + wxT("]"); - for (int i=0; i < numParams; i++) - { - d.Append(wxT(" [") + params[i] + wxT("]") ); - } - d.Replace(wxT("%"), wxT("%%"), true); - d.Replace(wxT("\\"), wxT("\\\\"), true); - wxLogVerbose(d); + wxString d = wxT("T [") + prefix + wxT("] [") + command + wxT("]"); + for (int i=0; i < numParams; i++) { + d.Append(wxT(" [") + params[i] + wxT("]") ); + } + d.Replace(wxT("%"), wxT("%%"), true); + d.Replace(wxT("\\"), wxT("\\\\"), true); + wxLogVerbose(d); #endif - wxString o; + wxString o; - if (prefix.Len() > 0) - { - o = wxT(":") + prefix + wxT(" "); - } + if (prefix.Len() > 0) { + o = wxT(":") + prefix + wxT(" "); + } - o.Append(command); + o.Append(command); - for (int i=0; i < numParams; i++) - { - if (i == (numParams - 1)) - { - o.Append(wxT(" :") + params[i]); - } - else - { - o.Append(wxT(" ") + params[i]); - } - } + for (int i=0; i < numParams; i++) { + if (i == (numParams - 1)) { + o.Append(wxT(" :") + params[i]); + } else { + o.Append(wxT(" ") + params[i]); + } + } - o.Append(wxT("\r\n")); + o.Append(wxT("\r\n")); - output = o; + output = o; } diff --git a/IRCMessage.h b/IRCMessage.h index 25c33af..b608a8a 100644 --- a/IRCMessage.h +++ b/IRCMessage.h @@ -27,44 +27,44 @@ along with this program. If not, see . class IRCMessage { - public: +public: - IRCMessage(); + IRCMessage(); - IRCMessage( const wxString& toNick, const wxString& msg ); + IRCMessage( const wxString& toNick, const wxString& msg ); - IRCMessage( const wxString& command ); + IRCMessage( const wxString& command ); - ~IRCMessage(); + ~IRCMessage(); - wxString prefix; - wxString command; - wxArrayString params; + wxString prefix; + wxString command; + wxArrayString params; - int numParams; + int numParams; - wxString& getPrefixNick(); - wxString& getPrefixName(); - wxString& getPrefixHost(); + wxString& getPrefixNick(); + wxString& getPrefixName(); + wxString& getPrefixHost(); - void composeMessage ( wxString& output ); + void composeMessage ( wxString& output ); - void addParam( const wxString& p ); + void addParam( const wxString& p ); - wxString getCommand(); + wxString getCommand(); - wxString getParam( int pos ); + wxString getParam( int pos ); - int getParamCount(); + int getParamCount(); - private: +private: - void parsePrefix(); + void parsePrefix(); - wxArrayString prefixComponents; - bool prefixParsed; + wxArrayString prefixComponents; + bool prefixParsed; }; diff --git a/IRCMessageQueue.cpp b/IRCMessageQueue.cpp index b42d798..2b37e17 100644 --- a/IRCMessageQueue.cpp +++ b/IRCMessageQueue.cpp @@ -24,112 +24,103 @@ along with this program. If not, see . IRCMessageQueue::IRCMessageQueue() { - eof = false; - first = NULL; - last = NULL; + eof = false; + first = NULL; + last = NULL; } IRCMessageQueue::~IRCMessageQueue() { - while (messageAvailable()) - { - IRCMessage * m = getMessage(); + while (messageAvailable()) { + IRCMessage * m = getMessage(); - delete m; - } + delete m; + } } bool IRCMessageQueue::isEOF() { - return eof; + return eof; } void IRCMessageQueue::signalEOF() { - eof = true; + eof = true; } bool IRCMessageQueue::messageAvailable() { - wxMutexLocker lock(accessMutex); + wxMutexLocker lock(accessMutex); - return (first != NULL); + return (first != NULL); } IRCMessage * IRCMessageQueue::peekFirst() { - wxMutexLocker lock(accessMutex); + wxMutexLocker lock(accessMutex); - IRCMessageQueueItem * k = first; + IRCMessageQueueItem * k = first; - if ( k == NULL ) - { - return NULL; - } + if ( k == NULL ) { + return NULL; + } - return k->msg; + return k->msg; } IRCMessage * IRCMessageQueue::getMessage() { - wxMutexLocker lock(accessMutex); + wxMutexLocker lock(accessMutex); - IRCMessageQueueItem * k; + IRCMessageQueueItem * k; - if (first == NULL) - { - return NULL; - } + if (first == NULL) { + return NULL; + } - k = first; + k = first; - first = k -> next; + first = k -> next; - if (k -> next == NULL) - { - last = NULL; - } - else - { - k -> next -> prev = NULL; - } + if (k -> next == NULL) { + last = NULL; + } else { + k -> next -> prev = NULL; + } - IRCMessage * msg = k -> msg; + IRCMessage * msg = k -> msg; - delete k; + delete k; - return msg; + return msg; } void IRCMessageQueue::putMessage( IRCMessage * m ) { - wxMutexLocker lock(accessMutex); + wxMutexLocker lock(accessMutex); - // wxLogVerbose(wxT("IRCMessageQueue::putMessage")); + // wxLogVerbose(wxT("IRCMessageQueue::putMessage")); - IRCMessageQueueItem * k = new IRCMessageQueueItem(m); + IRCMessageQueueItem * k = new IRCMessageQueueItem(m); - k -> prev = last; - k -> next = NULL; + k -> prev = last; + k -> next = NULL; - if (last == NULL) - { - first = k; - } - else - { - last -> next = k; - } + if (last == NULL) { + first = k; + } else { + last -> next = k; + } - last = k; + last = k; } diff --git a/IRCMessageQueue.h b/IRCMessageQueue.h index b405a40..78ebee4 100644 --- a/IRCMessageQueue.h +++ b/IRCMessageQueue.h @@ -29,51 +29,49 @@ along with this program. If not, see . class IRCMessageQueueItem { - public: - IRCMessageQueueItem( IRCMessage * m ) - { - msg = m; - } - - ~IRCMessageQueueItem() - { - } - - IRCMessage * msg; - - IRCMessageQueueItem * prev; - IRCMessageQueueItem * next; +public: + IRCMessageQueueItem( IRCMessage * m ) { + msg = m; + } + + ~IRCMessageQueueItem() { + } + + IRCMessage * msg; + + IRCMessageQueueItem * prev; + IRCMessageQueueItem * next; }; class IRCMessageQueue { - public: - IRCMessageQueue(); +public: + IRCMessageQueue(); + + ~IRCMessageQueue(); - ~IRCMessageQueue(); + bool isEOF(); - bool isEOF(); + void signalEOF(); - void signalEOF(); + bool messageAvailable(); - bool messageAvailable(); + IRCMessage * getMessage(); - IRCMessage * getMessage(); + IRCMessage * peekFirst(); - IRCMessage * peekFirst(); + void putMessage ( IRCMessage * m ); - void putMessage ( IRCMessage * m ); +private: - private: + bool eof; - bool eof; + IRCMessageQueueItem * first; + IRCMessageQueueItem * last; - IRCMessageQueueItem * first; - IRCMessageQueueItem * last; + wxMutex accessMutex; - wxMutex accessMutex; - }; #endif diff --git a/IRCProtocol.cpp b/IRCProtocol.cpp index 122b687..5b2fccf 100644 --- a/IRCProtocol.cpp +++ b/IRCProtocol.cpp @@ -27,51 +27,47 @@ along with this program. If not, see . #define CIRCDDB_VERSION "1.2.4" IRCProtocol::IRCProtocol ( IRCApplication * app, - const wxString& callsign, const wxString& password, const wxString& channel, - const wxString& versionInfo ) + const wxString& callsign, const wxString& password, const wxString& channel, + const wxString& versionInfo ) { - this -> password = password; - this -> channel = channel; - this -> app = app; + this -> password = password; + this -> channel = channel; + this -> app = app; - this->versionInfo = wxT("CIRCDDB:"); - this->versionInfo.Append(wxT(CIRCDDB_VERSION)); + this->versionInfo = wxT("CIRCDDB:"); + this->versionInfo.Append(wxT(CIRCDDB_VERSION)); - if (versionInfo.Len() > 0) - { - this->versionInfo.Append(wxT(" ")); - this->versionInfo.Append(versionInfo); - } + if (versionInfo.Len() > 0) { + this->versionInfo.Append(wxT(" ")); + this->versionInfo.Append(versionInfo); + } - int hyphenPos = callsign.find(wxT('-')); + int hyphenPos = callsign.find(wxT('-')); - if (hyphenPos == wxNOT_FOUND) - { - wxString n; + if (hyphenPos == wxNOT_FOUND) { + wxString n; - n = callsign + wxT("-1"); - nicks.Add(n); - n = callsign + wxT("-2"); - nicks.Add(n); - n = callsign + wxT("-3"); - nicks.Add(n); - n = callsign + wxT("-4"); - nicks.Add(n); - } - else - { - nicks.Add(callsign); - } + n = callsign + wxT("-1"); + nicks.Add(n); + n = callsign + wxT("-2"); + nicks.Add(n); + n = callsign + wxT("-3"); + nicks.Add(n); + n = callsign + wxT("-4"); + nicks.Add(n); + } else { + nicks.Add(callsign); + } - name = callsign; + name = callsign; - pingTimer = 60; // 30 seconds - state = 0; - timer = 0; + pingTimer = 60; // 30 seconds + state = 0; + timer = 0; - chooseNewNick(); + chooseNewNick(); } IRCProtocol::~IRCProtocol() @@ -80,368 +76,292 @@ IRCProtocol::~IRCProtocol() void IRCProtocol::chooseNewNick() { - int r = rand() % nicks.GetCount(); + int r = rand() % nicks.GetCount(); - currentNick = nicks[r]; + currentNick = nicks[r]; } void IRCProtocol::setNetworkReady( bool b ) { - if (b == true) - { - if (state != 0) - { - wxLogError(wxT("IRCProtocol::setNetworkReady: unexpected state")); - } - - state = 1; - chooseNewNick(); - } - else - { - state = 0; - } + if (b == true) { + if (state != 0) { + wxLogError(wxT("IRCProtocol::setNetworkReady: unexpected state")); + } + + state = 1; + chooseNewNick(); + } else { + state = 0; + } } bool IRCProtocol::processQueues ( IRCMessageQueue * recvQ, IRCMessageQueue * sendQ ) { - if (timer > 0) - { - timer --; - } + if (timer > 0) { + timer --; + } - while (recvQ->messageAvailable()) - { - IRCMessage * m = recvQ -> getMessage(); + while (recvQ->messageAvailable()) { + IRCMessage * m = recvQ -> getMessage(); #if defined(DEBUG_IRC) - wxString d = wxT("R [") + m->prefix + wxT("] [") + m->command + wxT("]"); - for (int i=0; i < m->numParams; i++) - { - d.Append(wxT(" [") + m->params[i] + wxT("]") ); - } - d.Replace(wxT("%"), wxT("%%"), true); - d.Replace(wxT("\\"), wxT("\\\\"), true); - wxLogVerbose(d); + wxString d = wxT("R [") + m->prefix + wxT("] [") + m->command + wxT("]"); + for (int i=0; i < m->numParams; i++) { + d.Append(wxT(" [") + m->params[i] + wxT("]") ); + } + d.Replace(wxT("%"), wxT("%%"), true); + d.Replace(wxT("\\"), wxT("\\\\"), true); + wxLogVerbose(d); #endif - if (m->command.IsSameAs(wxT("004"))) - { - if (state == 4) - { - if (m->params.GetCount() > 1) - { - wxRegEx serverNamePattern(wxT("^grp[1-9]s[1-9].ircDDB$")); - - if (serverNamePattern.Matches( m->params[1] )) - { - app->setBestServer(wxT("s-") + m->params[1].Mid(0,6)); - } - } - state = 5; // next: JOIN - app->setCurrentNick(currentNick); - } - } - else if (m->command.IsSameAs(wxT("PING"))) - { - IRCMessage * m2 = new IRCMessage(); - m2->command = wxT("PONG"); - if (m->params.GetCount() > 0) - { - m2->numParams = 1; - m2->params.Add( m->params[0] ); - } - sendQ -> putMessage(m2); - } - else if (m->command.IsSameAs(wxT("JOIN"))) - { - if ((m->numParams >= 1) && m->params[0].IsSameAs(channel)) - { - if (m->getPrefixNick().IsSameAs(currentNick) && (state == 6)) - { - if (debugChannel.Len() > 0) - { - state = 7; // next: join debug_channel - } - else - { - state = 10; // next: WHO * - } - } - else if (app != NULL) - { - app->userJoin( m->getPrefixNick(), m->getPrefixName(), m->getPrefixHost()); - } - } + if (m->command.IsSameAs(wxT("004"))) { + if (state == 4) { + if (m->params.GetCount() > 1) { + wxRegEx serverNamePattern(wxT("^grp[1-9]s[1-9].ircDDB$")); + + if (serverNamePattern.Matches( m->params[1] )) { + app->setBestServer(wxT("s-") + m->params[1].Mid(0,6)); + } + } + state = 5; // next: JOIN + app->setCurrentNick(currentNick); + } + } else if (m->command.IsSameAs(wxT("PING"))) { + IRCMessage * m2 = new IRCMessage(); + m2->command = wxT("PONG"); + if (m->params.GetCount() > 0) { + m2->numParams = 1; + m2->params.Add( m->params[0] ); + } + sendQ -> putMessage(m2); + } else if (m->command.IsSameAs(wxT("JOIN"))) { + if ((m->numParams >= 1) && m->params[0].IsSameAs(channel)) { + if (m->getPrefixNick().IsSameAs(currentNick) && (state == 6)) { + if (debugChannel.Len() > 0) { + state = 7; // next: join debug_channel + } else { + state = 10; // next: WHO * + } + } else if (app != NULL) { + app->userJoin( m->getPrefixNick(), m->getPrefixName(), m->getPrefixHost()); + } + } + + if ((m->numParams >= 1) && m->params[0].IsSameAs(debugChannel)) { + if (m->getPrefixNick().IsSameAs(currentNick) && (state == 8)) { + state = 10; // next: WHO * + } + } + } else if (m->command.IsSameAs(wxT("PONG"))) { + if (state == 12) { + timer = pingTimer; + state = 11; + } + } else if (m->command.IsSameAs(wxT("PART"))) { + if ((m->numParams >= 1) && m->params[0].IsSameAs(channel)) { + if (app != NULL) { + app->userLeave( m->getPrefixNick() ); + } + } + } else if (m->command.IsSameAs(wxT("KICK"))) { + if ((m->numParams >= 2) && m->params[0].IsSameAs(channel)) { + if (m->params[1].IsSameAs(currentNick)) { + // i was kicked!! + delete m; + return false; + } else if (app != NULL) { + app->userLeave( m->params[1] ); + } + } + } else if (m->command.IsSameAs(wxT("QUIT"))) { + if (app != NULL) { + app->userLeave( m->getPrefixNick() ); + } + } else if (m->command.IsSameAs(wxT("MODE"))) { + if ((m->numParams >= 3) && m->params[0].IsSameAs(channel)) { + if (app != NULL) { + size_t i; + wxString mode = m->params[1]; + + for (i = 1; (i < mode.Len()) && ((size_t) m->numParams >= (i+2)); i++) { + if ( mode[i] == wxT('o') ) { + if ( mode[0] == wxT('+') ) { + app->userChanOp(m->params[i+1], true); + } else if ( mode[0] == wxT('-') ) { + app->userChanOp(m->params[i+1], false); + } + } + } // for + } + } + } else if (m->command.IsSameAs(wxT("PRIVMSG"))) { + if ((m->numParams == 2) && (app != NULL)) { + if (m->params[0].IsSameAs(channel)) { + app->msgChannel(m); + } else if (m->params[0].IsSameAs(currentNick)) { + app->msgQuery(m); + } + } + } else if (m->command.IsSameAs(wxT("352"))) { // WHO list + if ((m->numParams >= 7) && m->params[0].IsSameAs(currentNick) + && m->params[1].IsSameAs(channel)) { + if (app != NULL) { + app->userJoin( m->params[5], m->params[2], m->params[3]); + app->userChanOp ( m->params[5], m->params[6].IsSameAs(wxT("H@"))); + } + } + } else if (m->command.IsSameAs(wxT("433"))) { // nick collision + if (state == 2) { + state = 3; // nick collision, choose new nick + timer = 10; // wait 5 seconds.. + } + } else if (m->command.IsSameAs(wxT("332")) || + m->command.IsSameAs(wxT("TOPIC"))) { // topic + if ((m->numParams == 2) && (app != NULL) && + m->params[0].IsSameAs(channel) ) { + app->setTopic(m->params[1]); + } + } - if ((m->numParams >= 1) && m->params[0].IsSameAs(debugChannel)) - { - if (m->getPrefixNick().IsSameAs(currentNick) && (state == 8)) - { - state = 10; // next: WHO * - } - } - } - else if (m->command.IsSameAs(wxT("PONG"))) - { - if (state == 12) - { - timer = pingTimer; - state = 11; - } - } - else if (m->command.IsSameAs(wxT("PART"))) - { - if ((m->numParams >= 1) && m->params[0].IsSameAs(channel)) - { - if (app != NULL) - { - app->userLeave( m->getPrefixNick() ); - } - } - } - else if (m->command.IsSameAs(wxT("KICK"))) - { - if ((m->numParams >= 2) && m->params[0].IsSameAs(channel)) - { - if (m->params[1].IsSameAs(currentNick)) - { - // i was kicked!! delete m; - return false; - } - else if (app != NULL) - { - app->userLeave( m->params[1] ); - } - } - } - else if (m->command.IsSameAs(wxT("QUIT"))) - { - if (app != NULL) - { - app->userLeave( m->getPrefixNick() ); - } - } - else if (m->command.IsSameAs(wxT("MODE"))) - { - if ((m->numParams >= 3) && m->params[0].IsSameAs(channel)) - { - if (app != NULL) - { - size_t i; - wxString mode = m->params[1]; - - for (i = 1; (i < mode.Len()) && ((size_t) m->numParams >= (i+2)); i++) - { - if ( mode[i] == wxT('o') ) - { - if ( mode[0] == wxT('+') ) - { - app->userChanOp(m->params[i+1], true); - } - else if ( mode[0] == wxT('-') ) - { - app->userChanOp(m->params[i+1], false); - } - } - } // for - } - } - } - else if (m->command.IsSameAs(wxT("PRIVMSG"))) - { - if ((m->numParams == 2) && (app != NULL)) - { - if (m->params[0].IsSameAs(channel)) - { - app->msgChannel(m); } - else if (m->params[0].IsSameAs(currentNick)) - { - app->msgQuery(m); - } - } - } - else if (m->command.IsSameAs(wxT("352"))) // WHO list - { - if ((m->numParams >= 7) && m->params[0].IsSameAs(currentNick) - && m->params[1].IsSameAs(channel)) - { - if (app != NULL) - { - app->userJoin( m->params[5], m->params[2], m->params[3]); - app->userChanOp ( m->params[5], m->params[6].IsSameAs(wxT("H@"))); + + IRCMessage * m; + + switch (state) { + case 1: + m = new IRCMessage(); + m->command = wxT("PASS"); + m->numParams = 1; + m->params.Add(password); + sendQ->putMessage(m); + + m = new IRCMessage(); + m->command = wxT("NICK"); + m->numParams = 1; + m->params.Add(currentNick); + sendQ->putMessage(m); + + timer = 10; // wait for possible nick collision message + state = 2; + break; + + case 2: + if (timer == 0) { + m = new IRCMessage(); + m->command = wxT("USER"); + m->numParams = 4; + m->params.Add(name); + m->params.Add(wxT("0")); + m->params.Add(wxT("*")); + m->params.Add(versionInfo); + sendQ->putMessage(m); + + timer = 30; + state = 4; // wait for login message + } + break; + + case 3: + if (timer == 0) { + chooseNewNick(); + m = new IRCMessage(); + m->command = wxT("NICK"); + m->numParams = 1; + m->params.Add(currentNick); + sendQ->putMessage(m); + + timer = 10; // wait for possible nick collision message + state = 2; + } + break; + + case 4: + if (timer == 0) { + // no login message received -> disconnect + return false; + } + break; + + case 5: + m = new IRCMessage(); + m->command = wxT("JOIN"); + m->numParams = 1; + m->params.Add(channel); + sendQ->putMessage(m); + + timer = 30; + state = 6; // wait for join message + break; + + case 6: + if (timer == 0) { + // no join message received -> disconnect + return false; + } + break; + + case 7: + if (debugChannel.Len() == 0) { + return false; // this state cannot be processed if there is no debug_channel + } + + m = new IRCMessage(); + m->command = wxT("JOIN"); + m->numParams = 1; + m->params.Add(debugChannel); + sendQ->putMessage(m); + + timer = 30; + state = 8; // wait for join message + break; + + case 8: + if (timer == 0) { + // no join message received -> disconnect + return false; + } + break; + + case 10: + m = new IRCMessage(); + m->command = wxT("WHO"); + m->numParams = 2; + m->params.Add(channel); + m->params.Add(wxT("*")); + sendQ->putMessage(m); + + timer = pingTimer; + state = 11; // wait for timer and then send ping + + if (app != NULL) { + app->setSendQ(sendQ); // this switches the application on + } + break; + + case 11: + if (timer == 0) { + m = new IRCMessage(); + m->command = wxT("PING"); + m->numParams = 1; + m->params.Add(currentNick); + sendQ->putMessage(m); + + timer = pingTimer; + state = 12; // wait for pong + } + break; + + case 12: + if (timer == 0) { + // no pong message received -> disconnect + return false; + } + break; } - } - } - else if (m->command.IsSameAs(wxT("433"))) // nick collision - { - if (state == 2) - { - state = 3; // nick collision, choose new nick - timer = 10; // wait 5 seconds.. - } - } - else if (m->command.IsSameAs(wxT("332")) || - m->command.IsSameAs(wxT("TOPIC"))) // topic - { - if ((m->numParams == 2) && (app != NULL) && - m->params[0].IsSameAs(channel) ) - { - app->setTopic(m->params[1]); - } - } - - delete m; - } - - IRCMessage * m; - - switch (state) - { - case 1: - m = new IRCMessage(); - m->command = wxT("PASS"); - m->numParams = 1; - m->params.Add(password); - sendQ->putMessage(m); - - m = new IRCMessage(); - m->command = wxT("NICK"); - m->numParams = 1; - m->params.Add(currentNick); - sendQ->putMessage(m); - - timer = 10; // wait for possible nick collision message - state = 2; - break; - - case 2: - if (timer == 0) - { - m = new IRCMessage(); - m->command = wxT("USER"); - m->numParams = 4; - m->params.Add(name); - m->params.Add(wxT("0")); - m->params.Add(wxT("*")); - m->params.Add(versionInfo); - sendQ->putMessage(m); - - timer = 30; - state = 4; // wait for login message - } - break; - - case 3: - if (timer == 0) - { - chooseNewNick(); - m = new IRCMessage(); - m->command = wxT("NICK"); - m->numParams = 1; - m->params.Add(currentNick); - sendQ->putMessage(m); - - timer = 10; // wait for possible nick collision message - state = 2; - } - break; - - case 4: - if (timer == 0) - { - // no login message received -> disconnect - return false; - } - break; - - case 5: - m = new IRCMessage(); - m->command = wxT("JOIN"); - m->numParams = 1; - m->params.Add(channel); - sendQ->putMessage(m); - - timer = 30; - state = 6; // wait for join message - break; - - case 6: - if (timer == 0) - { - // no join message received -> disconnect - return false; - } - break; - - case 7: - if (debugChannel.Len() == 0) - { - return false; // this state cannot be processed if there is no debug_channel - } - - m = new IRCMessage(); - m->command = wxT("JOIN"); - m->numParams = 1; - m->params.Add(debugChannel); - sendQ->putMessage(m); - - timer = 30; - state = 8; // wait for join message - break; - - case 8: - if (timer == 0) - { - // no join message received -> disconnect - return false; - } - break; - - case 10: - m = new IRCMessage(); - m->command = wxT("WHO"); - m->numParams = 2; - m->params.Add(channel); - m->params.Add(wxT("*")); - sendQ->putMessage(m); - - timer = pingTimer; - state = 11; // wait for timer and then send ping - - if (app != NULL) - { - app->setSendQ(sendQ); // this switches the application on - } - break; - - case 11: - if (timer == 0) - { - m = new IRCMessage(); - m->command = wxT("PING"); - m->numParams = 1; - m->params.Add(currentNick); - sendQ->putMessage(m); - - timer = pingTimer; - state = 12; // wait for pong - } - break; - - case 12: - if (timer == 0) - { - // no pong message received -> disconnect - return false; - } - break; - } - - return true; + + return true; } diff --git a/IRCProtocol.h b/IRCProtocol.h index cf144aa..fffc8eb 100644 --- a/IRCProtocol.h +++ b/IRCProtocol.h @@ -30,34 +30,34 @@ along with this program. If not, see . class IRCProtocol { - public: - IRCProtocol ( IRCApplication * app, - const wxString& callsign, const wxString& password, const wxString& channel, - const wxString& versionInfo ); +public: + IRCProtocol ( IRCApplication * app, + const wxString& callsign, const wxString& password, const wxString& channel, + const wxString& versionInfo ); - ~IRCProtocol(); + ~IRCProtocol(); - void setNetworkReady( bool state ); + void setNetworkReady( bool state ); - bool processQueues ( IRCMessageQueue * recvQ, IRCMessageQueue * sendQ ); + bool processQueues ( IRCMessageQueue * recvQ, IRCMessageQueue * sendQ ); - private: - void chooseNewNick(); +private: + void chooseNewNick(); - wxArrayString nicks; - wxString password; - wxString channel; - wxString name; - wxString currentNick; - wxString versionInfo; + wxArrayString nicks; + wxString password; + wxString channel; + wxString name; + wxString currentNick; + wxString versionInfo; - int state; - int timer; - int pingTimer; + int state; + int timer; + int pingTimer; - wxString debugChannel; + wxString debugChannel; - IRCApplication * app; + IRCApplication * app; }; diff --git a/IRCReceiver.cpp b/IRCReceiver.cpp index 5c55fe1..c4fe4f5 100644 --- a/IRCReceiver.cpp +++ b/IRCReceiver.cpp @@ -40,11 +40,11 @@ along with this program. If not, see . #include IRCReceiver::IRCReceiver(int sock, IRCMessageQueue * q ) - : wxThread(wxTHREAD_JOINABLE) + : wxThread(wxTHREAD_JOINABLE) { - this->sock = sock; + this->sock = sock; - recvQ = q; + recvQ = q; } IRCReceiver::~IRCReceiver() @@ -54,196 +54,158 @@ IRCReceiver::~IRCReceiver() bool IRCReceiver::startWork() { - if (Create() != wxTHREAD_NO_ERROR) - { - wxLogError(wxT("IRCReceiver::startWork: Could not create the worker thread!")); - return false; - } + if (Create() != wxTHREAD_NO_ERROR) { + wxLogError(wxT("IRCReceiver::startWork: Could not create the worker thread!")); + return false; + } - terminateThread = false; + terminateThread = false; - if (Run() != wxTHREAD_NO_ERROR) - { - wxLogError(wxT("IRCReceiver::startWork: Could not run the worker thread!")); - return false; - } + if (Run() != wxTHREAD_NO_ERROR) { + wxLogError(wxT("IRCReceiver::startWork: Could not run the worker thread!")); + return false; + } - return true; + return true; } void IRCReceiver::stopWork() { - terminateThread = true; + terminateThread = true; - Wait(); + Wait(); } static int doRead( int sock, char * buf, int buf_size ) { - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - fd_set rdset; - fd_set errset; - - FD_ZERO(&rdset); - FD_ZERO(&errset); - FD_SET(sock, &rdset); - FD_SET(sock, &errset); - - int res; - - res = select(sock+1, &rdset, NULL, &errset, &tv); - - if ( res < 0 ) - { - wxLogSysError(wxT("IRCReceiver::doRead: select")); - return -1; - } - else if ( res > 0 ) - { - if (FD_ISSET(sock, &errset)) - { - wxLogVerbose(wxT("IRCReceiver::doRead: select (FD_ISSET(sock, exceptfds))")); - return -1; - } - - if (FD_ISSET(sock, &rdset)) - { - res = recv(sock, buf, buf_size, 0); - - if (res < 0) - { - wxLogSysError(wxT("IRCReceiver::doRead: read")); - return -1; - } - else if (res == 0) - { - wxLogVerbose(wxT("IRCReceiver::doRead: EOF read==0")); - return -1; - } - else - { - return res; - } - } - - } - - return 0; + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + fd_set rdset; + fd_set errset; + + FD_ZERO(&rdset); + FD_ZERO(&errset); + FD_SET(sock, &rdset); + FD_SET(sock, &errset); + + int res; + + res = select(sock+1, &rdset, NULL, &errset, &tv); + + if ( res < 0 ) { + wxLogSysError(wxT("IRCReceiver::doRead: select")); + return -1; + } else if ( res > 0 ) { + if (FD_ISSET(sock, &errset)) { + wxLogVerbose(wxT("IRCReceiver::doRead: select (FD_ISSET(sock, exceptfds))")); + return -1; + } + + if (FD_ISSET(sock, &rdset)) { + res = recv(sock, buf, buf_size, 0); + + if (res < 0) { + wxLogSysError(wxT("IRCReceiver::doRead: read")); + return -1; + } else if (res == 0) { + wxLogVerbose(wxT("IRCReceiver::doRead: EOF read==0")); + return -1; + } else { + return res; + } + } + + } + + return 0; } wxThread::ExitCode IRCReceiver::Entry () { - IRCMessage * m = new IRCMessage(); - - int i; - int state = 0; - - while (!terminateThread) - { - - // wxLogVerbose(wxT("IRCReceiver: tick")); - - char buf[200]; - int r = doRead( sock, buf, sizeof buf ); - - if (r < 0) - { - recvQ -> signalEOF(); - delete m; // delete unfinished IRCMessage - break; - } - - for (i=0; i < r; i++) - { - char b = buf[i]; - - if (b > 0) - { - if (b == 10) - { - recvQ -> putMessage(m); - m = new IRCMessage(); - state = 0; - } - else if (b == 13) - { - // do nothing - } - else switch (state) - { - case 0: - if (b == ':') - { - state = 1; // prefix - } - else if (b == 32) - { - // do nothing - } - else - { - m -> command.Append(wxChar(b)); - state = 2; // command - } - break; - - case 1: - if (b == 32) - { - state = 2; // command is next - } - else - { - m -> prefix.Append(wxChar(b)); - } - break; - - case 2: - if (b == 32) - { - state = 3; // params - m -> numParams = 1; - m -> params.Add(wxT("")); - } - else - { - m -> command.Append(wxChar(b)); - } - break; - - case 3: - if (b == 32) - { - m -> numParams ++; - if (m -> numParams >= 15) - { - state = 5; // ignore the rest - } - - m -> params.Add(wxT("")); - } - else if ((b == ':') && (m -> params[ m -> numParams-1 ].Len() == 0)) - { - state = 4; // rest of line is this param - } - else - { - m -> params[ m -> numParams-1 ].Append(wxChar(b)); - } - break; - - case 4: - m -> params[ m -> numParams-1 ].Append(wxChar(b)); - break; - - - } // switch - } // if - } // for - } // while - - return 0; + IRCMessage * m = new IRCMessage(); + + int i; + int state = 0; + + while (!terminateThread) { + + // wxLogVerbose(wxT("IRCReceiver: tick")); + + char buf[200]; + int r = doRead( sock, buf, sizeof buf ); + + if (r < 0) { + recvQ -> signalEOF(); + delete m; // delete unfinished IRCMessage + break; + } + + for (i=0; i < r; i++) { + char b = buf[i]; + + if (b > 0) { + if (b == 10) { + recvQ -> putMessage(m); + m = new IRCMessage(); + state = 0; + } else if (b == 13) { + // do nothing + } else switch (state) { + case 0: + if (b == ':') { + state = 1; // prefix + } else if (b == 32) { + // do nothing + } else { + m -> command.Append(wxChar(b)); + state = 2; // command + } + break; + + case 1: + if (b == 32) { + state = 2; // command is next + } else { + m -> prefix.Append(wxChar(b)); + } + break; + + case 2: + if (b == 32) { + state = 3; // params + m -> numParams = 1; + m -> params.Add(wxT("")); + } else { + m -> command.Append(wxChar(b)); + } + break; + + case 3: + if (b == 32) { + m -> numParams ++; + if (m -> numParams >= 15) { + state = 5; // ignore the rest + } + + m -> params.Add(wxT("")); + } else if ((b == ':') && (m -> params[ m -> numParams-1 ].Len() == 0)) { + state = 4; // rest of line is this param + } else { + m -> params[ m -> numParams-1 ].Append(wxChar(b)); + } + break; + + case 4: + m -> params[ m -> numParams-1 ].Append(wxChar(b)); + break; + + + } // switch + } // if + } // for + } // while + + return 0; } diff --git a/IRCReceiver.h b/IRCReceiver.h index 0f371ce..1ea7d58 100644 --- a/IRCReceiver.h +++ b/IRCReceiver.h @@ -31,32 +31,32 @@ along with this program. If not, see . class IRCReceiver : public wxThread { - public: +public: - IRCReceiver(int sock, IRCMessageQueue * q); + IRCReceiver(int sock, IRCMessageQueue * q); - ~IRCReceiver(); + ~IRCReceiver(); - bool startWork(); + bool startWork(); - void stopWork(); + void stopWork(); - protected: +protected: - virtual wxThread::ExitCode Entry(); + virtual wxThread::ExitCode Entry(); - private: +private: - bool terminateThread; - int sock; - IRCMessageQueue * recvQ; + bool terminateThread; + int sock; + IRCMessageQueue * recvQ; }; -#endif +#endif diff --git a/IRCutils.cpp b/IRCutils.cpp index a72ede2..66e91f6 100644 --- a/IRCutils.cpp +++ b/IRCutils.cpp @@ -43,99 +43,85 @@ along with this program. If not, see . int getAllIPV4Addresses ( const char * name, unsigned short port, - unsigned int * num, struct sockaddr_in * addr, unsigned int max_addr ) + unsigned int * num, struct sockaddr_in * addr, unsigned int max_addr ) { - struct addrinfo hints; - struct addrinfo * res; + struct addrinfo hints; + struct addrinfo * res; - memset(&hints, 0x00, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; + memset(&hints, 0x00, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; - int r = getaddrinfo( name, NULL, &hints, &res ); + int r = getaddrinfo( name, NULL, &hints, &res ); - if (r == 0) - { - struct addrinfo * rp; - unsigned int numAddr = 0; + if (r == 0) { + struct addrinfo * rp; + unsigned int numAddr = 0; - for (rp = res; rp != NULL; rp = rp->ai_next) - { - if (rp->ai_family == AF_INET) - { - numAddr ++; - } - } + for (rp = res; rp != NULL; rp = rp->ai_next) { + if (rp->ai_family == AF_INET) { + numAddr ++; + } + } - if (numAddr > 0) - { - if (numAddr > max_addr) - { - numAddr = max_addr; - } + if (numAddr > 0) { + if (numAddr > max_addr) { + numAddr = max_addr; + } - int * shuffle = new int[numAddr]; + int * shuffle = new int[numAddr]; - unsigned int i; + unsigned int i; - for (i=0; i < numAddr; i++) - { - shuffle[i] = i; - } + for (i=0; i < numAddr; i++) { + shuffle[i] = i; + } - for (i=0; i < (numAddr - 1); i++) - { - if (rand() & 1) - { - int tmp; - tmp = shuffle[i]; - shuffle[i] = shuffle[i+1]; - shuffle[i+1] = tmp; - } - } + for (i=0; i < (numAddr - 1); i++) { + if (rand() & 1) { + int tmp; + tmp = shuffle[i]; + shuffle[i] = shuffle[i+1]; + shuffle[i+1] = tmp; + } + } - for (i=(numAddr - 1); i > 0; i--) - { - if (rand() & 1) - { - int tmp; - tmp = shuffle[i]; - shuffle[i] = shuffle[i-1]; - shuffle[i-1] = tmp; - } - } + for (i=(numAddr - 1); i > 0; i--) { + if (rand() & 1) { + int tmp; + tmp = shuffle[i]; + shuffle[i] = shuffle[i-1]; + shuffle[i-1] = tmp; + } + } - for (rp = res, i=0 ; (rp != NULL) && (i < numAddr); rp = rp->ai_next) - { - if (rp->ai_family == AF_INET) - { - memcpy( addr+shuffle[i], rp->ai_addr, sizeof (struct sockaddr_in) ); + for (rp = res, i=0 ; (rp != NULL) && (i < numAddr); rp = rp->ai_next) { + if (rp->ai_family == AF_INET) { + memcpy( addr+shuffle[i], rp->ai_addr, sizeof (struct sockaddr_in) ); - addr[shuffle[i]].sin_port = htons(port); + addr[shuffle[i]].sin_port = htons(port); - i++; - } - } + i++; + } + } - delete[] shuffle; - } + delete[] shuffle; + } - *num = numAddr; + *num = numAddr; - freeaddrinfo(res); + freeaddrinfo(res); - return 0; + return 0; - } - else - { - wxString e( gai_strerror(r), wxConvUTF8); + } else { + wxString e( gai_strerror(r), wxConvUTF8); - wxLogWarning(wxT("getaddrinfo: ") + e ); + wxLogWarning(wxT("getaddrinfo: ") + e ); - return 1; - } + return 1; + } } @@ -146,35 +132,34 @@ int getAllIPV4Addresses ( const char * name, unsigned short port, void safeStringCopy (char * dest, const char * src, unsigned int buf_size) { - unsigned int i = 0; + unsigned int i = 0; - while (i < (buf_size - 1) && (src[i] != 0)) - { - dest[i] = src[i]; - i++; - } + while (i < (buf_size - 1) && (src[i] != 0)) { + dest[i] = src[i]; + i++; + } - dest[i] = 0; + dest[i] = 0; } wxString getCurrentTime(void) { - time_t now = time(NULL); - struct tm* tm; - struct tm tm_buf; - char buffer[25]; + time_t now = time(NULL); + struct tm* tm; + struct tm tm_buf; + char buffer[25]; #if defined(__WINDOWS__) - gmtime_s(&tm_buf, &now); - tm = &tm_buf; + gmtime_s(&tm_buf, &now); + tm = &tm_buf; #else - gmtime_r(&now, &tm_buf); - tm = &tm_buf; + gmtime_r(&now, &tm_buf); + tm = &tm_buf; #endif - strftime(buffer, sizeof buffer, "%Y-%m-%d %H:%M:%S", tm); + strftime(buffer, sizeof buffer, "%Y-%m-%d %H:%M:%S", tm); - return wxString(buffer, wxConvLocal); + return wxString(buffer, wxConvLocal); } diff --git a/IRCutils.h b/IRCutils.h index f2e44a6..83311ff 100644 --- a/IRCutils.h +++ b/IRCutils.h @@ -22,7 +22,7 @@ along with this program. If not, see . int getAllIPV4Addresses ( const char * name, unsigned short port, - unsigned int * num, struct sockaddr_in * addr, unsigned int max_addr ); + unsigned int * num, struct sockaddr_in * addr, unsigned int max_addr ); void safeStringCopy (char * dest, const char * src, unsigned int buf_size); diff --git a/dstar_dv.cpp b/dstar_dv.cpp index caa3abb..d2e9352 100644 --- a/dstar_dv.cpp +++ b/dstar_dv.cpp @@ -22,73 +22,71 @@ along with this program. If not, see . #include "dstar_dv.h" #include "golay23.h" -int bit_pos1[] = -{ - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2, - - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2, - 0, 0, 1, 1, 2, 2 +int bit_pos1[] = { + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2, + + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2, + 0, 0, 1, 1, 2, 2 }; -int bit_pos2[] = -{ - 23, 11, - 23, 11, - 23, 11, - - 22, 10, - 22, 10, - 22, 10, - - 21, 9, - 21, 9, - 21, 9, - - 20, 8, - 20, 8, - 20, 8, - - 19, 7, - 19, 7, - 19, 7, - - 18, 6, - 18, 6, - 18, 6, - - 17, 5, - 17, 5, - 17, 5, - - 16, 4, - 16, 4, - 16, 4, - - 15, 3, - 15, 3, - 15, 3, - - 14, 2, - 14, 2, - 14, 2, - - 13, 1, - 13, 1, - 13, 1, - - 12, 0, - 12, 0, - 12, 0 - +int bit_pos2[] = { + 23, 11, + 23, 11, + 23, 11, + + 22, 10, + 22, 10, + 22, 10, + + 21, 9, + 21, 9, + 21, 9, + + 20, 8, + 20, 8, + 20, 8, + + 19, 7, + 19, 7, + 19, 7, + + 18, 6, + 18, 6, + 18, 6, + + 17, 5, + 17, 5, + 17, 5, + + 16, 4, + 16, 4, + 16, 4, + + 15, 3, + 15, 3, + 15, 3, + + 14, 2, + 14, 2, + 14, 2, + + 13, 1, + 13, 1, + 13, 1, + + 12, 0, + 12, 0, + 12, 0 + }; @@ -98,156 +96,142 @@ static int prng[4096]; static void init_prng(void) { - int i; + int i; - for (i=0; i < 4096; i++) - { - int mask = 0x800000; - int j; - int pr; + for (i=0; i < 4096; i++) { + int mask = 0x800000; + int j; + int pr; - prng[i] = 0; - pr = i << 4; + prng[i] = 0; + pr = i << 4; - for (j=0; j < 24; j++) - { - pr = ((173 * pr) + 13849) & 0xFFFF; + for (j=0; j < 24; j++) { + pr = ((173 * pr) + 13849) & 0xFFFF; - if ((pr & 0x8000) != 0) - { - prng[i] |= mask; - } + if ((pr & 0x8000) != 0) { + prng[i] |= mask; + } - mask = mask >> 1; - } - } + mask = mask >> 1; + } + } } void dstar_dv_init(void) { - long temp; - int i; - int a[4]; - - decoding_table[0] = 0; - decoding_table[1] = 1; - temp = 1; - for (i=2; i<= 23; i++) - { - temp = temp << 1; - decoding_table[get_syndrome(temp)] = temp; - } - - a[1] = 1; - a[2] = 2; - temp = arr2int(a,2); - decoding_table[get_syndrome(temp)] = temp; - for (i=1; i<253; i++) - { - nextcomb(23,2,a); - temp = arr2int(a,2); - decoding_table[get_syndrome(temp)] = temp; - } - - a[1] = 1; - a[2] = 2; - a[3] = 3; - temp = arr2int(a,3); - decoding_table[get_syndrome(temp)] = temp; - for (i=1; i<1771; i++) - { - nextcomb(23,3,a); - temp = arr2int(a,3); - decoding_table[get_syndrome(temp)] = temp; - } - - init_prng(); + long temp; + int i; + int a[4]; + + decoding_table[0] = 0; + decoding_table[1] = 1; + temp = 1; + for (i=2; i<= 23; i++) { + temp = temp << 1; + decoding_table[get_syndrome(temp)] = temp; + } + + a[1] = 1; + a[2] = 2; + temp = arr2int(a,2); + decoding_table[get_syndrome(temp)] = temp; + for (i=1; i<253; i++) { + nextcomb(23,2,a); + temp = arr2int(a,2); + decoding_table[get_syndrome(temp)] = temp; + } + + a[1] = 1; + a[2] = 2; + a[3] = 3; + temp = arr2int(a,3); + decoding_table[get_syndrome(temp)] = temp; + for (i=1; i<1771; i++) { + nextcomb(23,3,a); + temp = arr2int(a,3); + decoding_table[get_syndrome(temp)] = temp; + } + + init_prng(); } static int golay2412 (int data, int *decoded) { - int block = (data >> 1) & 0x07fffff; - int corrected_block = block ^ decoding_table[get_syndrome(block)]; + int block = (data >> 1) & 0x07fffff; + int corrected_block = block ^ decoding_table[get_syndrome(block)]; - int errs = 0; - int parity_corr = 0; - int i; + int errs = 0; + int parity_corr = 0; + int i; - for (i = 0; i < 23; i++) - { - int mask = 1 << i; + for (i = 0; i < 23; i++) { + int mask = 1 << i; - int bit_rcvd = block & mask; - int bit_corr = corrected_block & mask; + int bit_rcvd = block & mask; + int bit_corr = corrected_block & mask; - if (bit_corr != 0) - { - parity_corr ++; - } + if (bit_corr != 0) { + parity_corr ++; + } - if (bit_rcvd != bit_corr) - { - errs ++; - } - } + if (bit_rcvd != bit_corr) { + errs ++; + } + } - if ((parity_corr & 0x01) != (data & 0x01)) - { - errs ++; - } + if ((parity_corr & 0x01) != (data & 0x01)) { + errs ++; + } - *decoded = corrected_block >> 11; + *decoded = corrected_block >> 11; - return errs; + return errs; } int dstar_dv_decode_first_block (const unsigned char * d, int * errs) { - int bits[3]; - int i; - int data; + int bits[3]; + int i; + int data; - for (i=0; i < 3; i++) - { - bits[i] = 0; - } + for (i=0; i < 3; i++) { + bits[i] = 0; + } - for (i=0; i < 72; i++) - { - bits[ bit_pos1[i] ] |= (d[ i >> 3 ] & (0x80 >> (i & 0x07))) ? (1 << bit_pos2[i]) : 0; - } + for (i=0; i < 72; i++) { + bits[ bit_pos1[i] ] |= (d[ i >> 3 ] & (0x80 >> (i & 0x07))) ? (1 << bit_pos2[i]) : 0; + } - *errs = golay2412( bits[0], & data ); + *errs = golay2412( bits[0], & data ); - return data; + return data; } int dstar_dv_decode (const unsigned char * d, int data[3]) { - int bits[3]; - int i; - int errs; + int bits[3]; + int i; + int errs; - for (i=0; i < 3; i++) - { - bits[i] = 0; - } + for (i=0; i < 3; i++) { + bits[i] = 0; + } - for (i=0; i < 72; i++) - { - bits[ bit_pos1[i] ] |= (d[ i >> 3 ] & (0x80 >> (i & 0x07))) ? (1 << bit_pos2[i]) : 0; - } + for (i=0; i < 72; i++) { + bits[ bit_pos1[i] ] |= (d[ i >> 3 ] & (0x80 >> (i & 0x07))) ? (1 << bit_pos2[i]) : 0; + } - errs = golay2412( bits[0], data ); + errs = golay2412( bits[0], data ); - errs += golay2412( bits[1] ^ prng[ data[0] & 0x0fff ], data + 1 ); + errs += golay2412( bits[1] ^ prng[ data[0] & 0x0fff ], data + 1 ); - data[2] = bits[2]; + data[2] = bits[2]; - return errs; + return errs; } diff --git a/dstar_dv.h b/dstar_dv.h index 59872e3..183d74b 100644 --- a/dstar_dv.h +++ b/dstar_dv.h @@ -22,17 +22,17 @@ along with this program. If not, see . /* Call this function first before using any of the other functions */ void dstar_dv_init(void); -/* +/* This function decodes the first and most important Golay block of a DSTAR Digital Voice frame. The function is provided with a pointer to the 9-byte voice data. Result is the decoded first block. The number of decoding errors is reported in the variable errs and ranges from 0 to 4. Only 24 bits are -checked, the BER therefore is: BER = errs / 24 +checked, the BER therefore is: BER = errs / 24 */ int dstar_dv_decode_first_block (const unsigned char * d, int * errs); -/* +/* This function decodes the both Golay blocks of a DSTAR Digital Voice frame. The function is provided with a pointer to the 9-byte voice data. Function result is diff --git a/dvap_rptr.cpp b/dvap_rptr.cpp index b9582eb..36fea00 100644 --- a/dvap_rptr.cpp +++ b/dvap_rptr.cpp @@ -44,86 +44,77 @@ #define IP_SIZE 15 /* data from dvap */ -struct dvap_hdr -{ - unsigned char hdr0; // 0x2f - unsigned char hdr1; // 0xa0 - unsigned char streamid[2]; - unsigned char framepos; - unsigned char seq; - unsigned char flag1; - unsigned char flag2; - unsigned char flag3; - unsigned char rpt1[8]; - unsigned char rpt2[8]; - unsigned char urcall[8]; - unsigned char mycall[8]; - unsigned char sfx[4]; - unsigned char pfcs[2]; +struct dvap_hdr { + unsigned char hdr0; // 0x2f + unsigned char hdr1; // 0xa0 + unsigned char streamid[2]; + unsigned char framepos; + unsigned char seq; + unsigned char flag1; + unsigned char flag2; + unsigned char flag3; + unsigned char rpt1[8]; + unsigned char rpt2[8]; + unsigned char urcall[8]; + unsigned char mycall[8]; + unsigned char sfx[4]; + unsigned char pfcs[2]; }; -struct dvap_voice -{ - unsigned char hdr0; // 0x12 - unsigned char hdr1; // 0xc0 - unsigned char streamid[2]; - unsigned char framepos; - unsigned char seq; - unsigned char voice[9]; - unsigned char txt[3]; +struct dvap_voice { + unsigned char hdr0; // 0x12 + unsigned char hdr1; // 0xc0 + unsigned char streamid[2]; + unsigned char framepos; + unsigned char seq; + unsigned char voice[9]; + unsigned char txt[3]; }; /* data from the local gateway */ -struct hdr -{ - unsigned char flags[3]; - unsigned char rpt2[8]; - unsigned char rpt1[8]; - unsigned char urcall[8]; - unsigned char mycall[8]; - unsigned char sfx[4]; - unsigned char pfcs[2]; +struct hdr { + unsigned char flags[3]; + unsigned char rpt2[8]; + unsigned char rpt1[8]; + unsigned char urcall[8]; + unsigned char mycall[8]; + unsigned char sfx[4]; + unsigned char pfcs[2]; }; -struct icm -{ - unsigned char icm_id; - unsigned char dst_rptr_id; - unsigned char snd_rptr_id; - unsigned char snd_term_id; - unsigned char streamid[2]; - unsigned char ctrl; +struct icm { + unsigned char icm_id; + unsigned char dst_rptr_id; + unsigned char snd_rptr_id; + unsigned char snd_term_id; + unsigned char streamid[2]; + unsigned char ctrl; }; -struct voice_and_text -{ - unsigned char voice[9]; - unsigned char text[3]; +struct voice_and_text { + unsigned char voice[9]; + unsigned char text[3]; }; -struct audio -{ - unsigned char buff[sizeof(struct hdr)]; +struct audio { + unsigned char buff[sizeof(struct hdr)]; }; -struct pkt -{ - unsigned char pkt_id[4]; - unsigned char nothing1[2]; - unsigned char flags[2]; - unsigned char nothing2[2]; - struct icm myicm; - union - { - struct audio rf_audio; - struct hdr rf_hdr; - struct voice_and_text vat; - }; +struct pkt { + unsigned char pkt_id[4]; + unsigned char nothing1[2]; + unsigned char flags[2]; + unsigned char nothing2[2]; + struct icm myicm; + union { + struct audio rf_audio; + struct hdr rf_hdr; + struct voice_and_text vat; + }; }; -struct dvap_ack_arg_type -{ - char mycall[8]; - float ber; +struct dvap_ack_arg_type { + char mycall[8]; + float ber; }; dvap_ack_arg_type dvap_ack_arg; @@ -196,92 +187,87 @@ static unsigned char DVP_RQST_START[] = {0x05, 0x00, 0x18, 0x00, 0x01}; static unsigned char DVP_REPL_START[] = {0x05, 0x00, 0x18, 0x00, 0x01}; static unsigned char DVP_RQST_STOP[] = {0x05, 0x00, 0x18, 0x00, 0x00}; static unsigned char DVP_REPL_STOP[] = {0x05, 0x00, 0x18, 0x00, 0x00}; -static unsigned char DVP_HDR[] = -{ - 0x2F, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +static unsigned char DVP_HDR[] = { + 0x2F, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static unsigned char DVP_REPL_HDR[] = -{ - 0x2F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +static unsigned char DVP_REPL_HDR[] = { + 0x2F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char DVP_REPL_PTT[] = {0x05, 0x20, 0x18, 0x01, 0x00}; -static unsigned char DVP_DAT[] = -{ - 0x12, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +static unsigned char DVP_DAT[] = { + 0x12, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char DVP_STS[] = {0x07, 0x20, 0x90, 0x00, 0x00, 0x00, 0x00}; static unsigned char DVP_ACK[] = {0x03, 0x60, 0x00}; static unsigned int MAX_REPL_CNT = 20; -enum REPLY_TYPE -{ - RT_TIMEOUT, - RT_ERR, - RT_UNKNOWN, - RT_NAME, - RT_SER, - RT_FW, - RT_START, - RT_STOP, - RT_MODU, - RT_MODE, - RT_SQL, - RT_PWR, - RT_OFF, - RT_FREQ, - RT_STS, - RT_PTT, - RT_ACK, - RT_HDR, - RT_HDR_ACK, - RT_DAT +enum REPLY_TYPE { + RT_TIMEOUT, + RT_ERR, + RT_UNKNOWN, + RT_NAME, + RT_SER, + RT_FW, + RT_START, + RT_STOP, + RT_MODU, + RT_MODE, + RT_SQL, + RT_PWR, + RT_OFF, + RT_FREQ, + RT_STS, + RT_PTT, + RT_ACK, + RT_HDR, + RT_HDR_ACK, + RT_DAT }; static unsigned int space = 0; static unsigned int aseed = 0; -static unsigned short crc_tabccitt[256] = -{ - 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, - 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, - 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, - 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, - 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, - 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, - 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, - 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, - 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, - 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, - 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, - 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, - 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, - 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, - 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, - 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, - 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, - 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, - 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, - 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, - 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, - 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, - 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, - 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, - 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, - 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, - 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, - 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, - 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, - 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, - 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, - 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 +static unsigned short crc_tabccitt[256] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 }; /* helper routines */ @@ -320,2076 +306,1850 @@ extern int dstar_dv_decode(const unsigned char *d, int data[3]); static void calcPFCS(unsigned char *packet, unsigned char *pfcs) { - unsigned short crc_dstar_ffff = 0xffff; - unsigned short tmp, short_c; - short int i; - - for (i = 0; i < 39 ; i++) - { - short_c = 0x00ff & (unsigned short)packet[i]; - tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; - crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; - } - crc_dstar_ffff = ~crc_dstar_ffff; - tmp = crc_dstar_ffff; - - pfcs[0] = (unsigned char)(crc_dstar_ffff & 0xff); - pfcs[1] = (unsigned char)((tmp >> 8) & 0xff); - - return; + unsigned short crc_dstar_ffff = 0xffff; + unsigned short tmp, short_c; + short int i; + + for (i = 0; i < 39 ; i++) { + short_c = 0x00ff & (unsigned short)packet[i]; + tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; + crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; + } + crc_dstar_ffff = ~crc_dstar_ffff; + tmp = crc_dstar_ffff; + + pfcs[0] = (unsigned char)(crc_dstar_ffff & 0xff); + pfcs[1] = (unsigned char)((tmp >> 8) & 0xff); + + return; } static void sig_catch(int signum) { - if ((signum == SIGTERM) || - (signum == SIGINT) || - (signum == SIGHUP)) - keep_running = false; - exit(0); + if ((signum == SIGTERM) || + (signum == SIGINT) || + (signum == SIGHUP)) + keep_running = false; + exit(0); } /* log the event */ static void traceit(const char *fmt,...) { - time_t ltime; - struct tm mytm; - char trace_buf[TRACE_BFSZ]; + time_t ltime; + struct tm mytm; + char trace_buf[TRACE_BFSZ]; - time(<ime); - localtime_r(<ime,&mytm); + time(<ime); + localtime_r(<ime,&mytm); - snprintf(trace_buf,TRACE_BFSZ - 1,"%02d%02d%02d at %02d:%02d:%02d:", - mytm.tm_mon+1,mytm.tm_mday,mytm.tm_year % 100, - mytm.tm_hour,mytm.tm_min,mytm.tm_sec); + snprintf(trace_buf,TRACE_BFSZ - 1,"%02d%02d%02d at %02d:%02d:%02d:", + mytm.tm_mon+1,mytm.tm_mday,mytm.tm_year % 100, + mytm.tm_hour,mytm.tm_min,mytm.tm_sec); - va_list args; - va_start(args,fmt); - vsnprintf(trace_buf + strlen(trace_buf), TRACE_BFSZ - strlen(trace_buf) - 1, fmt, args); - va_end(args); + va_list args; + va_start(args,fmt); + vsnprintf(trace_buf + strlen(trace_buf), TRACE_BFSZ - strlen(trace_buf) - 1, fmt, args); + va_end(args); - fprintf(stdout, "%s", trace_buf); - return; + fprintf(stdout, "%s", trace_buf); + return; } /* process configuration file */ static int read_config(const char *cfgFile) { - short int valid_params = 18; - short int params = 0; - - FILE *cnf = NULL; - char inbuf[1024]; - char *p = NULL; - char *ptr; - unsigned short i; - - cnf = fopen(cfgFile, "r"); - if (!cnf) - { - traceit("Failed to open file %s\n", cfgFile); - return 1; - } - - traceit("Reading file %s\n", cfgFile); - while (fgets(inbuf, 1020, cnf) != NULL) - { - if (strchr(inbuf, '#')) - continue; - - p = strchr(inbuf, '\r'); - if (p) - *p = '\0'; - p = strchr(inbuf, '\n'); - if (p) - *p = '\0'; - - p = strchr(inbuf, '='); - if (!p) - continue; - *p = '\0'; - - if (strcmp(inbuf,"RPTR") == 0) - { - memset(RPTR,' ', sizeof(RPTR)); - RPTR[RPTR_SIZE] = '\0'; - - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if ((strlen(p + 1) < 1) || (strlen(p + 1) > (RPTR_SIZE - 2))) - traceit("RPTR value [%s] invalid\n", p + 1); - else - { - memcpy(RPTR, p + 1, strlen(p + 1)); - traceit("RPTR=[%s]\n",RPTR); - params ++; - } - } - else - if (strcmp(inbuf,"OWNER") == 0) - { - memset(OWNER,' ', sizeof(OWNER)); - OWNER[RPTR_SIZE] = '\0'; - - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if ((strlen(p + 1) < 1) || (strlen(p + 1) > (RPTR_SIZE - 2))) - traceit("OWNER value [%s] invalid\n", p + 1); - else - { - memcpy(OWNER, p + 1, strlen(p + 1)); - traceit("OWNER=[%s]\n",OWNER); - params ++; - } - } - else - if (strcmp(inbuf,"INVALID_YRCALL_KEY") == 0) - { - memset(INVALID_YRCALL_KEY, 0, sizeof(INVALID_YRCALL_KEY)); - - if ( (strlen(p + 1) < 1) || (strlen(p + 1) > CALL_SIZE) ) - traceit("INVALID_YRCALL_KEY value [%s] invalid\n", p + 1); - else - { - memcpy(INVALID_YRCALL_KEY, p + 1, strlen(p + 1)); - - for (i = 0; i < strlen(INVALID_YRCALL_KEY); i++) - INVALID_YRCALL_KEY[i] = toupper(INVALID_YRCALL_KEY[i]); - - traceit("INVALID_YRCALL_KEY=[%s]\n",INVALID_YRCALL_KEY); - params ++; - } - } - else - if (strcmp(inbuf,"RPTR_MOD") == 0) - { - RPTR_MOD = *(p + 1); - traceit("RPTR_MOD=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"RPTR_VIRTUAL_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("RPTR_VIRTUAL_IP value [%s] invalid\n", p + 1); - else - { - strncpy(RPTR_VIRTUAL_IP, p + 1, IP_SIZE); - RPTR_VIRTUAL_IP[IP_SIZE] = '\0'; - traceit("RPTR_VIRTUAL_IP=[%s]\n", RPTR_VIRTUAL_IP); - params ++; - } - } - else - if (strcmp(inbuf,"RPTR_PORT") == 0) - { - RPTR_PORT = atoi(p + 1); - traceit("RPTR_PORT=[%d]\n",RPTR_PORT); - params ++; - } - else - if (strcmp(inbuf,"G2_INTERNAL_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("G2_INTERNAL_IP value [%s] invalid\n", p + 1); - else - { - strncpy(G2_INTERNAL_IP, p + 1, IP_SIZE); - G2_INTERNAL_IP[IP_SIZE] = '\0'; - traceit("G2_INTERNAL_IP=[%s]\n", G2_INTERNAL_IP); - params ++; - } - } - else - if (strcmp(inbuf,"G2_PORT") == 0) - { - G2_PORT = atoi(p + 1); - traceit("G2_PORT=[%d]\n",G2_PORT); - params ++; - } - else - if (strcmp(inbuf,"DVP_SERIAL") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if ((strlen(p + 1) > 63) || (strlen(p + 1) < 1)) - traceit("DVP_SERIAL value [%s] invalid\n", p + 1); - else - { - strcpy(DVP_SERIAL, p + 1); - traceit("DVP_SERIAL=[%s]\n", DVP_SERIAL); - params ++; - } - } - else - if (strcmp(inbuf,"DVP_FREQ") == 0) - { - DVP_FREQ = atoi(p + 1); - traceit("DVP_FREQ=[%u]\n", DVP_FREQ); - params ++; - } - else - if (strcmp(inbuf,"DVP_PWR") == 0) - { - DVP_PWR = atoi(p + 1); - traceit("DVP_PWR=[%d]\n", DVP_PWR); - params ++; - } - else - if (strcmp(inbuf,"DVP_SQL") == 0) - { - DVP_SQL = atoi(p + 1); - traceit("DVP_SQL=[%d]\n", DVP_SQL); - params ++; - } - else - if (strcmp(inbuf,"DVP_OFF") == 0) - { - DVP_OFF = atoi(p + 1); - traceit("DVP_OFF=[%u]\n", DVP_OFF); - params ++; - } - else - if (strcmp(inbuf,"WAIT_FOR_PACKETS") == 0) - { - WAIT_FOR_PACKETS = atoi(p + 1); - if (WAIT_FOR_PACKETS <= 5) - WAIT_FOR_PACKETS = 25; - traceit("WAIT_FOR_PACKETS=[%d]\n",WAIT_FOR_PACKETS); - params ++; - } - else - if (strcmp(inbuf,"REMOTE_TIMEOUT") == 0) - { - REMOTE_TIMEOUT = atoi(p + 1); - if (REMOTE_TIMEOUT < 1) - REMOTE_TIMEOUT = 1; - traceit("REMOTE_TIMEOUT=[%d]\n",REMOTE_TIMEOUT); - params ++; - } - else - if (strcmp(inbuf,"DELAY_BETWEEN") == 0) - { - DELAY_BETWEEN = atoi(p + 1); - if (DELAY_BETWEEN <= 0) - DELAY_BETWEEN = 20; - traceit("DELAY_BETWEEN=[%d]\n",DELAY_BETWEEN); - params ++; - } - else - if (strcmp(inbuf,"DELAY_BEFORE") == 0) - { - DELAY_BEFORE = atoi(p + 1); - if (DELAY_BEFORE <= 0) - DELAY_BEFORE = 1; - traceit("DELAY_BEFORE=[%d]\n",DELAY_BEFORE); - params ++; - } - else - if (strcmp(inbuf,"RPTR_ACK") == 0) - { - if (*(p + 1) == 'Y') - RPTR_ACK = true; - else - RPTR_ACK = false; - traceit("RPTR_ACK=[%c]\n", *(p + 1)); - params ++; - } - } - fclose(cnf); - - if (params != valid_params) - { - traceit("Configuration file %s invalid\n",cfgFile); - return 1; - } - - /********* HERE HERE check for valid values *************/ - /* check valid values */ - /********* HERE HERE check for valid values *************/ - - inactiveMax = (REMOTE_TIMEOUT * 1000) / WAIT_FOR_PACKETS; - traceit("Max loops = %d\n", inactiveMax); - - /* convert to Microseconds */ - WAIT_FOR_PACKETS = WAIT_FOR_PACKETS * 1000; - - return 0; + short int valid_params = 18; + short int params = 0; + + FILE *cnf = NULL; + char inbuf[1024]; + char *p = NULL; + char *ptr; + unsigned short i; + + cnf = fopen(cfgFile, "r"); + if (!cnf) { + traceit("Failed to open file %s\n", cfgFile); + return 1; + } + + traceit("Reading file %s\n", cfgFile); + while (fgets(inbuf, 1020, cnf) != NULL) { + if (strchr(inbuf, '#')) + continue; + + p = strchr(inbuf, '\r'); + if (p) + *p = '\0'; + p = strchr(inbuf, '\n'); + if (p) + *p = '\0'; + + p = strchr(inbuf, '='); + if (!p) + continue; + *p = '\0'; + + if (strcmp(inbuf,"RPTR") == 0) { + memset(RPTR,' ', sizeof(RPTR)); + RPTR[RPTR_SIZE] = '\0'; + + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if ((strlen(p + 1) < 1) || (strlen(p + 1) > (RPTR_SIZE - 2))) + traceit("RPTR value [%s] invalid\n", p + 1); + else { + memcpy(RPTR, p + 1, strlen(p + 1)); + traceit("RPTR=[%s]\n",RPTR); + params ++; + } + } else if (strcmp(inbuf,"OWNER") == 0) { + memset(OWNER,' ', sizeof(OWNER)); + OWNER[RPTR_SIZE] = '\0'; + + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if ((strlen(p + 1) < 1) || (strlen(p + 1) > (RPTR_SIZE - 2))) + traceit("OWNER value [%s] invalid\n", p + 1); + else { + memcpy(OWNER, p + 1, strlen(p + 1)); + traceit("OWNER=[%s]\n",OWNER); + params ++; + } + } else if (strcmp(inbuf,"INVALID_YRCALL_KEY") == 0) { + memset(INVALID_YRCALL_KEY, 0, sizeof(INVALID_YRCALL_KEY)); + + if ( (strlen(p + 1) < 1) || (strlen(p + 1) > CALL_SIZE) ) + traceit("INVALID_YRCALL_KEY value [%s] invalid\n", p + 1); + else { + memcpy(INVALID_YRCALL_KEY, p + 1, strlen(p + 1)); + + for (i = 0; i < strlen(INVALID_YRCALL_KEY); i++) + INVALID_YRCALL_KEY[i] = toupper(INVALID_YRCALL_KEY[i]); + + traceit("INVALID_YRCALL_KEY=[%s]\n",INVALID_YRCALL_KEY); + params ++; + } + } else if (strcmp(inbuf,"RPTR_MOD") == 0) { + RPTR_MOD = *(p + 1); + traceit("RPTR_MOD=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"RPTR_VIRTUAL_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("RPTR_VIRTUAL_IP value [%s] invalid\n", p + 1); + else { + strncpy(RPTR_VIRTUAL_IP, p + 1, IP_SIZE); + RPTR_VIRTUAL_IP[IP_SIZE] = '\0'; + traceit("RPTR_VIRTUAL_IP=[%s]\n", RPTR_VIRTUAL_IP); + params ++; + } + } else if (strcmp(inbuf,"RPTR_PORT") == 0) { + RPTR_PORT = atoi(p + 1); + traceit("RPTR_PORT=[%d]\n",RPTR_PORT); + params ++; + } else if (strcmp(inbuf,"G2_INTERNAL_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("G2_INTERNAL_IP value [%s] invalid\n", p + 1); + else { + strncpy(G2_INTERNAL_IP, p + 1, IP_SIZE); + G2_INTERNAL_IP[IP_SIZE] = '\0'; + traceit("G2_INTERNAL_IP=[%s]\n", G2_INTERNAL_IP); + params ++; + } + } else if (strcmp(inbuf,"G2_PORT") == 0) { + G2_PORT = atoi(p + 1); + traceit("G2_PORT=[%d]\n",G2_PORT); + params ++; + } else if (strcmp(inbuf,"DVP_SERIAL") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if ((strlen(p + 1) > 63) || (strlen(p + 1) < 1)) + traceit("DVP_SERIAL value [%s] invalid\n", p + 1); + else { + strcpy(DVP_SERIAL, p + 1); + traceit("DVP_SERIAL=[%s]\n", DVP_SERIAL); + params ++; + } + } else if (strcmp(inbuf,"DVP_FREQ") == 0) { + DVP_FREQ = atoi(p + 1); + traceit("DVP_FREQ=[%u]\n", DVP_FREQ); + params ++; + } else if (strcmp(inbuf,"DVP_PWR") == 0) { + DVP_PWR = atoi(p + 1); + traceit("DVP_PWR=[%d]\n", DVP_PWR); + params ++; + } else if (strcmp(inbuf,"DVP_SQL") == 0) { + DVP_SQL = atoi(p + 1); + traceit("DVP_SQL=[%d]\n", DVP_SQL); + params ++; + } else if (strcmp(inbuf,"DVP_OFF") == 0) { + DVP_OFF = atoi(p + 1); + traceit("DVP_OFF=[%u]\n", DVP_OFF); + params ++; + } else if (strcmp(inbuf,"WAIT_FOR_PACKETS") == 0) { + WAIT_FOR_PACKETS = atoi(p + 1); + if (WAIT_FOR_PACKETS <= 5) + WAIT_FOR_PACKETS = 25; + traceit("WAIT_FOR_PACKETS=[%d]\n",WAIT_FOR_PACKETS); + params ++; + } else if (strcmp(inbuf,"REMOTE_TIMEOUT") == 0) { + REMOTE_TIMEOUT = atoi(p + 1); + if (REMOTE_TIMEOUT < 1) + REMOTE_TIMEOUT = 1; + traceit("REMOTE_TIMEOUT=[%d]\n",REMOTE_TIMEOUT); + params ++; + } else if (strcmp(inbuf,"DELAY_BETWEEN") == 0) { + DELAY_BETWEEN = atoi(p + 1); + if (DELAY_BETWEEN <= 0) + DELAY_BETWEEN = 20; + traceit("DELAY_BETWEEN=[%d]\n",DELAY_BETWEEN); + params ++; + } else if (strcmp(inbuf,"DELAY_BEFORE") == 0) { + DELAY_BEFORE = atoi(p + 1); + if (DELAY_BEFORE <= 0) + DELAY_BEFORE = 1; + traceit("DELAY_BEFORE=[%d]\n",DELAY_BEFORE); + params ++; + } else if (strcmp(inbuf,"RPTR_ACK") == 0) { + if (*(p + 1) == 'Y') + RPTR_ACK = true; + else + RPTR_ACK = false; + traceit("RPTR_ACK=[%c]\n", *(p + 1)); + params ++; + } + } + fclose(cnf); + + if (params != valid_params) { + traceit("Configuration file %s invalid\n",cfgFile); + return 1; + } + + /********* HERE HERE check for valid values *************/ + /* check valid values */ + /********* HERE HERE check for valid values *************/ + + inactiveMax = (REMOTE_TIMEOUT * 1000) / WAIT_FOR_PACKETS; + traceit("Max loops = %d\n", inactiveMax); + + /* convert to Microseconds */ + WAIT_FOR_PACKETS = WAIT_FOR_PACKETS * 1000; + + return 0; } static int open_sock() { - struct sockaddr_in inaddr; - int rc = -1; - - insock = socket(PF_INET, SOCK_DGRAM, 0); - if (insock == -1) - { - traceit("Failed to create insock, error=%d, message=%s\n",errno,strerror(errno)); - return -1; - } - - memset(&inaddr, 0, sizeof(inaddr)); - inaddr.sin_family = AF_INET; - inaddr.sin_port = htons(RPTR_PORT); - inaddr.sin_addr.s_addr = inet_addr(RPTR_VIRTUAL_IP); - rc = bind(insock, (struct sockaddr *)&inaddr, sizeof(inaddr)); - if (rc == -1) - { - traceit("Failed to bind server socket, error=%d, message=%s\n", errno,strerror(errno)); - close(insock); insock = -1; - return -1; - } - fcntl(insock,F_SETFL,O_NONBLOCK); - - memset(&outaddr, 0, sizeof(outaddr)); - outaddr.sin_family = AF_INET; - outaddr.sin_port = htons(G2_PORT); - outaddr.sin_addr.s_addr = inet_addr(G2_INTERNAL_IP); - - return 0; + struct sockaddr_in inaddr; + int rc = -1; + + insock = socket(PF_INET, SOCK_DGRAM, 0); + if (insock == -1) { + traceit("Failed to create insock, error=%d, message=%s\n",errno,strerror(errno)); + return -1; + } + + memset(&inaddr, 0, sizeof(inaddr)); + inaddr.sin_family = AF_INET; + inaddr.sin_port = htons(RPTR_PORT); + inaddr.sin_addr.s_addr = inet_addr(RPTR_VIRTUAL_IP); + rc = bind(insock, (struct sockaddr *)&inaddr, sizeof(inaddr)); + if (rc == -1) { + traceit("Failed to bind server socket, error=%d, message=%s\n", errno,strerror(errno)); + close(insock); + insock = -1; + return -1; + } + fcntl(insock,F_SETFL,O_NONBLOCK); + + memset(&outaddr, 0, sizeof(outaddr)); + outaddr.sin_family = AF_INET; + outaddr.sin_port = htons(G2_PORT); + outaddr.sin_addr.s_addr = inet_addr(G2_INTERNAL_IP); + + return 0; } static bool open_ser(char *dvp) { - static termios t; - - serfd = open(dvp, O_RDWR | O_NOCTTY | O_NDELAY, 0); - if (serfd < 0) - { - traceit("Failed to open device [%s], error=%d, message=%s\n", dvp, errno, strerror(errno)); - return false; - } - - if (isatty(serfd) == 0) - { - traceit("Device %s is not a tty device\n", dvp); - close(serfd); serfd = -1; - return false; - } - - if (tcgetattr(serfd, &t) < 0) - { - traceit("tcgetattr failed for %s, error=%d\n", dvp, errno); - close(serfd); serfd = -1; - return false; - } - - t.c_lflag &= ~(ECHO | ECHOE | ICANON | IEXTEN | ISIG); - t.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF | IXANY); - t.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS); - t.c_cflag |= CS8; - t.c_oflag &= ~(OPOST); - t.c_cc[VMIN] = 0; - t.c_cc[VTIME] = 10; - - cfsetospeed(&t, B230400); - cfsetispeed(&t, B230400); - - if (tcsetattr(serfd, TCSANOW, &t) < 0) - { - traceit("tcsetattr failed for %s, error=%d\n", dvp, errno); - close(serfd); serfd = -1; - return false; - } - - return true; + static termios t; + + serfd = open(dvp, O_RDWR | O_NOCTTY | O_NDELAY, 0); + if (serfd < 0) { + traceit("Failed to open device [%s], error=%d, message=%s\n", dvp, errno, strerror(errno)); + return false; + } + + if (isatty(serfd) == 0) { + traceit("Device %s is not a tty device\n", dvp); + close(serfd); + serfd = -1; + return false; + } + + if (tcgetattr(serfd, &t) < 0) { + traceit("tcgetattr failed for %s, error=%d\n", dvp, errno); + close(serfd); + serfd = -1; + return false; + } + + t.c_lflag &= ~(ECHO | ECHOE | ICANON | IEXTEN | ISIG); + t.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF | IXANY); + t.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS); + t.c_cflag |= CS8; + t.c_oflag &= ~(OPOST); + t.c_cc[VMIN] = 0; + t.c_cc[VTIME] = 10; + + cfsetospeed(&t, B230400); + cfsetispeed(&t, B230400); + + if (tcsetattr(serfd, TCSANOW, &t) < 0) { + traceit("tcsetattr failed for %s, error=%d\n", dvp, errno); + close(serfd); + serfd = -1; + return false; + } + + return true; } static bool open_dvp() { - short int i; - bool ok = false; - char dvp_device[128]; - - do - { - for (i = 0; i < 32; i++) - { - sprintf(dvp_device, "/dev/ttyUSB%d", i); - - if (access(dvp_device, R_OK | W_OK) != 0) - continue; - - ok = open_ser(dvp_device); - if (!ok) - continue; - - if (flock(serfd, LOCK_EX | LOCK_NB) != 0) - { - close(serfd); serfd = -1; - ok = false; - traceit("Device %s is already locked/used by other dvap_rptr\n", dvp_device); - continue; - } - traceit("Device %s now locked for exclusive use\n", dvp_device); - - ok = get_ser(dvp_device); - if (!ok) - { - close(serfd); serfd = -1; - continue; - } - break; - } - if (!ok) - break; - - ok = get_name(); - if (!ok) - break; - - ok = get_fw(); - if (!ok) - break; - - - ok = set_modu(); - if (!ok) - break; - - ok = set_mode(); - if (!ok) - break; - - ok = set_sql(); - if (!ok) - break; - - ok = set_pwr(); - if (!ok) - break; - - ok = set_off(); - if (!ok) - break; - - ok = set_freq(); - if (!ok) - break; - - ok = start_dvap(); - if (!ok) - break; - - } while (false); - - if (!ok) - { - if (serfd != -1) - { - (void)write_to_dvp(DVP_RQST_STOP, 5); - close(serfd); - serfd = -1; - } - return false; - } - return true; + short int i; + bool ok = false; + char dvp_device[128]; + + do { + for (i = 0; i < 32; i++) { + sprintf(dvp_device, "/dev/ttyUSB%d", i); + + if (access(dvp_device, R_OK | W_OK) != 0) + continue; + + ok = open_ser(dvp_device); + if (!ok) + continue; + + if (flock(serfd, LOCK_EX | LOCK_NB) != 0) { + close(serfd); + serfd = -1; + ok = false; + traceit("Device %s is already locked/used by other dvap_rptr\n", dvp_device); + continue; + } + traceit("Device %s now locked for exclusive use\n", dvp_device); + + ok = get_ser(dvp_device); + if (!ok) { + close(serfd); + serfd = -1; + continue; + } + break; + } + if (!ok) + break; + + ok = get_name(); + if (!ok) + break; + + ok = get_fw(); + if (!ok) + break; + + + ok = set_modu(); + if (!ok) + break; + + ok = set_mode(); + if (!ok) + break; + + ok = set_sql(); + if (!ok) + break; + + ok = set_pwr(); + if (!ok) + break; + + ok = set_off(); + if (!ok) + break; + + ok = set_freq(); + if (!ok) + break; + + ok = start_dvap(); + if (!ok) + break; + + } while (false); + + if (!ok) { + if (serfd != -1) { + (void)write_to_dvp(DVP_RQST_STOP, 5); + close(serfd); + serfd = -1; + } + return false; + } + return true; } static int read_from_dvp(unsigned char *buf, unsigned int len) { - unsigned int off = 0; - fd_set fds; - int n; - struct timeval tv; - ssize_t temp_len; - - if (len == 0) - return 0; - - while (off < len) - { - FD_ZERO(&fds); - FD_SET(serfd, &fds); - - if (off == 0) - { - tv.tv_sec = 0; - tv.tv_usec = 0; - n = select(serfd + 1, &fds, NULL, NULL, &tv); - if (n == 0) - return 0; // nothing to read from the dvap - } - else - n = select(serfd + 1, &fds, NULL, NULL, NULL); - - if (n < 0) - { - traceit("select error=%d on dvap\n", errno); - return -1; - } - - if (n > 0) - { - temp_len = read(serfd, buf + off, len - off); - if (temp_len > 0) - off += temp_len; - } - } - - return len; + unsigned int off = 0; + fd_set fds; + int n; + struct timeval tv; + ssize_t temp_len; + + if (len == 0) + return 0; + + while (off < len) { + FD_ZERO(&fds); + FD_SET(serfd, &fds); + + if (off == 0) { + tv.tv_sec = 0; + tv.tv_usec = 0; + n = select(serfd + 1, &fds, NULL, NULL, &tv); + if (n == 0) + return 0; // nothing to read from the dvap + } else + n = select(serfd + 1, &fds, NULL, NULL, NULL); + + if (n < 0) { + traceit("select error=%d on dvap\n", errno); + return -1; + } + + if (n > 0) { + temp_len = read(serfd, buf + off, len - off); + if (temp_len > 0) + off += temp_len; + } + } + + return len; } static int write_to_dvp(unsigned char *buf, unsigned int len) { - unsigned int ptr = 0; - ssize_t n; - - if (len == 0) - return 0; - - while (ptr < len) - { - n = write(serfd, buf + ptr, len - ptr); - if (n < 0) - { - traceit("Error %d writing to dvap\n", errno); - return -1; - } - - if (n > 0) - ptr += n; - } - - return len; + unsigned int ptr = 0; + ssize_t n; + + if (len == 0) + return 0; + + while (ptr < len) { + n = write(serfd, buf + ptr, len - ptr); + if (n < 0) { + traceit("Error %d writing to dvap\n", errno); + return -1; + } + + if (n > 0) + ptr += n; + } + + return len; } static REPLY_TYPE get_reply(unsigned char *buf, unsigned int *len) { - unsigned int off = 2; - int rc = -1; - - rc = read_from_dvp(buf, 2); - if (rc == 0) - return RT_TIMEOUT; - if (rc != 2) - return RT_ERR; - - *len = buf[0] + (buf[1] & 0x1f) * 256; - if (*len > 50) - { - syncit(); - return RT_TIMEOUT; - } - - while (off < *len) - { - rc = read_from_dvp(buf + off, *len - off); - if (rc < 0) - return RT_TIMEOUT; - if (rc > 0) - off += rc; - } - - if (memcmp(buf, DVP_STS, 4) == 0) - return RT_STS; - else - if (memcmp(buf, DVP_DAT, 2) == 0) - return RT_DAT; - else - if (memcmp(buf, DVP_HDR, 2) == 0) - return RT_HDR; - else - if (memcmp(buf, DVP_REPL_HDR, 2) == 0) - return RT_HDR_ACK; - else - if (memcmp(buf, DVP_REPL_PTT, 4) == 0) - return RT_PTT; - else - if (memcmp(buf, DVP_REPL_START, 5) == 0) - return RT_START; - else - if (memcmp(buf, DVP_REPL_STOP, 5) == 0) - return RT_STOP; - else - if (memcmp(buf, DVP_REPL_OFF, 4) == 0) - return RT_OFF; - else - if (memcmp(buf, DVP_REPL_NAME, 4) == 0) - return RT_NAME; - else - if (memcmp(buf + 1, DVP_REPL_SER + 1, 3) == 0) - return RT_SER; - else - if (memcmp(buf, DVP_REPL_FW, 5) == 0) - return RT_FW; - else - if (memcmp(buf, DVP_REPL_FREQ, 4) == 0) - return RT_FREQ; - else - if (memcmp(buf, DVP_REPL_MODU, 5) == 0) - return RT_MODU; - else - if (memcmp(buf, DVP_REPL_MODE, 5) == 0) - return RT_MODE; - else - if (memcmp(buf, DVP_REPL_PWR, 4) == 0) - return RT_PWR; - else - if (memcmp(buf, DVP_REPL_SQL, 4) == 0) - return RT_SQL; - else - { - syncit(); - return RT_TIMEOUT; - } - - /* It should never get here */ - return RT_TIMEOUT; + unsigned int off = 2; + int rc = -1; + + rc = read_from_dvp(buf, 2); + if (rc == 0) + return RT_TIMEOUT; + if (rc != 2) + return RT_ERR; + + *len = buf[0] + (buf[1] & 0x1f) * 256; + if (*len > 50) { + syncit(); + return RT_TIMEOUT; + } + + while (off < *len) { + rc = read_from_dvp(buf + off, *len - off); + if (rc < 0) + return RT_TIMEOUT; + if (rc > 0) + off += rc; + } + + if (memcmp(buf, DVP_STS, 4) == 0) + return RT_STS; + else if (memcmp(buf, DVP_DAT, 2) == 0) + return RT_DAT; + else if (memcmp(buf, DVP_HDR, 2) == 0) + return RT_HDR; + else if (memcmp(buf, DVP_REPL_HDR, 2) == 0) + return RT_HDR_ACK; + else if (memcmp(buf, DVP_REPL_PTT, 4) == 0) + return RT_PTT; + else if (memcmp(buf, DVP_REPL_START, 5) == 0) + return RT_START; + else if (memcmp(buf, DVP_REPL_STOP, 5) == 0) + return RT_STOP; + else if (memcmp(buf, DVP_REPL_OFF, 4) == 0) + return RT_OFF; + else if (memcmp(buf, DVP_REPL_NAME, 4) == 0) + return RT_NAME; + else if (memcmp(buf + 1, DVP_REPL_SER + 1, 3) == 0) + return RT_SER; + else if (memcmp(buf, DVP_REPL_FW, 5) == 0) + return RT_FW; + else if (memcmp(buf, DVP_REPL_FREQ, 4) == 0) + return RT_FREQ; + else if (memcmp(buf, DVP_REPL_MODU, 5) == 0) + return RT_MODU; + else if (memcmp(buf, DVP_REPL_MODE, 5) == 0) + return RT_MODE; + else if (memcmp(buf, DVP_REPL_PWR, 4) == 0) + return RT_PWR; + else if (memcmp(buf, DVP_REPL_SQL, 4) == 0) + return RT_SQL; + else { + syncit(); + return RT_TIMEOUT; + } + + /* It should never get here */ + return RT_TIMEOUT; } static void syncit() { - unsigned char data[7]; - unsigned char c; - int n; - struct timeval tv; - fd_set fds; - short cnt = 0; - - traceit("Starting syncing dvap\n"); - memset(data, 0x00, 7); - - while (memcmp(data, DVP_STS, 4) != 0) - { - FD_ZERO(&fds); - FD_SET(serfd, &fds); - tv.tv_sec = 0; - tv.tv_usec = 1000; - n = select(serfd + 1, &fds, NULL, NULL, &tv); - if (n <= 0) - { - cnt ++; - if (cnt > 100) - { - traceit("dvap is not responding,...stopping\n"); - keep_running = false; - return; - } - } - else - { - n = read_from_dvp(&c, 1); - if (n > 0) - { - data[0] = data[1]; - data[1] = data[2]; - data[2] = data[3]; - data[3] = data[4]; - data[4] = data[5]; - data[5] = data[6]; - data[6] = c; - - cnt = 0; - } - } - } - traceit("Stopping syncing dvap\n"); - return; + unsigned char data[7]; + unsigned char c; + int n; + struct timeval tv; + fd_set fds; + short cnt = 0; + + traceit("Starting syncing dvap\n"); + memset(data, 0x00, 7); + + while (memcmp(data, DVP_STS, 4) != 0) { + FD_ZERO(&fds); + FD_SET(serfd, &fds); + tv.tv_sec = 0; + tv.tv_usec = 1000; + n = select(serfd + 1, &fds, NULL, NULL, &tv); + if (n <= 0) { + cnt ++; + if (cnt > 100) { + traceit("dvap is not responding,...stopping\n"); + keep_running = false; + return; + } + } else { + n = read_from_dvp(&c, 1); + if (n > 0) { + data[0] = data[1]; + data[1] = data[2]; + data[2] = data[3]; + data[3] = data[4]; + data[4] = data[5]; + data[5] = data[6]; + data[6] = c; + + cnt = 0; + } + } + } + traceit("Stopping syncing dvap\n"); + return; } static bool get_name() { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - bool testit = false; - int rc = -1; - unsigned char dvp_buf[200]; - - rc = write_to_dvp(DVP_RQST_NAME, 4); - if (rc != 4) - { - traceit("Failed to send request to get dvap name\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to receive dvap name\n"); - return false; - } - } while (reply != RT_NAME); - - testit = (memcmp(dvp_buf, DVP_REPL_NAME, len) == 0); - - if (!testit) - { - traceit("Failed to receive dvap name\n"); - return false; - } - - traceit("Device name: %.*s\n", 11, dvp_buf + 4); - return true; + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + bool testit = false; + int rc = -1; + unsigned char dvp_buf[200]; + + rc = write_to_dvp(DVP_RQST_NAME, 4); + if (rc != 4) { + traceit("Failed to send request to get dvap name\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to receive dvap name\n"); + return false; + } + } while (reply != RT_NAME); + + testit = (memcmp(dvp_buf, DVP_REPL_NAME, len) == 0); + + if (!testit) { + traceit("Failed to receive dvap name\n"); + return false; + } + + traceit("Device name: %.*s\n", 11, dvp_buf + 4); + return true; } static bool get_fw() { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - unsigned int ver; - int rc = -1; - unsigned char dvp_buf[200]; - - rc = write_to_dvp(DVP_RQST_FW, 5); - if (rc != 5) - { - traceit("Failed to send request to get dvap fw\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to receive dvap fw\n"); - return false; - } - } while (reply != RT_FW); - - ver = dvp_buf[6] * 256 + dvp_buf[5]; - traceit("dvap fw ver: %u.%u\n", ver / 100, ver % 100); - - return true; + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + unsigned int ver; + int rc = -1; + unsigned char dvp_buf[200]; + + rc = write_to_dvp(DVP_RQST_FW, 5); + if (rc != 5) { + traceit("Failed to send request to get dvap fw\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to receive dvap fw\n"); + return false; + } + } while (reply != RT_FW); + + ver = dvp_buf[6] * 256 + dvp_buf[5]; + traceit("dvap fw ver: %u.%u\n", ver / 100, ver % 100); + + return true; } static bool get_ser(char *dvp) { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - int rc = -1; - unsigned char dvp_buf[200]; - - rc = write_to_dvp(DVP_RQST_SER, 4); - if (rc != 4) - { - traceit("Failed to send request to get dvap serial#\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to receive dvap serial#\n"); - return false; - } - } while (reply != RT_SER); - - if (strcmp((char *)(dvp_buf + 4), DVP_SERIAL) == 0) - { - traceit("Using %s: %s, because serial number matches your dvap_rptr.cfg\n", - dvp, DVP_SERIAL); - return true; - } - else - { - traceit("Device %s has serial %s, but does not match your config value %s\n", dvp, dvp_buf + 4, DVP_SERIAL); - return false; - } + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + int rc = -1; + unsigned char dvp_buf[200]; + + rc = write_to_dvp(DVP_RQST_SER, 4); + if (rc != 4) { + traceit("Failed to send request to get dvap serial#\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to receive dvap serial#\n"); + return false; + } + } while (reply != RT_SER); + + if (strcmp((char *)(dvp_buf + 4), DVP_SERIAL) == 0) { + traceit("Using %s: %s, because serial number matches your dvap_rptr.cfg\n", + dvp, DVP_SERIAL); + return true; + } else { + traceit("Device %s has serial %s, but does not match your config value %s\n", dvp, dvp_buf + 4, DVP_SERIAL); + return false; + } } static bool set_modu() { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - int rc = -1; - unsigned char dvp_buf[200]; - - rc = write_to_dvp(DVP_RQST_MODU, 5); - if (rc != 5) - { - traceit("Failed to send request to set dvap modulation\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to set dvap modulation\n"); - return false; - } - } while (reply != RT_MODU); - - return true; + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + int rc = -1; + unsigned char dvp_buf[200]; + + rc = write_to_dvp(DVP_RQST_MODU, 5); + if (rc != 5) { + traceit("Failed to send request to set dvap modulation\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to set dvap modulation\n"); + return false; + } + } while (reply != RT_MODU); + + return true; } static bool set_mode() { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - int rc = -1; - unsigned char dvp_buf[200]; - - rc = write_to_dvp(DVP_RQST_MODE, 5); - if (rc != 5) - { - traceit("Failed to send request to set dvap mode\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to set dvap mode\n"); - return false; - } - } while (reply != RT_MODE); - - return true; + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + int rc = -1; + unsigned char dvp_buf[200]; + + rc = write_to_dvp(DVP_RQST_MODE, 5); + if (rc != 5) { + traceit("Failed to send request to set dvap mode\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to set dvap mode\n"); + return false; + } + } while (reply != RT_MODE); + + return true; } static bool set_sql() { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - int rc = -1; - unsigned char buf[10]; - unsigned char dvp_buf[200]; - - memcpy(buf, DVP_RQST_SQL, 5); - memcpy(buf + 4, &DVP_SQL, 1); - - rc = write_to_dvp(buf, 5); - if (rc != 5) - { - traceit("Failed to send request to set dvap sql\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to set dvap sql\n"); - return false; - } - } while (reply != RT_SQL); - - return true; + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + int rc = -1; + unsigned char buf[10]; + unsigned char dvp_buf[200]; + + memcpy(buf, DVP_RQST_SQL, 5); + memcpy(buf + 4, &DVP_SQL, 1); + + rc = write_to_dvp(buf, 5); + if (rc != 5) { + traceit("Failed to send request to set dvap sql\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to set dvap sql\n"); + return false; + } + } while (reply != RT_SQL); + + return true; } static bool set_pwr() { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - int rc = -1; - unsigned char buf[10]; - int16_t temp_pwr; - unsigned char dvp_buf[200]; - - memcpy(buf, DVP_RQST_PWR, 6); - temp_pwr = (isit_bigendian())?do_swap16(DVP_PWR):DVP_PWR; - memcpy(buf + 4, &temp_pwr, sizeof(int16_t)); - - rc = write_to_dvp(buf, 6); - if (rc != 6) - { - traceit("Failed to send request to set dvap pwr\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to set dvap pwr\n"); - return false; - } - } while (reply != RT_PWR); - - return true; + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + int rc = -1; + unsigned char buf[10]; + int16_t temp_pwr; + unsigned char dvp_buf[200]; + + memcpy(buf, DVP_RQST_PWR, 6); + temp_pwr = (isit_bigendian())?do_swap16(DVP_PWR):DVP_PWR; + memcpy(buf + 4, &temp_pwr, sizeof(int16_t)); + + rc = write_to_dvp(buf, 6); + if (rc != 6) { + traceit("Failed to send request to set dvap pwr\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to set dvap pwr\n"); + return false; + } + } while (reply != RT_PWR); + + return true; } static bool set_off() { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - int rc = -1; - unsigned char buf[10]; - int16_t temp_off; - unsigned char dvp_buf[200]; - - memcpy(buf, DVP_RQST_OFF, 6); - temp_off = (isit_bigendian())?do_swap16(DVP_OFF):DVP_OFF; - memcpy(buf + 4, &temp_off, sizeof(int16_t)); - - rc = write_to_dvp(buf, 6); - if (rc != 6) - { - traceit("Failed to send request to set dvap offset\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to set dvap offset\n"); - return false; - } - } while (reply != RT_OFF); - - return true; + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + int rc = -1; + unsigned char buf[10]; + int16_t temp_off; + unsigned char dvp_buf[200]; + + memcpy(buf, DVP_RQST_OFF, 6); + temp_off = (isit_bigendian())?do_swap16(DVP_OFF):DVP_OFF; + memcpy(buf + 4, &temp_off, sizeof(int16_t)); + + rc = write_to_dvp(buf, 6); + if (rc != 6) { + traceit("Failed to send request to set dvap offset\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to set dvap offset\n"); + return false; + } + } while (reply != RT_OFF); + + return true; } static bool set_freq() { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - int rc = -1; - unsigned char buf[10]; - u_int32_t temp_freq; - unsigned char dvp_buf[200]; - - memcpy(buf, DVP_RQST_FREQ, 8); - temp_freq = (isit_bigendian())?do_swapu32(DVP_FREQ):DVP_FREQ; - memcpy(buf + 4, &temp_freq, sizeof(u_int32_t)); - - rc = write_to_dvp(buf, 8); - if (rc != 8) - { - traceit("Failed to send request to set dvap frequency\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to set dvap frequency\n"); - return false; - } - } while (reply != RT_FREQ); - - return true; + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + int rc = -1; + unsigned char buf[10]; + u_int32_t temp_freq; + unsigned char dvp_buf[200]; + + memcpy(buf, DVP_RQST_FREQ, 8); + temp_freq = (isit_bigendian())?do_swapu32(DVP_FREQ):DVP_FREQ; + memcpy(buf + 4, &temp_freq, sizeof(u_int32_t)); + + rc = write_to_dvp(buf, 8); + if (rc != 8) { + traceit("Failed to send request to set dvap frequency\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to set dvap frequency\n"); + return false; + } + } while (reply != RT_FREQ); + + return true; } static bool start_dvap() { - unsigned cnt = 0; - unsigned int len = 0; - REPLY_TYPE reply; - int rc = -1; - unsigned char dvp_buf[200]; - - rc = write_to_dvp(DVP_RQST_START, 5); - if (rc != 5) - { - traceit("Failed to send request to start the dvap dongle\n"); - return false; - } - - do { - usleep(5000); - - reply = get_reply(dvp_buf, &len); - - cnt ++; - if (cnt >= MAX_REPL_CNT) - { - traceit("Reached max number of requests to start the dvap dongle\n"); - return false; - } - } while (reply != RT_START); - - return true; + unsigned cnt = 0; + unsigned int len = 0; + REPLY_TYPE reply; + int rc = -1; + unsigned char dvp_buf[200]; + + rc = write_to_dvp(DVP_RQST_START, 5); + if (rc != 5) { + traceit("Failed to send request to start the dvap dongle\n"); + return false; + } + + do { + usleep(5000); + + reply = get_reply(dvp_buf, &len); + + cnt ++; + if (cnt >= MAX_REPL_CNT) { + traceit("Reached max number of requests to start the dvap dongle\n"); + return false; + } + } while (reply != RT_START); + + return true; } static void readFrom20000() { - unsigned char dvp_buf[200]; - struct sockaddr_in from; - socklen_t fromlen; - int len; - fd_set readfd; - struct timeval tv; - int inactive = 0; - short seq_no = 0; - unsigned streamid[2] = {0x00, 0x00}; - u_int16_t sid; - unsigned char sync_codes[3] = {0x55, 0x2d, 0x16}; - struct pkt net_buf; - u_int16_t stream_id_to_dvap = 0; - u_int8_t frame_pos_to_dvap = 0; - u_int8_t seq_to_dvap = 0; - char silence[12] = - { - 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8, - 0x70,0x4f,0x93 - }; - - bool written_to_q = false; - unsigned char ctrl_in = 0x80; - - while (keep_running) - { - written_to_q = false; - - tv.tv_sec = 0; - tv.tv_usec = WAIT_FOR_PACKETS; - fromlen = sizeof(struct sockaddr); - FD_ZERO (&readfd); - FD_SET (insock, &readfd); - select(insock + 1, &readfd, NULL, NULL, &tv); - - if (FD_ISSET(insock, &readfd)) - { - len = recvfrom (insock, (char *)&net_buf, 58, 0, (struct sockaddr *)&from, &fromlen); - if (len == 58) - { - if (busy20000) - { - FD_CLR (insock, &readfd); - continue; - } - - /* check the module and gateway */ - if (net_buf.rf_hdr.rpt2[7] != RPTR_MOD) - { - FD_CLR (insock, &readfd); - break; - } - memcpy(net_buf.rf_hdr.rpt1, OWNER, 7); - net_buf.rf_hdr.rpt1[7] = 'G'; - - if (memcmp(RPTR, OWNER, RPTR_SIZE) != 0) - { - // restriction mode - memcpy(net_buf.rf_hdr.rpt1, RPTR, 7); - memcpy(net_buf.rf_hdr.rpt2, RPTR, 7); - - if (memcmp(net_buf.rf_hdr.mycall, OWNER, 7) == 0) - { - /* this is an ACK back */ - memcpy(net_buf.rf_hdr.mycall, RPTR, 7); - } - } - - if ((net_buf.rf_hdr.flags[0] != 0x00) && - (net_buf.rf_hdr.flags[0] != 0x01) && - (net_buf.rf_hdr.flags[0] != 0x08) && - (net_buf.rf_hdr.flags[0] != 0x20) && - (net_buf.rf_hdr.flags[0] != 0x28) && - (net_buf.rf_hdr.flags[0] != 0x40)) - { - FD_CLR (insock, &readfd); - break; - } - - if ((memcmp(net_buf.pkt_id, "DSTR", 4) != 0) || - (net_buf.flags[0] != 0x73) || - (net_buf.flags[1] != 0x12) || - (net_buf.myicm.icm_id != 0x20)) /* voice type */ - { - FD_CLR (insock, &readfd); - break; - } - - busy20000 = true; - - ctrl_in = 0x80; - written_to_q = true; - - traceit("Start G2: streamid=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s\n", - net_buf.myicm.streamid[0], net_buf.myicm.streamid[1], - net_buf.rf_hdr.flags[0], net_buf.rf_hdr.flags[1], net_buf.rf_hdr.flags[2], - net_buf.rf_hdr.mycall, net_buf.rf_hdr.sfx, net_buf.rf_hdr.urcall, - net_buf.rf_hdr.rpt2, net_buf.rf_hdr.rpt1); - - /* save the streamid that is winning */ - streamid[0] = net_buf.myicm.streamid[0]; - streamid[1] = net_buf.myicm.streamid[1]; - - if (net_buf.rf_hdr.flags[0] != 0x01) - { - - if (net_buf.rf_hdr.flags[0] == 0x00) - net_buf.rf_hdr.flags[0] = 0x40; - else - if (net_buf.rf_hdr.flags[0] == 0x08) - net_buf.rf_hdr.flags[0] = 0x48; - else - if (net_buf.rf_hdr.flags[0] == 0x20) - net_buf.rf_hdr.flags[0] = 0x60; - else - if (net_buf.rf_hdr.flags[0] == 0x28) - net_buf.rf_hdr.flags[0] = 0x68; - else - net_buf.rf_hdr.flags[0] = 0x40; - } - net_buf.rf_hdr.flags[1] = 0x00; - net_buf.rf_hdr.flags[2] = 0x00; - - // write the header packet to the dvap here - while ((space < 1) && keep_running) - usleep(5); - stream_id_to_dvap = (rand_r(&aseed) % 65535U) + 1U; - memcpy(dvp_buf, DVP_HDR, 47); - sid = (isit_bigendian())?do_swapu16(stream_id_to_dvap):stream_id_to_dvap; - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x80; - dvp_buf[5] = 0; - memset(dvp_buf + 6, ' ', 41); - dvp_buf[6] = net_buf.rf_hdr.flags[0]; - dvp_buf[7] = net_buf.rf_hdr.flags[1]; - dvp_buf[8] = net_buf.rf_hdr.flags[2]; - memcpy(dvp_buf + 9, net_buf.rf_hdr.rpt1, 8); - memcpy(dvp_buf + 17, net_buf.rf_hdr.rpt2, 8); - memcpy(dvp_buf + 25, net_buf.rf_hdr.urcall, 8); - memcpy(dvp_buf + 33, net_buf.rf_hdr.mycall, 8); - memcpy(dvp_buf + 41, net_buf.rf_hdr.sfx, 4); - calcPFCS(dvp_buf + 6, dvp_buf + 45); - frame_pos_to_dvap = 0; - seq_to_dvap = 0; - (void)write_to_dvp(dvp_buf, 47); - - inactive = 0; - seq_no = 0; - } - else - if (len == 29) - { - if (busy20000) - { - if ((net_buf.myicm.streamid[0] == streamid[0]) && - (net_buf.myicm.streamid[1] == streamid[1])) - { - if (net_buf.myicm.ctrl == ctrl_in) - { - /* do not update written_to_q, ctrl_in */ - ; // traceit("dup\n"); - } - else - { - ctrl_in = net_buf.myicm.ctrl; - written_to_q = true; - - if (seq_no == 0) - { - net_buf.rf_audio.buff[9] = 0x55; - net_buf.rf_audio.buff[10] = 0x2d; - net_buf.rf_audio.buff[11] = 0x16; - } - else - { - if ((net_buf.rf_audio.buff[9] == 0x55) && - (net_buf.rf_audio.buff[10] == 0x2d) && - (net_buf.rf_audio.buff[11] == 0x16)) - { - net_buf.rf_audio.buff[9] = 0x70; - net_buf.rf_audio.buff[10] = 0x4f; - net_buf.rf_audio.buff[11] = 0x93; - } - } - - // write the audio packet to the dvap here - while ((space < 1) && keep_running) - usleep(5); - memcpy(dvp_buf, DVP_DAT, 18); - if (memcmp(net_buf.rf_audio.buff + 9, sync_codes, 3) == 0) - frame_pos_to_dvap = 0; - sid = (isit_bigendian())?do_swapu16(stream_id_to_dvap):stream_id_to_dvap; - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = frame_pos_to_dvap; - dvp_buf[5] = seq_to_dvap; - if ((net_buf.myicm.ctrl & 0x40) != 0) - dvp_buf[4] |= 0x40U; - memcpy(dvp_buf + 6, net_buf.rf_audio.buff, 12); - (void)write_to_dvp(dvp_buf, 18); - frame_pos_to_dvap ++; - seq_to_dvap ++; - - inactive = 0; - - seq_no ++; - if (seq_no == 21) - seq_no = 0; - - if ((net_buf.myicm.ctrl & 0x40) != 0) - { - traceit("End G2: streamid=%d,%d\n", net_buf.myicm.streamid[0], net_buf.myicm.streamid[1]); - - streamid[0] = 0x00; - streamid[1] = 0x00; - - inactive = 0; - FD_CLR (insock, &readfd); - // maybe put a sleep here to prevent fast voice-overs - - busy20000 = false; - break; - } - } - } - } - else - { - FD_CLR (insock, &readfd); - break; - } - } - else - { - if (!busy20000) - { - FD_CLR (insock, &readfd); - break; - } - } - FD_CLR (insock, &readfd); - } - - /* - If we received a dup or select() timed out or streamids dont match, - then written_to_q is false - */ - if (!written_to_q) /* nothing was written to the adapter */ - { - if (busy20000) - { - if (++inactive == inactiveMax) - { - traceit("G2 Timeout...\n"); - - streamid[0] = 0x00; - streamid[1] = 0x00; - - inactive = 0; - // maybe put a sleep here to prevent fast voice-overs - - busy20000 = false; - break; - } - else - { - if (space == 127) - { - if (seq_no == 0) - { - silence[9] = 0x55; - silence[10] = 0x2d; - silence[11] = 0x16; - } - else - { - silence[9] = 0x70; - silence[10] = 0x4f; - silence[11] = 0x93; - } - - memcpy(dvp_buf, DVP_DAT, 18); - if (memcmp(silence + 9, sync_codes, 3) == 0) - frame_pos_to_dvap = 0; - sid = (isit_bigendian())?do_swapu16(stream_id_to_dvap):stream_id_to_dvap; - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = frame_pos_to_dvap; - dvp_buf[5] = seq_to_dvap; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - frame_pos_to_dvap ++; - seq_to_dvap ++; - - seq_no ++; - if (seq_no == 21) - seq_no = 0; - } - } - } - else - break; - } - } - return; + unsigned char dvp_buf[200]; + struct sockaddr_in from; + socklen_t fromlen; + int len; + fd_set readfd; + struct timeval tv; + int inactive = 0; + short seq_no = 0; + unsigned streamid[2] = {0x00, 0x00}; + u_int16_t sid; + unsigned char sync_codes[3] = {0x55, 0x2d, 0x16}; + struct pkt net_buf; + u_int16_t stream_id_to_dvap = 0; + u_int8_t frame_pos_to_dvap = 0; + u_int8_t seq_to_dvap = 0; + unsigned char silence[12] = { 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8,0x70,0x4f,0x93 }; + + bool written_to_q = false; + unsigned char ctrl_in = 0x80; + + while (keep_running) { + written_to_q = false; + + tv.tv_sec = 0; + tv.tv_usec = WAIT_FOR_PACKETS; + fromlen = sizeof(struct sockaddr); + FD_ZERO (&readfd); + FD_SET (insock, &readfd); + select(insock + 1, &readfd, NULL, NULL, &tv); + + if (FD_ISSET(insock, &readfd)) { + len = recvfrom (insock, (char *)&net_buf, 58, 0, (struct sockaddr *)&from, &fromlen); + if (len == 58) { + if (busy20000) { + FD_CLR (insock, &readfd); + continue; + } + + /* check the module and gateway */ + if (net_buf.rf_hdr.rpt2[7] != RPTR_MOD) { + FD_CLR (insock, &readfd); + break; + } + memcpy(net_buf.rf_hdr.rpt1, OWNER, 7); + net_buf.rf_hdr.rpt1[7] = 'G'; + + if (memcmp(RPTR, OWNER, RPTR_SIZE) != 0) { + // restriction mode + memcpy(net_buf.rf_hdr.rpt1, RPTR, 7); + memcpy(net_buf.rf_hdr.rpt2, RPTR, 7); + + if (memcmp(net_buf.rf_hdr.mycall, OWNER, 7) == 0) { + /* this is an ACK back */ + memcpy(net_buf.rf_hdr.mycall, RPTR, 7); + } + } + + if ((net_buf.rf_hdr.flags[0] != 0x00) && + (net_buf.rf_hdr.flags[0] != 0x01) && + (net_buf.rf_hdr.flags[0] != 0x08) && + (net_buf.rf_hdr.flags[0] != 0x20) && + (net_buf.rf_hdr.flags[0] != 0x28) && + (net_buf.rf_hdr.flags[0] != 0x40)) { + FD_CLR (insock, &readfd); + break; + } + + if ((memcmp(net_buf.pkt_id, "DSTR", 4) != 0) || + (net_buf.flags[0] != 0x73) || + (net_buf.flags[1] != 0x12) || + (net_buf.myicm.icm_id != 0x20)) { /* voice type */ + FD_CLR (insock, &readfd); + break; + } + + busy20000 = true; + + ctrl_in = 0x80; + written_to_q = true; + + traceit("Start G2: streamid=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s\n", + net_buf.myicm.streamid[0], net_buf.myicm.streamid[1], + net_buf.rf_hdr.flags[0], net_buf.rf_hdr.flags[1], net_buf.rf_hdr.flags[2], + net_buf.rf_hdr.mycall, net_buf.rf_hdr.sfx, net_buf.rf_hdr.urcall, + net_buf.rf_hdr.rpt2, net_buf.rf_hdr.rpt1); + + /* save the streamid that is winning */ + streamid[0] = net_buf.myicm.streamid[0]; + streamid[1] = net_buf.myicm.streamid[1]; + + if (net_buf.rf_hdr.flags[0] != 0x01) { + + if (net_buf.rf_hdr.flags[0] == 0x00) + net_buf.rf_hdr.flags[0] = 0x40; + else if (net_buf.rf_hdr.flags[0] == 0x08) + net_buf.rf_hdr.flags[0] = 0x48; + else if (net_buf.rf_hdr.flags[0] == 0x20) + net_buf.rf_hdr.flags[0] = 0x60; + else if (net_buf.rf_hdr.flags[0] == 0x28) + net_buf.rf_hdr.flags[0] = 0x68; + else + net_buf.rf_hdr.flags[0] = 0x40; + } + net_buf.rf_hdr.flags[1] = 0x00; + net_buf.rf_hdr.flags[2] = 0x00; + + // write the header packet to the dvap here + while ((space < 1) && keep_running) + usleep(5); + stream_id_to_dvap = (rand_r(&aseed) % 65535U) + 1U; + memcpy(dvp_buf, DVP_HDR, 47); + sid = (isit_bigendian())?do_swapu16(stream_id_to_dvap):stream_id_to_dvap; + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x80; + dvp_buf[5] = 0; + memset(dvp_buf + 6, ' ', 41); + dvp_buf[6] = net_buf.rf_hdr.flags[0]; + dvp_buf[7] = net_buf.rf_hdr.flags[1]; + dvp_buf[8] = net_buf.rf_hdr.flags[2]; + memcpy(dvp_buf + 9, net_buf.rf_hdr.rpt1, 8); + memcpy(dvp_buf + 17, net_buf.rf_hdr.rpt2, 8); + memcpy(dvp_buf + 25, net_buf.rf_hdr.urcall, 8); + memcpy(dvp_buf + 33, net_buf.rf_hdr.mycall, 8); + memcpy(dvp_buf + 41, net_buf.rf_hdr.sfx, 4); + calcPFCS(dvp_buf + 6, dvp_buf + 45); + frame_pos_to_dvap = 0; + seq_to_dvap = 0; + (void)write_to_dvp(dvp_buf, 47); + + inactive = 0; + seq_no = 0; + } else if (len == 29) { + if (busy20000) { + if ((net_buf.myicm.streamid[0] == streamid[0]) && + (net_buf.myicm.streamid[1] == streamid[1])) { + if (net_buf.myicm.ctrl == ctrl_in) { + /* do not update written_to_q, ctrl_in */ + ; // traceit("dup\n"); + } else { + ctrl_in = net_buf.myicm.ctrl; + written_to_q = true; + + if (seq_no == 0) { + net_buf.rf_audio.buff[9] = 0x55; + net_buf.rf_audio.buff[10] = 0x2d; + net_buf.rf_audio.buff[11] = 0x16; + } else { + if ((net_buf.rf_audio.buff[9] == 0x55) && + (net_buf.rf_audio.buff[10] == 0x2d) && + (net_buf.rf_audio.buff[11] == 0x16)) { + net_buf.rf_audio.buff[9] = 0x70; + net_buf.rf_audio.buff[10] = 0x4f; + net_buf.rf_audio.buff[11] = 0x93; + } + } + + // write the audio packet to the dvap here + while ((space < 1) && keep_running) + usleep(5); + memcpy(dvp_buf, DVP_DAT, 18); + if (memcmp(net_buf.rf_audio.buff + 9, sync_codes, 3) == 0) + frame_pos_to_dvap = 0; + sid = (isit_bigendian())?do_swapu16(stream_id_to_dvap):stream_id_to_dvap; + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = frame_pos_to_dvap; + dvp_buf[5] = seq_to_dvap; + if ((net_buf.myicm.ctrl & 0x40) != 0) + dvp_buf[4] |= 0x40U; + memcpy(dvp_buf + 6, net_buf.rf_audio.buff, 12); + (void)write_to_dvp(dvp_buf, 18); + frame_pos_to_dvap ++; + seq_to_dvap ++; + + inactive = 0; + + seq_no ++; + if (seq_no == 21) + seq_no = 0; + + if ((net_buf.myicm.ctrl & 0x40) != 0) { + traceit("End G2: streamid=%d,%d\n", net_buf.myicm.streamid[0], net_buf.myicm.streamid[1]); + + streamid[0] = 0x00; + streamid[1] = 0x00; + + inactive = 0; + FD_CLR (insock, &readfd); + // maybe put a sleep here to prevent fast voice-overs + + busy20000 = false; + break; + } + } + } + } else { + FD_CLR (insock, &readfd); + break; + } + } else { + if (!busy20000) { + FD_CLR (insock, &readfd); + break; + } + } + FD_CLR (insock, &readfd); + } + + /* + If we received a dup or select() timed out or streamids dont match, + then written_to_q is false + */ + if (!written_to_q) { /* nothing was written to the adapter */ + if (busy20000) { + if (++inactive == inactiveMax) { + traceit("G2 Timeout...\n"); + + streamid[0] = 0x00; + streamid[1] = 0x00; + + inactive = 0; + // maybe put a sleep here to prevent fast voice-overs + + busy20000 = false; + break; + } else { + if (space == 127) { + if (seq_no == 0) { + silence[9] = 0x55; + silence[10] = 0x2d; + silence[11] = 0x16; + } else { + silence[9] = 0x70; + silence[10] = 0x4f; + silence[11] = 0x93; + } + + memcpy(dvp_buf, DVP_DAT, 18); + if (memcmp(silence + 9, sync_codes, 3) == 0) + frame_pos_to_dvap = 0; + sid = (isit_bigendian())?do_swapu16(stream_id_to_dvap):stream_id_to_dvap; + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = frame_pos_to_dvap; + dvp_buf[5] = seq_to_dvap; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + frame_pos_to_dvap ++; + seq_to_dvap ++; + + seq_no ++; + if (seq_no == 21) + seq_no = 0; + } + } + } else + break; + } + } + return; } int main(int argc, const char **argv) { - struct sigaction act; - int rc = -1; - time_t tnow = 0; - time_t ackpoint = 0; - pthread_t readFromRF_t; - pthread_attr_t attr; - short cnt = 0; - - setvbuf(stdout, NULL, _IOLBF, 0); - traceit("dvap_rptr VERSION %s\n", VERSION); - - if (argc != 2) - { - traceit("Usage: dvap_rptr dvap_rptr.cfg\n"); - return 1; - } - - rc = read_config(argv[1]); - if (rc != 0) - { - traceit("Failed to process config file %s\n", argv[1]); - return 1; - } - - if (strlen(RPTR) != 8) - { - traceit("Bad RPTR value, length must be exactly 8 bytes\n"); - return 1; - } - if ((RPTR_MOD != 'A') && (RPTR_MOD != 'B') && (RPTR_MOD != 'C')) - { - traceit("Bad RPTR_MOD value, must be one of A or B or C\n"); - return 1; - } - - if (RPTR_MOD == 'A') - SND_TERM_ID = 0x03; - else - if (RPTR_MOD == 'B') - SND_TERM_ID = 0x01; - else - if (RPTR_MOD == 'C') - SND_TERM_ID = 0x02; - - strcpy(RPTR_and_G, RPTR); - RPTR_and_G[7] = 'G'; - - strcpy(RPTR_and_MOD, RPTR); - RPTR_and_MOD[7] = RPTR_MOD; - - time(&tnow); - aseed = tnow + getpid(); - - act.sa_handler = sig_catch; - sigemptyset(&act.sa_mask); - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - return 1; - } - if (sigaction(SIGHUP, &act, 0) != 0) - { - traceit("sigaction-HUP failed, error=%d\n", errno); - return 1; - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - return 1; - } - - /* open dvp */ - if (!open_dvp()) - return 1; - - rc = open_sock(); - if (rc != 0) - { - (void)write_to_dvp(DVP_RQST_STOP, 5); - close(serfd); - return 1; - } - - dstar_dv_init(); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&readFromRF_t, &attr, readFromRF, (void *)0); - if (rc != 0) - { - keep_running = false; - traceit("failed to start thread readFromRF thread\n"); - } - else - traceit("Started thread readFromRF\n"); - pthread_attr_destroy(&attr); - - while (keep_running) - { - time(&tnow); - if ((tnow - ackpoint) > 2) - { - rc = write_to_dvp(DVP_ACK, 3); - if (rc < 0) - { - cnt ++; - if (cnt > 5) - { - traceit("Could not send KEEPALIVE signal to dvap 5 times...exiting\n"); - keep_running = false; - } - } - else - cnt = 0; - ackpoint = tnow; - } - readFrom20000(); - } - - close(insock); - traceit("dvap_rptr exiting\n"); - return 0; + struct sigaction act; + int rc = -1; + time_t tnow = 0; + time_t ackpoint = 0; + pthread_t readFromRF_t; + pthread_attr_t attr; + short cnt = 0; + + setvbuf(stdout, NULL, _IOLBF, 0); + traceit("dvap_rptr VERSION %s\n", VERSION); + + if (argc != 2) { + traceit("Usage: dvap_rptr dvap_rptr.cfg\n"); + return 1; + } + + rc = read_config(argv[1]); + if (rc != 0) { + traceit("Failed to process config file %s\n", argv[1]); + return 1; + } + + if (strlen(RPTR) != 8) { + traceit("Bad RPTR value, length must be exactly 8 bytes\n"); + return 1; + } + if ((RPTR_MOD != 'A') && (RPTR_MOD != 'B') && (RPTR_MOD != 'C')) { + traceit("Bad RPTR_MOD value, must be one of A or B or C\n"); + return 1; + } + + if (RPTR_MOD == 'A') + SND_TERM_ID = 0x03; + else if (RPTR_MOD == 'B') + SND_TERM_ID = 0x01; + else if (RPTR_MOD == 'C') + SND_TERM_ID = 0x02; + + strcpy(RPTR_and_G, RPTR); + RPTR_and_G[7] = 'G'; + + strcpy(RPTR_and_MOD, RPTR); + RPTR_and_MOD[7] = RPTR_MOD; + + time(&tnow); + aseed = tnow + getpid(); + + act.sa_handler = sig_catch; + sigemptyset(&act.sa_mask); + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + return 1; + } + if (sigaction(SIGHUP, &act, 0) != 0) { + traceit("sigaction-HUP failed, error=%d\n", errno); + return 1; + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + return 1; + } + + /* open dvp */ + if (!open_dvp()) + return 1; + + rc = open_sock(); + if (rc != 0) { + (void)write_to_dvp(DVP_RQST_STOP, 5); + close(serfd); + return 1; + } + + dstar_dv_init(); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&readFromRF_t, &attr, readFromRF, (void *)0); + if (rc != 0) { + keep_running = false; + traceit("failed to start thread readFromRF thread\n"); + } else + traceit("Started thread readFromRF\n"); + pthread_attr_destroy(&attr); + + while (keep_running) { + time(&tnow); + if ((tnow - ackpoint) > 2) { + rc = write_to_dvp(DVP_ACK, 3); + if (rc < 0) { + cnt ++; + if (cnt > 5) { + traceit("Could not send KEEPALIVE signal to dvap 5 times...exiting\n"); + keep_running = false; + } + } else + cnt = 0; + ackpoint = tnow; + } + readFrom20000(); + } + + close(insock); + traceit("dvap_rptr exiting\n"); + return 0; } static void *rptr_ack(void *arg) { - char mycall[8]; - memcpy(mycall, ((struct dvap_ack_arg_type *)arg)->mycall, 8); - float ber = ((struct dvap_ack_arg_type *)arg)->ber; - - char RADIO_ID[21]; - - sprintf(RADIO_ID, "%20.2f", ber); - memcpy(RADIO_ID, "BER%", 4); - - struct sigaction act; - unsigned char dvp_buf[200]; - u_int16_t stream_id_to_dvap = 0; - u_int16_t sid; - time_t tnow = 0; - char silence[12] = - { - 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8, - 0x70,0x4f,0x93 - }; - unsigned int aseed_ack = 0; - struct timespec nanos; - - act.sa_handler = sig_catch; - sigemptyset(&act.sa_mask); - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - traceit("thread rptr_ack exiting\n"); - pthread_exit(NULL); - } - if (sigaction(SIGHUP, &act, 0) != 0) - { - traceit("sigaction-HUP failed, error=%d\n", errno); - traceit("thread rptr_ack exiting\n"); - pthread_exit(NULL); - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - traceit("thread rptr_ack exiting\n"); - pthread_exit(NULL); - } - - sleep(DELAY_BEFORE); - // traceit("ack-start\n"); - - time(&tnow); - aseed_ack = tnow + getpid(); - - stream_id_to_dvap = (rand_r(&aseed_ack) % 65535U) + 1U; - sid = (isit_bigendian())?do_swapu16(stream_id_to_dvap):stream_id_to_dvap; - - // HEADER - while ((space < 1) && keep_running) - usleep(5); - memcpy(dvp_buf, DVP_HDR, 47); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x80; - dvp_buf[5] = 0; - memset(dvp_buf + 6, ' ', 41); - dvp_buf[6] = 0x01; - dvp_buf[7] = 0x00; - dvp_buf[8] = 0x00; - memcpy(dvp_buf + 9, RPTR_and_MOD, 8); - memcpy(dvp_buf + 17, RPTR_and_G, 8); - memcpy(dvp_buf + 25, mycall, 8); - memcpy(dvp_buf + 33, RPTR_and_MOD, 8); - memcpy(dvp_buf + 41, (unsigned char *)" ", 4); - calcPFCS(dvp_buf + 6, dvp_buf + 45); - (void)write_to_dvp(dvp_buf, 47); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - // SYNC - while ((space < 1) && keep_running) - usleep(5); - silence[9] = 0x55; silence[10] = 0x2d; silence[11] = 0x16; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x00; - dvp_buf[5] = 0x00; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - // NOTHING - while ((space < 1) && keep_running) - usleep(5); - silence[9] = '@' ^ 0x70; - silence[10] = RADIO_ID[0] ^ 0x4f; - silence[11] = RADIO_ID[1] ^ 0x93; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x01; - dvp_buf[5] = 0x01; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - while ((space < 1) && keep_running) - usleep(5); - silence[9] = RADIO_ID[2] ^ 0x70; - silence[10] = RADIO_ID[3] ^ 0x4f; - silence[11] = RADIO_ID[4] ^ 0x93; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x02; - dvp_buf[5] = 0x02; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - while ((space < 1) && keep_running) - usleep(5); - silence[9] = 'A' ^ 0x70; - silence[10] = RADIO_ID[5] ^ 0x4f; - silence[11] = RADIO_ID[6] ^ 0x93; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x03; - dvp_buf[5] = 0x03; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - while ((space < 1) && keep_running) - usleep(5); - silence[9] = RADIO_ID[7] ^ 0x70; - silence[10] = RADIO_ID[8] ^ 0x4f; - silence[11] = RADIO_ID[9] ^ 0x93; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x04; - dvp_buf[5] = 0x04; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - while ((space < 1) && keep_running) - usleep(5); - silence[9] = 'B' ^ 0x70; - silence[10] = RADIO_ID[10] ^ 0x4f; - silence[11] = RADIO_ID[11] ^ 0x93; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x05; - dvp_buf[5] = 0x05; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - while ((space < 1) && keep_running) - usleep(5); - silence[9] = RADIO_ID[12] ^ 0x70; - silence[10] = RADIO_ID[13] ^ 0x4f; - silence[11] = RADIO_ID[14] ^ 0x93; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x06; - dvp_buf[5] = 0x06; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - while ((space < 1) && keep_running) - usleep(5); - silence[9] = 'C' ^ 0x70; - silence[10] = RADIO_ID[15] ^ 0x4f; - silence[11] = RADIO_ID[16] ^ 0x93; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x07; - dvp_buf[5] = 0x07; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - while ((space < 1) && keep_running) - usleep(5); - silence[9] = RADIO_ID[17] ^ 0x70; - silence[10] = RADIO_ID[18] ^ 0x4f; - silence[11] = RADIO_ID[19] ^ 0x93; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = 0x08; - dvp_buf[5] = 0x08; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - // END - while ((space < 1) && keep_running) - usleep(5); - silence[0] = 0x55; silence[1] = 0xc8; silence[2] = 0x7a; - silence[9] = 0x55; silence[10] = 0x55; silence[11] = 0x55; - memcpy(dvp_buf, DVP_DAT, 18); - memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); - dvp_buf[4] = (0x09 | 0x40); - dvp_buf[5] = 0x09; - memcpy(dvp_buf + 6, silence, 12); - (void)write_to_dvp(dvp_buf, 18); - - // traceit("ack-end\n"); - pthread_exit(NULL); + char mycall[8]; + memcpy(mycall, ((struct dvap_ack_arg_type *)arg)->mycall, 8); + float ber = ((struct dvap_ack_arg_type *)arg)->ber; + + char RADIO_ID[21]; + + sprintf(RADIO_ID, "%20.2f", ber); + memcpy(RADIO_ID, "BER%", 4); + + struct sigaction act; + unsigned char dvp_buf[200]; + u_int16_t stream_id_to_dvap = 0; + u_int16_t sid; + time_t tnow = 0; + unsigned char silence[12] = { 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8,0x70,0x4f,0x93 }; + unsigned int aseed_ack = 0; + struct timespec nanos; + + act.sa_handler = sig_catch; + sigemptyset(&act.sa_mask); + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + traceit("thread rptr_ack exiting\n"); + pthread_exit(NULL); + } + if (sigaction(SIGHUP, &act, 0) != 0) { + traceit("sigaction-HUP failed, error=%d\n", errno); + traceit("thread rptr_ack exiting\n"); + pthread_exit(NULL); + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + traceit("thread rptr_ack exiting\n"); + pthread_exit(NULL); + } + + sleep(DELAY_BEFORE); + // traceit("ack-start\n"); + + time(&tnow); + aseed_ack = tnow + getpid(); + + stream_id_to_dvap = (rand_r(&aseed_ack) % 65535U) + 1U; + sid = (isit_bigendian())?do_swapu16(stream_id_to_dvap):stream_id_to_dvap; + + // HEADER + while ((space < 1) && keep_running) + usleep(5); + memcpy(dvp_buf, DVP_HDR, 47); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x80; + dvp_buf[5] = 0; + memset(dvp_buf + 6, ' ', 41); + dvp_buf[6] = 0x01; + dvp_buf[7] = 0x00; + dvp_buf[8] = 0x00; + memcpy(dvp_buf + 9, RPTR_and_MOD, 8); + memcpy(dvp_buf + 17, RPTR_and_G, 8); + memcpy(dvp_buf + 25, mycall, 8); + memcpy(dvp_buf + 33, RPTR_and_MOD, 8); + memcpy(dvp_buf + 41, (unsigned char *)" ", 4); + calcPFCS(dvp_buf + 6, dvp_buf + 45); + (void)write_to_dvp(dvp_buf, 47); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + // SYNC + while ((space < 1) && keep_running) + usleep(5); + silence[9] = 0x55; + silence[10] = 0x2d; + silence[11] = 0x16; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x00; + dvp_buf[5] = 0x00; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + // NOTHING + while ((space < 1) && keep_running) + usleep(5); + silence[9] = '@' ^ 0x70; + silence[10] = RADIO_ID[0] ^ 0x4f; + silence[11] = RADIO_ID[1] ^ 0x93; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x01; + dvp_buf[5] = 0x01; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + while ((space < 1) && keep_running) + usleep(5); + silence[9] = RADIO_ID[2] ^ 0x70; + silence[10] = RADIO_ID[3] ^ 0x4f; + silence[11] = RADIO_ID[4] ^ 0x93; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x02; + dvp_buf[5] = 0x02; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + while ((space < 1) && keep_running) + usleep(5); + silence[9] = 'A' ^ 0x70; + silence[10] = RADIO_ID[5] ^ 0x4f; + silence[11] = RADIO_ID[6] ^ 0x93; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x03; + dvp_buf[5] = 0x03; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + while ((space < 1) && keep_running) + usleep(5); + silence[9] = RADIO_ID[7] ^ 0x70; + silence[10] = RADIO_ID[8] ^ 0x4f; + silence[11] = RADIO_ID[9] ^ 0x93; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x04; + dvp_buf[5] = 0x04; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + while ((space < 1) && keep_running) + usleep(5); + silence[9] = 'B' ^ 0x70; + silence[10] = RADIO_ID[10] ^ 0x4f; + silence[11] = RADIO_ID[11] ^ 0x93; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x05; + dvp_buf[5] = 0x05; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + while ((space < 1) && keep_running) + usleep(5); + silence[9] = RADIO_ID[12] ^ 0x70; + silence[10] = RADIO_ID[13] ^ 0x4f; + silence[11] = RADIO_ID[14] ^ 0x93; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x06; + dvp_buf[5] = 0x06; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + while ((space < 1) && keep_running) + usleep(5); + silence[9] = 'C' ^ 0x70; + silence[10] = RADIO_ID[15] ^ 0x4f; + silence[11] = RADIO_ID[16] ^ 0x93; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x07; + dvp_buf[5] = 0x07; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + while ((space < 1) && keep_running) + usleep(5); + silence[9] = RADIO_ID[17] ^ 0x70; + silence[10] = RADIO_ID[18] ^ 0x4f; + silence[11] = RADIO_ID[19] ^ 0x93; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = 0x08; + dvp_buf[5] = 0x08; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + // END + while ((space < 1) && keep_running) + usleep(5); + silence[0] = 0x55; + silence[1] = 0xc8; + silence[2] = 0x7a; + silence[9] = 0x55; + silence[10] = 0x55; + silence[11] = 0x55; + memcpy(dvp_buf, DVP_DAT, 18); + memcpy(dvp_buf + 2, &sid, sizeof(u_int16_t)); + dvp_buf[4] = (0x09 | 0x40); + dvp_buf[5] = 0x09; + memcpy(dvp_buf + 6, silence, 12); + (void)write_to_dvp(dvp_buf, 18); + + // traceit("ack-end\n"); + pthread_exit(NULL); } static void *readFromRF(void *arg) { - REPLY_TYPE reply; - unsigned int len = 0; - unsigned char dvp_buf[200]; - struct pkt net_buf; - time_t tnow = 0; - time_t S_ctrl_msg_time = 0; - unsigned char S_packet[26]; - unsigned short C_COUNTER = 0; - time_t last_RF_time = 0; - struct sigaction act; - bool dvap_busy = false; - bool ptt = false; - bool the_end = true; - dvap_hdr *from_dvap_hdr = (dvap_hdr *)dvp_buf; - // dvap_voice *from_dvap_voice = (dvap_voice *)dvp_buf; - bool ok = true; - int i = 0; - u_int16_t streamid_raw = 0; - short int sequence = 0x00; - char mycall[8]; - pthread_t rptr_ack_t; - pthread_attr_t attr; - int rc = -1; - short int status_cntr = 3000; - char temp_yrcall[CALL_SIZE + 1]; - char *temp_ptr = NULL; - - num_dv_frames = 0; - num_bit_errors = 0; - - arg = arg; - act.sa_handler = sig_catch; - sigemptyset(&act.sa_mask); - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - keep_running = false; - traceit("thread readFromRF exiting\n"); - pthread_exit(NULL); - } - if (sigaction(SIGHUP, &act, 0) != 0) - { - traceit("sigaction-HUP failed, error=%d\n", errno); - keep_running = false; - traceit("thread readFromRF exiting\n"); - pthread_exit(NULL); - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - keep_running = false; - traceit("thread readFromRF exiting\n"); - pthread_exit(NULL); - } - - /* prepare the S server status packet */ - memcpy(S_packet, "DSTR", 4); - S_packet[4] = 0x00; - S_packet[5] = 0x00; - S_packet[6] = 0x73; - S_packet[7] = 0x21; - S_packet[8] = 0x00; - S_packet[9] = 0x10; - - while (keep_running) - { - time(&tnow); - - /* send the S packet if needed */ - if ((tnow - S_ctrl_msg_time) > 60) - { - S_packet[5] = (unsigned char)(C_COUNTER & 0xff); - S_packet[4] = ((C_COUNTER >> 8) & 0xff); - memcpy(S_packet + 10, OWNER, 8); S_packet[17] = 'S'; - memcpy(S_packet + 18, OWNER, 8); S_packet[25] = 'S'; - sendto(insock, (char *)S_packet, sizeof(S_packet), 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); - C_COUNTER ++; - S_ctrl_msg_time = tnow; - } - - // local RF user went away ? - if (dvap_busy) - { - time(&tnow); - if ((tnow - last_RF_time) > 1) - dvap_busy = false; - } - - // read from the dvap and process - reply = get_reply(dvp_buf, &len); - if (reply == RT_ERR) - { - traceit("Detected ERROR event from DVAP dongle, stopping...n"); - break; - } - else - if (reply == RT_STOP) - { - traceit("Detected STOP event from DVAP dongle, stopping...\n"); - break; - } - else if (reply == RT_START) - traceit("Detected START event from DVAP dongle\n"); - else - if (reply == RT_PTT) - { - ptt = (dvp_buf[4] == 0x01); - // traceit("Detected PTT=%s\n", ptt?"on":"off"); - } - else - if (reply == RT_STS) - { - space = dvp_buf[6]; - if (status_cntr < 3000) - status_cntr += 20; - } - else - if (reply == RT_HDR) - { - num_dv_frames = 0; - num_bit_errors = 0; - - traceit("From DVAP: flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s\n", - from_dvap_hdr->flag1, from_dvap_hdr->flag2, from_dvap_hdr->flag3, - from_dvap_hdr->mycall, from_dvap_hdr->sfx, from_dvap_hdr->urcall, - from_dvap_hdr->rpt2, from_dvap_hdr->rpt1); - - ok = true; - - /* Accept valid flags only */ - if (ok) - { - /* net flags */ - if ((from_dvap_hdr->flag1 != 0x00) && - (from_dvap_hdr->flag1 != 0x08) && - (from_dvap_hdr->flag1 != 0x20) && - (from_dvap_hdr->flag1 != 0x28) && - - /* rptr flags */ - (from_dvap_hdr->flag1 != 0x40) && - (from_dvap_hdr->flag1 != 0x48) && - (from_dvap_hdr->flag1 != 0x60) && - (from_dvap_hdr->flag1 != 0x68)) - ok = false; - } - - /* Reject those stupid STN stations */ - if (ok) - { - memcpy(temp_yrcall, from_dvap_hdr->urcall, CALL_SIZE); - temp_yrcall[CALL_SIZE] = '\0'; - temp_ptr = strstr(temp_yrcall, INVALID_YRCALL_KEY); - if (temp_ptr == temp_yrcall) // found it at first position - { - traceit("YRCALL value [%s] starts with the INVALID_YRCALL_KEY [%s], resetting to CQCQCQ\n", - temp_yrcall, INVALID_YRCALL_KEY); - memcpy(from_dvap_hdr->urcall, "CQCQCQ ", 8); - } - } - - /*** copy the dvap header ***/ - memcpy(net_buf.rf_audio.buff, dvp_buf + 6, 41); - - /* RPT1 must always be the repeater + module */ - memcpy(net_buf.rf_hdr.rpt1, RPTR_and_MOD, 8); - /* copy RPT2 */ - memcpy(net_buf.rf_hdr.rpt2, from_dvap_hdr->rpt1, 8); - - /* RPT2 must also be valid */ - if ((net_buf.rf_hdr.rpt2[7] == 'A') || - (net_buf.rf_hdr.rpt2[7] == 'B') || - (net_buf.rf_hdr.rpt2[7] == 'C') || - (net_buf.rf_hdr.rpt2[7] == 'G')) - memcpy(net_buf.rf_hdr.rpt2, RPTR, 7); - else - memset(net_buf.rf_hdr.rpt2, ' ', 8); - - if ((memcmp(net_buf.rf_hdr.urcall, "CQCQCQ", 6) != 0) && (net_buf.rf_hdr.rpt2[0] != ' ')) - memcpy(net_buf.rf_hdr.rpt2, RPTR_and_G, 8); - - /* 8th in rpt1, rpt2 must be diff */ - if (net_buf.rf_hdr.rpt2[7] == net_buf.rf_hdr.rpt1[7]) - memset(net_buf.rf_hdr.rpt2, ' ', 8); - - /* - Are we restricting the RF user ? - If RPTR is OWNER, then any RF user can talk. - If RPTR is not OWNER, - that means that mycall, rpt1, rpt2 must be equal to RPTR - otherwise we drop the rf data - */ - if (memcmp(RPTR, OWNER, RPTR_SIZE) != 0) - { - if (memcmp(net_buf.rf_hdr.mycall, RPTR, RPTR_SIZE) != 0) - { - traceit("mycall=[%.8s], not equal to %s\n", net_buf.rf_hdr.mycall, RPTR); - ok = false; - } - } - else - if (memcmp(net_buf.rf_hdr.mycall, " ", 8) == 0) - { - traceit("Invalid value for mycall=[%.8s]\n", net_buf.rf_hdr.mycall); - ok = false; - } - - if (ok) - { - for (i = 0; i < 8; i++) - { - if (!isupper(net_buf.rf_hdr.mycall[i]) && - !isdigit(net_buf.rf_hdr.mycall[i]) && - (net_buf.rf_hdr.mycall[i] != ' ')) - { - memset(net_buf.rf_hdr.mycall, ' ', 8); - ok = false; - traceit("Invalid value for MYCALL\n"); - break; - } - } - - for (i = 0; i < 4; i++) - { - if (!isupper(net_buf.rf_hdr.sfx[i]) && - !isdigit(net_buf.rf_hdr.sfx[i]) && - (net_buf.rf_hdr.sfx[i] != ' ')) - { - memset(net_buf.rf_hdr.sfx, ' ', 4); - break; - } - } - - for (i = 0; i < 8; i++) - { - if (!isupper(net_buf.rf_hdr.urcall[i]) && - !isdigit(net_buf.rf_hdr.urcall[i]) && - (net_buf.rf_hdr.urcall[i] != ' ') && - (net_buf.rf_hdr.urcall[i] != '/')) - { - memcpy(net_buf.rf_hdr.urcall, "CQCQCQ ", 8); - break; - } - } - - /*** what if YRCALL is all spaces, we can NOT allow that ***/ - if (memcmp(net_buf.rf_hdr.urcall, " ", 8) == 0) - memcpy(net_buf.rf_hdr.urcall, "CQCQCQ ", 8); - - /* change the rptr flags to net flags */ - if (from_dvap_hdr->flag1 == 0x40) - net_buf.rf_hdr.flags[0] = 0x00; - else - if (from_dvap_hdr->flag1 == 0x48) - net_buf.rf_hdr.flags[0] = 0x08; - else - if (from_dvap_hdr->flag1 == 0x60) - net_buf.rf_hdr.flags[0] = 0x20; - else - if (from_dvap_hdr->flag1 == 0x68) - net_buf.rf_hdr.flags[0] = 0x28; - else - net_buf.rf_hdr.flags[0] = 0x00; - net_buf.rf_hdr.flags[1] = 0x00; - net_buf.rf_hdr.flags[2] = 0x00; - - /* for icom g2 */ - S_packet[5] = (unsigned char)(C_COUNTER & 0xff); - S_packet[4] = ((C_COUNTER >> 8) & 0xff); - memcpy(S_packet + 10, net_buf.rf_hdr.mycall, 8); - memcpy(S_packet + 18, OWNER, 8); S_packet[25] = RPTR_MOD; - sendto(insock, (char *)S_packet, sizeof(S_packet), 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); - C_COUNTER ++; - - /* - Before we send the data to the local gateway, - set RPT1, RPT2 to be the local gateway - */ - memcpy(net_buf.rf_hdr.rpt1, OWNER, 7); - if (net_buf.rf_hdr.rpt2[7] != ' ') - memcpy(net_buf.rf_hdr.rpt2, OWNER, 7); - - memcpy(net_buf.pkt_id, "DSTR", 4); - net_buf.nothing1[0] = ((C_COUNTER >> 8) & 0xff); - net_buf.nothing1[1] = (unsigned char)(C_COUNTER & 0xff); - net_buf.flags[0] = 0x73; - net_buf.flags[1] = 0x12; - net_buf.nothing2[0] = 0x00; - net_buf.nothing2[1] = 0x30; - net_buf.myicm.icm_id = 0x20; - net_buf.myicm.dst_rptr_id = 0x00; - net_buf.myicm.snd_rptr_id = 0x01; - net_buf.myicm.snd_term_id = SND_TERM_ID; - streamid_raw = (rand_r(&aseed) % 65535U) + 1U; - net_buf.myicm.streamid[0] = streamid_raw / 256U; - net_buf.myicm.streamid[1] = streamid_raw % 256U; - net_buf.myicm.ctrl = 0x80; sequence = 0x00; - calcPFCS((unsigned char *)&(net_buf.rf_hdr), net_buf.rf_hdr.pfcs); - sendto(insock, (char *)&net_buf, 58, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); - C_COUNTER ++; - - // local RF user keying up, start timer - dvap_busy = true; - time(&last_RF_time); - - // save mycall for the ack later - memcpy(mycall, from_dvap_hdr->mycall, 8); - - } - } - else - if (reply == RT_DAT) - { - /* have we already received a header ? */ - if (dvap_busy) - { - the_end = ((dvp_buf[4] & 0x40) == 0x40); - - net_buf.nothing1[0] = ((C_COUNTER >> 8) & 0xff); - net_buf.nothing1[1] = (unsigned char)(C_COUNTER & 0xff); - net_buf.nothing2[1] = 0x13; - net_buf.myicm.ctrl = sequence++; - if (the_end) - net_buf.myicm.ctrl = sequence | 0x40; - memcpy(net_buf.rf_audio.buff, dvp_buf + 6, 12); - sendto(insock, (char *)&net_buf, 29, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); - - ber_errs = dstar_dv_decode((unsigned char *)&net_buf + 17, ber_data); - if (ber_data[0] != 0xf85) - { - num_bit_errors += ber_errs; - num_dv_frames ++; - } - - C_COUNTER ++; - if (sequence > 0x14) - sequence = 0x00; - - // local RF user still talking, update timer - time(&last_RF_time); - if (the_end) - { - // local RF user stopped talking - dvap_busy = false; - traceit("End of dvap audio, ber=%.02f\n", - (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)) ); - - if (RPTR_ACK && !busy20000) - { - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - memcpy(dvap_ack_arg.mycall, mycall, 8); - dvap_ack_arg.ber = (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)); - rc = pthread_create(&rptr_ack_t, &attr, rptr_ack, (void *)&dvap_ack_arg); - if (rc != 0) - traceit("failed to start thread rptr_ack thread\n"); - pthread_attr_destroy(&attr); - } - } - } - } - usleep(1000); - status_cntr --; - if (status_cntr < 0) - break; - } - - /* stop dvap */ - (void)write_to_dvp(DVP_RQST_STOP, 5); - close(serfd); - - traceit("readFromRF thread exiting\n"); - - keep_running = false; - pthread_exit(NULL); + REPLY_TYPE reply; + unsigned int len = 0; + unsigned char dvp_buf[200]; + struct pkt net_buf; + time_t tnow = 0; + time_t S_ctrl_msg_time = 0; + unsigned char S_packet[26]; + unsigned short C_COUNTER = 0; + time_t last_RF_time = 0; + struct sigaction act; + bool dvap_busy = false; + // bool ptt = false; + bool the_end = true; + dvap_hdr *from_dvap_hdr = (dvap_hdr *)dvp_buf; + // dvap_voice *from_dvap_voice = (dvap_voice *)dvp_buf; + bool ok = true; + int i = 0; + u_int16_t streamid_raw = 0; + short int sequence = 0x00; + char mycall[8]; + pthread_t rptr_ack_t; + pthread_attr_t attr; + int rc = -1; + short int status_cntr = 3000; + char temp_yrcall[CALL_SIZE + 1]; + char *temp_ptr = NULL; + + num_dv_frames = 0; + num_bit_errors = 0; + + arg = arg; + act.sa_handler = sig_catch; + sigemptyset(&act.sa_mask); + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + keep_running = false; + traceit("thread readFromRF exiting\n"); + pthread_exit(NULL); + } + if (sigaction(SIGHUP, &act, 0) != 0) { + traceit("sigaction-HUP failed, error=%d\n", errno); + keep_running = false; + traceit("thread readFromRF exiting\n"); + pthread_exit(NULL); + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + keep_running = false; + traceit("thread readFromRF exiting\n"); + pthread_exit(NULL); + } + + /* prepare the S server status packet */ + memcpy(S_packet, "DSTR", 4); + S_packet[4] = 0x00; + S_packet[5] = 0x00; + S_packet[6] = 0x73; + S_packet[7] = 0x21; + S_packet[8] = 0x00; + S_packet[9] = 0x10; + + while (keep_running) { + time(&tnow); + + /* send the S packet if needed */ + if ((tnow - S_ctrl_msg_time) > 60) { + S_packet[5] = (unsigned char)(C_COUNTER & 0xff); + S_packet[4] = ((C_COUNTER >> 8) & 0xff); + memcpy(S_packet + 10, OWNER, 8); + S_packet[17] = 'S'; + memcpy(S_packet + 18, OWNER, 8); + S_packet[25] = 'S'; + sendto(insock, (char *)S_packet, sizeof(S_packet), 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); + C_COUNTER ++; + S_ctrl_msg_time = tnow; + } + + // local RF user went away ? + if (dvap_busy) { + time(&tnow); + if ((tnow - last_RF_time) > 1) + dvap_busy = false; + } + + // read from the dvap and process + reply = get_reply(dvp_buf, &len); + if (reply == RT_ERR) { + traceit("Detected ERROR event from DVAP dongle, stopping...n"); + break; + } else if (reply == RT_STOP) { + traceit("Detected STOP event from DVAP dongle, stopping...\n"); + break; + } else if (reply == RT_START) { + traceit("Detected START event from DVAP dongle\n"); + // else if (reply == RT_PTT) { + // ptt = (dvp_buf[4] == 0x01); + // traceit("Detected PTT=%s\n", ptt?"on":"off"); + } else if (reply == RT_STS) { + space = dvp_buf[6]; + if (status_cntr < 3000) + status_cntr += 20; + } else if (reply == RT_HDR) { + num_dv_frames = 0; + num_bit_errors = 0; + + traceit("From DVAP: flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s\n", + from_dvap_hdr->flag1, from_dvap_hdr->flag2, from_dvap_hdr->flag3, + from_dvap_hdr->mycall, from_dvap_hdr->sfx, from_dvap_hdr->urcall, + from_dvap_hdr->rpt2, from_dvap_hdr->rpt1); + + ok = true; + + /* Accept valid flags only */ + if (ok) { + /* net flags */ + if ((from_dvap_hdr->flag1 != 0x00) && + (from_dvap_hdr->flag1 != 0x08) && + (from_dvap_hdr->flag1 != 0x20) && + (from_dvap_hdr->flag1 != 0x28) && + + /* rptr flags */ + (from_dvap_hdr->flag1 != 0x40) && + (from_dvap_hdr->flag1 != 0x48) && + (from_dvap_hdr->flag1 != 0x60) && + (from_dvap_hdr->flag1 != 0x68)) + ok = false; + } + + /* Reject those stupid STN stations */ + if (ok) { + memcpy(temp_yrcall, from_dvap_hdr->urcall, CALL_SIZE); + temp_yrcall[CALL_SIZE] = '\0'; + temp_ptr = strstr(temp_yrcall, INVALID_YRCALL_KEY); + if (temp_ptr == temp_yrcall) { // found it at first position + traceit("YRCALL value [%s] starts with the INVALID_YRCALL_KEY [%s], resetting to CQCQCQ\n", + temp_yrcall, INVALID_YRCALL_KEY); + memcpy(from_dvap_hdr->urcall, "CQCQCQ ", 8); + } + } + + /*** copy the dvap header ***/ + memcpy(net_buf.rf_audio.buff, dvp_buf + 6, 41); + + /* RPT1 must always be the repeater + module */ + memcpy(net_buf.rf_hdr.rpt1, RPTR_and_MOD, 8); + /* copy RPT2 */ + memcpy(net_buf.rf_hdr.rpt2, from_dvap_hdr->rpt1, 8); + + /* RPT2 must also be valid */ + if ((net_buf.rf_hdr.rpt2[7] == 'A') || + (net_buf.rf_hdr.rpt2[7] == 'B') || + (net_buf.rf_hdr.rpt2[7] == 'C') || + (net_buf.rf_hdr.rpt2[7] == 'G')) + memcpy(net_buf.rf_hdr.rpt2, RPTR, 7); + else + memset(net_buf.rf_hdr.rpt2, ' ', 8); + + if ((memcmp(net_buf.rf_hdr.urcall, "CQCQCQ", 6) != 0) && (net_buf.rf_hdr.rpt2[0] != ' ')) + memcpy(net_buf.rf_hdr.rpt2, RPTR_and_G, 8); + + /* 8th in rpt1, rpt2 must be diff */ + if (net_buf.rf_hdr.rpt2[7] == net_buf.rf_hdr.rpt1[7]) + memset(net_buf.rf_hdr.rpt2, ' ', 8); + + /* + Are we restricting the RF user ? + If RPTR is OWNER, then any RF user can talk. + If RPTR is not OWNER, + that means that mycall, rpt1, rpt2 must be equal to RPTR + otherwise we drop the rf data + */ + if (memcmp(RPTR, OWNER, RPTR_SIZE) != 0) { + if (memcmp(net_buf.rf_hdr.mycall, RPTR, RPTR_SIZE) != 0) { + traceit("mycall=[%.8s], not equal to %s\n", net_buf.rf_hdr.mycall, RPTR); + ok = false; + } + } else if (memcmp(net_buf.rf_hdr.mycall, " ", 8) == 0) { + traceit("Invalid value for mycall=[%.8s]\n", net_buf.rf_hdr.mycall); + ok = false; + } + + if (ok) { + for (i = 0; i < 8; i++) { + if (!isupper(net_buf.rf_hdr.mycall[i]) && + !isdigit(net_buf.rf_hdr.mycall[i]) && + (net_buf.rf_hdr.mycall[i] != ' ')) { + memset(net_buf.rf_hdr.mycall, ' ', 8); + ok = false; + traceit("Invalid value for MYCALL\n"); + break; + } + } + + for (i = 0; i < 4; i++) { + if (!isupper(net_buf.rf_hdr.sfx[i]) && + !isdigit(net_buf.rf_hdr.sfx[i]) && + (net_buf.rf_hdr.sfx[i] != ' ')) { + memset(net_buf.rf_hdr.sfx, ' ', 4); + break; + } + } + + for (i = 0; i < 8; i++) { + if (!isupper(net_buf.rf_hdr.urcall[i]) && + !isdigit(net_buf.rf_hdr.urcall[i]) && + (net_buf.rf_hdr.urcall[i] != ' ') && + (net_buf.rf_hdr.urcall[i] != '/')) { + memcpy(net_buf.rf_hdr.urcall, "CQCQCQ ", 8); + break; + } + } + + /*** what if YRCALL is all spaces, we can NOT allow that ***/ + if (memcmp(net_buf.rf_hdr.urcall, " ", 8) == 0) + memcpy(net_buf.rf_hdr.urcall, "CQCQCQ ", 8); + + /* change the rptr flags to net flags */ + if (from_dvap_hdr->flag1 == 0x40) + net_buf.rf_hdr.flags[0] = 0x00; + else if (from_dvap_hdr->flag1 == 0x48) + net_buf.rf_hdr.flags[0] = 0x08; + else if (from_dvap_hdr->flag1 == 0x60) + net_buf.rf_hdr.flags[0] = 0x20; + else if (from_dvap_hdr->flag1 == 0x68) + net_buf.rf_hdr.flags[0] = 0x28; + else + net_buf.rf_hdr.flags[0] = 0x00; + net_buf.rf_hdr.flags[1] = 0x00; + net_buf.rf_hdr.flags[2] = 0x00; + + /* for icom g2 */ + S_packet[5] = (unsigned char)(C_COUNTER & 0xff); + S_packet[4] = ((C_COUNTER >> 8) & 0xff); + memcpy(S_packet + 10, net_buf.rf_hdr.mycall, 8); + memcpy(S_packet + 18, OWNER, 8); + S_packet[25] = RPTR_MOD; + sendto(insock, (char *)S_packet, sizeof(S_packet), 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); + C_COUNTER ++; + + /* + Before we send the data to the local gateway, + set RPT1, RPT2 to be the local gateway + */ + memcpy(net_buf.rf_hdr.rpt1, OWNER, 7); + if (net_buf.rf_hdr.rpt2[7] != ' ') + memcpy(net_buf.rf_hdr.rpt2, OWNER, 7); + + memcpy(net_buf.pkt_id, "DSTR", 4); + net_buf.nothing1[0] = ((C_COUNTER >> 8) & 0xff); + net_buf.nothing1[1] = (unsigned char)(C_COUNTER & 0xff); + net_buf.flags[0] = 0x73; + net_buf.flags[1] = 0x12; + net_buf.nothing2[0] = 0x00; + net_buf.nothing2[1] = 0x30; + net_buf.myicm.icm_id = 0x20; + net_buf.myicm.dst_rptr_id = 0x00; + net_buf.myicm.snd_rptr_id = 0x01; + net_buf.myicm.snd_term_id = SND_TERM_ID; + streamid_raw = (rand_r(&aseed) % 65535U) + 1U; + net_buf.myicm.streamid[0] = streamid_raw / 256U; + net_buf.myicm.streamid[1] = streamid_raw % 256U; + net_buf.myicm.ctrl = 0x80; + sequence = 0x00; + calcPFCS((unsigned char *)&(net_buf.rf_hdr), net_buf.rf_hdr.pfcs); + sendto(insock, (char *)&net_buf, 58, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); + C_COUNTER ++; + + // local RF user keying up, start timer + dvap_busy = true; + time(&last_RF_time); + + // save mycall for the ack later + memcpy(mycall, from_dvap_hdr->mycall, 8); + + } + } else if (reply == RT_DAT) { + /* have we already received a header ? */ + if (dvap_busy) { + the_end = ((dvp_buf[4] & 0x40) == 0x40); + + net_buf.nothing1[0] = ((C_COUNTER >> 8) & 0xff); + net_buf.nothing1[1] = (unsigned char)(C_COUNTER & 0xff); + net_buf.nothing2[1] = 0x13; + net_buf.myicm.ctrl = sequence++; + if (the_end) + net_buf.myicm.ctrl = sequence | 0x40; + memcpy(net_buf.rf_audio.buff, dvp_buf + 6, 12); + sendto(insock, (char *)&net_buf, 29, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); + + ber_errs = dstar_dv_decode((unsigned char *)&net_buf + 17, ber_data); + if (ber_data[0] != 0xf85) { + num_bit_errors += ber_errs; + num_dv_frames ++; + } + + C_COUNTER ++; + if (sequence > 0x14) + sequence = 0x00; + + // local RF user still talking, update timer + time(&last_RF_time); + if (the_end) { + // local RF user stopped talking + dvap_busy = false; + traceit("End of dvap audio, ber=%.02f\n", + (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)) ); + + if (RPTR_ACK && !busy20000) { + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + memcpy(dvap_ack_arg.mycall, mycall, 8); + dvap_ack_arg.ber = (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)); + rc = pthread_create(&rptr_ack_t, &attr, rptr_ack, (void *)&dvap_ack_arg); + if (rc != 0) + traceit("failed to start thread rptr_ack thread\n"); + pthread_attr_destroy(&attr); + } + } + } + } + usleep(1000); + status_cntr --; + if (status_cntr < 0) + break; + } + + /* stop dvap */ + (void)write_to_dvp(DVP_RQST_STOP, 5); + close(serfd); + + traceit("readFromRF thread exiting\n"); + + keep_running = false; + pthread_exit(NULL); } diff --git a/dvrptr.cpp b/dvrptr.cpp index 6eebf51..e24622d 100644 --- a/dvrptr.cpp +++ b/dvrptr.cpp @@ -1,7 +1,7 @@ -/* +/* * DVRPTR Repeater for Linux * Autor: DG1HT DH2YBE KI4LKF - * + * --------------------------------------------------------------------------------------------------------*/ #include #include @@ -42,8 +42,8 @@ short old_seq_no = 0; short seq_no1 = 1; short seq_no2 = 1; short seq_no3 = 0; -int fd_ser = -1; -bool busy20000 = false; +int fd_ser = -1; +bool busy20000 = false; static unsigned char S_packet[26]; static time_t S_ctrl_msg_time = 0; @@ -51,8 +51,8 @@ static int rqst_count = 6; static const int TRACE_BFSZ = 200; static char trace_buf[TRACE_BFSZ]; static unsigned streamid[2] = {0x00, 0x00}; -static unsigned char start_Header[8]={0xD0,0x03,0x00,0x16,0x01,0x00,0x00,0x00}; -static unsigned char ptt_off[8]={0xD0,0x03,0x00,0x1A,0x01,0xff,0x00,0x00}; +static unsigned char start_Header[8]= {0xD0,0x03,0x00,0x16,0x01,0x00,0x00,0x00}; +static unsigned char ptt_off[8]= {0xD0,0x03,0x00,0x1A,0x01,0xff,0x00,0x00}; static int insock = -1; static int read_config(const char *cfgFile); @@ -72,12 +72,12 @@ static unsigned char writevoice[24]; static unsigned char writevoice1[24]; // Modem INIT -static unsigned char Modem_Init0[6]={0xD0,0x01,0x00,0x11,0x00,0x00}; -static unsigned char Modem_Init1[7]={0xD0,0x02,0x00,0x10,0x03,0x00,0x00}; // RX TX Enable -static unsigned char Modem_Init2[12]={0xD0,0x07,0x00,0x14,0xC0,0x04,0x00,0x57,0x53,0x00,0x00,0x00}; // Modem Init -static unsigned char Modem_STATUS[6]={0xD0,0x01,0x00,0x10,0x00,0x00}; // Status Abfragr -static unsigned char Modem_SERIAL[6]={0xD0,0x01,0x00,0x12,0x00,0x00}; - +static unsigned char Modem_Init0[6]= {0xD0,0x01,0x00,0x11,0x00,0x00}; +static unsigned char Modem_Init1[7]= {0xD0,0x02,0x00,0x10,0x03,0x00,0x00}; // RX TX Enable +static unsigned char Modem_Init2[12]= {0xD0,0x07,0x00,0x14,0xC0,0x04,0x00,0x57,0x53,0x00,0x00,0x00}; // Modem Init +static unsigned char Modem_STATUS[6]= {0xD0,0x01,0x00,0x10,0x00,0x00}; // Status Abfragr +static unsigned char Modem_SERIAL[6]= {0xD0,0x01,0x00,0x12,0x00,0x00}; + static char DVRPTR_SERIAL[16]; static char DVCALL[RPTR_SIZE + 1] = {"ABCDEF"}; static char RPTR[RPTR_SIZE + 1] = {"ABCDEF"}; @@ -114,1102 +114,1094 @@ static char INVALID_YRCALL_KEY[CALL_SIZE + 1] = { "" }; char Ergebnis[250]; -struct hdr -{ - unsigned char flags[3]; - unsigned char rpt2[8]; - unsigned char rpt1[8]; - unsigned char urcall[8]; - unsigned char mycall[8]; - unsigned char sfx[4]; - unsigned char pfcs[2]; +struct hdr { + unsigned char flags[3]; + unsigned char rpt2[8]; + unsigned char rpt1[8]; + unsigned char urcall[8]; + unsigned char mycall[8]; + unsigned char sfx[4]; + unsigned char pfcs[2]; }; -struct icm -{ - unsigned char icm_id; - unsigned char dst_rptr_id; - unsigned char snd_rptr_id; - unsigned char snd_term_id; - unsigned char streamid[2]; - unsigned char ctrl; +struct icm { + unsigned char icm_id; + unsigned char dst_rptr_id; + unsigned char snd_rptr_id; + unsigned char snd_term_id; + unsigned char streamid[2]; + unsigned char ctrl; }; -struct voice_and_text -{ - unsigned char voice[8]; - unsigned char text[2]; +struct voice_and_text { + unsigned char voice[8]; + unsigned char text[2]; }; -struct nettext -{ - unsigned char net_text[20]; +struct nettext { + unsigned char net_text[20]; }; -struct audio -{ - unsigned char buff[sizeof(struct hdr)]; +struct audio { + unsigned char buff[sizeof(struct hdr)]; }; -struct pkt -{ - unsigned char pkt_id[4]; - unsigned char nothing1[2]; - unsigned char flags[2]; - unsigned char nothing2[2]; - struct icm myicm; - union - { - struct audio rf_audio; - struct hdr rf_hdr; - struct nettext net_text; - struct voice_and_text vat; - }; +struct pkt { + unsigned char pkt_id[4]; + unsigned char nothing1[2]; + unsigned char flags[2]; + unsigned char nothing2[2]; + struct icm myicm; + union { + struct audio rf_audio; + struct hdr rf_hdr; + struct nettext net_text; + struct voice_and_text vat; + }; }; static struct pkt recv_buf; typedef unsigned int U32; //! 32-bit union. -typedef union -{ - U32 u32 ; - unsigned short u16[2]; - unsigned char u8[4]; +typedef union { + U32 u32 ; + unsigned short u16[2]; + unsigned char u8[4]; } Union32; static const U32 ENCODING_TABLE_23127[] = { - 0x000000U, 0x0018EAU, 0x00293EU, 0x0031D4U, 0x004A96U, 0x00527CU, 0x0063A8U, 0x007B42U, 0x008DC6U, 0x00952CU, - 0x00A4F8U, 0x00BC12U, 0x00C750U, 0x00DFBAU, 0x00EE6EU, 0x00F684U, 0x010366U, 0x011B8CU, 0x012A58U, 0x0132B2U, - 0x0149F0U, 0x01511AU, 0x0160CEU, 0x017824U, 0x018EA0U, 0x01964AU, 0x01A79EU, 0x01BF74U, 0x01C436U, 0x01DCDCU, - 0x01ED08U, 0x01F5E2U, 0x0206CCU, 0x021E26U, 0x022FF2U, 0x023718U, 0x024C5AU, 0x0254B0U, 0x026564U, 0x027D8EU, - 0x028B0AU, 0x0293E0U, 0x02A234U, 0x02BADEU, 0x02C19CU, 0x02D976U, 0x02E8A2U, 0x02F048U, 0x0305AAU, 0x031D40U, - 0x032C94U, 0x03347EU, 0x034F3CU, 0x0357D6U, 0x036602U, 0x037EE8U, 0x03886CU, 0x039086U, 0x03A152U, 0x03B9B8U, - 0x03C2FAU, 0x03DA10U, 0x03EBC4U, 0x03F32EU, 0x040D98U, 0x041572U, 0x0424A6U, 0x043C4CU, 0x04470EU, 0x045FE4U, - 0x046E30U, 0x0476DAU, 0x04805EU, 0x0498B4U, 0x04A960U, 0x04B18AU, 0x04CAC8U, 0x04D222U, 0x04E3F6U, 0x04FB1CU, - 0x050EFEU, 0x051614U, 0x0527C0U, 0x053F2AU, 0x054468U, 0x055C82U, 0x056D56U, 0x0575BCU, 0x058338U, 0x059BD2U, - 0x05AA06U, 0x05B2ECU, 0x05C9AEU, 0x05D144U, 0x05E090U, 0x05F87AU, 0x060B54U, 0x0613BEU, 0x06226AU, 0x063A80U, - 0x0641C2U, 0x065928U, 0x0668FCU, 0x067016U, 0x068692U, 0x069E78U, 0x06AFACU, 0x06B746U, 0x06CC04U, 0x06D4EEU, - 0x06E53AU, 0x06FDD0U, 0x070832U, 0x0710D8U, 0x07210CU, 0x0739E6U, 0x0742A4U, 0x075A4EU, 0x076B9AU, 0x077370U, - 0x0785F4U, 0x079D1EU, 0x07ACCAU, 0x07B420U, 0x07CF62U, 0x07D788U, 0x07E65CU, 0x07FEB6U, 0x0803DAU, 0x081B30U, - 0x082AE4U, 0x08320EU, 0x08494CU, 0x0851A6U, 0x086072U, 0x087898U, 0x088E1CU, 0x0896F6U, 0x08A722U, 0x08BFC8U, - 0x08C48AU, 0x08DC60U, 0x08EDB4U, 0x08F55EU, 0x0900BCU, 0x091856U, 0x092982U, 0x093168U, 0x094A2AU, 0x0952C0U, - 0x096314U, 0x097BFEU, 0x098D7AU, 0x099590U, 0x09A444U, 0x09BCAEU, 0x09C7ECU, 0x09DF06U, 0x09EED2U, 0x09F638U, - 0x0A0516U, 0x0A1DFCU, 0x0A2C28U, 0x0A34C2U, 0x0A4F80U, 0x0A576AU, 0x0A66BEU, 0x0A7E54U, 0x0A88D0U, 0x0A903AU, - 0x0AA1EEU, 0x0AB904U, 0x0AC246U, 0x0ADAACU, 0x0AEB78U, 0x0AF392U, 0x0B0670U, 0x0B1E9AU, 0x0B2F4EU, 0x0B37A4U, - 0x0B4CE6U, 0x0B540CU, 0x0B65D8U, 0x0B7D32U, 0x0B8BB6U, 0x0B935CU, 0x0BA288U, 0x0BBA62U, 0x0BC120U, 0x0BD9CAU, - 0x0BE81EU, 0x0BF0F4U, 0x0C0E42U, 0x0C16A8U, 0x0C277CU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3EU, 0x0C6DEAU, 0x0C7500U, - 0x0C8384U, 0x0C9B6EU, 0x0CAABAU, 0x0CB250U, 0x0CC912U, 0x0CD1F8U, 0x0CE02CU, 0x0CF8C6U, 0x0D0D24U, 0x0D15CEU, - 0x0D241AU, 0x0D3CF0U, 0x0D47B2U, 0x0D5F58U, 0x0D6E8CU, 0x0D7666U, 0x0D80E2U, 0x0D9808U, 0x0DA9DCU, 0x0DB136U, - 0x0DCA74U, 0x0DD29EU, 0x0DE34AU, 0x0DFBA0U, 0x0E088EU, 0x0E1064U, 0x0E21B0U, 0x0E395AU, 0x0E4218U, 0x0E5AF2U, - 0x0E6B26U, 0x0E73CCU, 0x0E8548U, 0x0E9DA2U, 0x0EAC76U, 0x0EB49CU, 0x0ECFDEU, 0x0ED734U, 0x0EE6E0U, 0x0EFE0AU, - 0x0F0BE8U, 0x0F1302U, 0x0F22D6U, 0x0F3A3CU, 0x0F417EU, 0x0F5994U, 0x0F6840U, 0x0F70AAU, 0x0F862EU, 0x0F9EC4U, - 0x0FAF10U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD452U, 0x0FE586U, 0x0FFD6CU, 0x1007B4U, 0x101F5EU, 0x102E8AU, 0x103660U, - 0x104D22U, 0x1055C8U, 0x10641CU, 0x107CF6U, 0x108A72U, 0x109298U, 0x10A34CU, 0x10BBA6U, 0x10C0E4U, 0x10D80EU, - 0x10E9DAU, 0x10F130U, 0x1104D2U, 0x111C38U, 0x112DECU, 0x113506U, 0x114E44U, 0x1156AEU, 0x11677AU, 0x117F90U, - 0x118914U, 0x1191FEU, 0x11A02AU, 0x11B8C0U, 0x11C382U, 0x11DB68U, 0x11EABCU, 0x11F256U, 0x120178U, 0x121992U, - 0x122846U, 0x1230ACU, 0x124BEEU, 0x125304U, 0x1262D0U, 0x127A3AU, 0x128CBEU, 0x129454U, 0x12A580U, 0x12BD6AU, - 0x12C628U, 0x12DEC2U, 0x12EF16U, 0x12F7FCU, 0x13021EU, 0x131AF4U, 0x132B20U, 0x1333CAU, 0x134888U, 0x135062U, - 0x1361B6U, 0x13795CU, 0x138FD8U, 0x139732U, 0x13A6E6U, 0x13BE0CU, 0x13C54EU, 0x13DDA4U, 0x13EC70U, 0x13F49AU, - 0x140A2CU, 0x1412C6U, 0x142312U, 0x143BF8U, 0x1440BAU, 0x145850U, 0x146984U, 0x14716EU, 0x1487EAU, 0x149F00U, - 0x14AED4U, 0x14B63EU, 0x14CD7CU, 0x14D596U, 0x14E442U, 0x14FCA8U, 0x15094AU, 0x1511A0U, 0x152074U, 0x15389EU, - 0x1543DCU, 0x155B36U, 0x156AE2U, 0x157208U, 0x15848CU, 0x159C66U, 0x15ADB2U, 0x15B558U, 0x15CE1AU, 0x15D6F0U, - 0x15E724U, 0x15FFCEU, 0x160CE0U, 0x16140AU, 0x1625DEU, 0x163D34U, 0x164676U, 0x165E9CU, 0x166F48U, 0x1677A2U, - 0x168126U, 0x1699CCU, 0x16A818U, 0x16B0F2U, 0x16CBB0U, 0x16D35AU, 0x16E28EU, 0x16FA64U, 0x170F86U, 0x17176CU, - 0x1726B8U, 0x173E52U, 0x174510U, 0x175DFAU, 0x176C2EU, 0x1774C4U, 0x178240U, 0x179AAAU, 0x17AB7EU, 0x17B394U, - 0x17C8D6U, 0x17D03CU, 0x17E1E8U, 0x17F902U, 0x18046EU, 0x181C84U, 0x182D50U, 0x1835BAU, 0x184EF8U, 0x185612U, - 0x1867C6U, 0x187F2CU, 0x1889A8U, 0x189142U, 0x18A096U, 0x18B87CU, 0x18C33EU, 0x18DBD4U, 0x18EA00U, 0x18F2EAU, - 0x190708U, 0x191FE2U, 0x192E36U, 0x1936DCU, 0x194D9EU, 0x195574U, 0x1964A0U, 0x197C4AU, 0x198ACEU, 0x199224U, - 0x19A3F0U, 0x19BB1AU, 0x19C058U, 0x19D8B2U, 0x19E966U, 0x19F18CU, 0x1A02A2U, 0x1A1A48U, 0x1A2B9CU, 0x1A3376U, - 0x1A4834U, 0x1A50DEU, 0x1A610AU, 0x1A79E0U, 0x1A8F64U, 0x1A978EU, 0x1AA65AU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD18U, - 0x1AECCCU, 0x1AF426U, 0x1B01C4U, 0x1B192EU, 0x1B28FAU, 0x1B3010U, 0x1B4B52U, 0x1B53B8U, 0x1B626CU, 0x1B7A86U, - 0x1B8C02U, 0x1B94E8U, 0x1BA53CU, 0x1BBDD6U, 0x1BC694U, 0x1BDE7EU, 0x1BEFAAU, 0x1BF740U, 0x1C09F6U, 0x1C111CU, - 0x1C20C8U, 0x1C3822U, 0x1C4360U, 0x1C5B8AU, 0x1C6A5EU, 0x1C72B4U, 0x1C8430U, 0x1C9CDAU, 0x1CAD0EU, 0x1CB5E4U, - 0x1CCEA6U, 0x1CD64CU, 0x1CE798U, 0x1CFF72U, 0x1D0A90U, 0x1D127AU, 0x1D23AEU, 0x1D3B44U, 0x1D4006U, 0x1D58ECU, - 0x1D6938U, 0x1D71D2U, 0x1D8756U, 0x1D9FBCU, 0x1DAE68U, 0x1DB682U, 0x1DCDC0U, 0x1DD52AU, 0x1DE4FEU, 0x1DFC14U, - 0x1E0F3AU, 0x1E17D0U, 0x1E2604U, 0x1E3EEEU, 0x1E45ACU, 0x1E5D46U, 0x1E6C92U, 0x1E7478U, 0x1E82FCU, 0x1E9A16U, - 0x1EABC2U, 0x1EB328U, 0x1EC86AU, 0x1ED080U, 0x1EE154U, 0x1EF9BEU, 0x1F0C5CU, 0x1F14B6U, 0x1F2562U, 0x1F3D88U, - 0x1F46CAU, 0x1F5E20U, 0x1F6FF4U, 0x1F771EU, 0x1F819AU, 0x1F9970U, 0x1FA8A4U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E6U, - 0x1FE232U, 0x1FFAD8U, 0x200F68U, 0x201782U, 0x202656U, 0x203EBCU, 0x2045FEU, 0x205D14U, 0x206CC0U, 0x20742AU, - 0x2082AEU, 0x209A44U, 0x20AB90U, 0x20B37AU, 0x20C838U, 0x20D0D2U, 0x20E106U, 0x20F9ECU, 0x210C0EU, 0x2114E4U, - 0x212530U, 0x213DDAU, 0x214698U, 0x215E72U, 0x216FA6U, 0x21774CU, 0x2181C8U, 0x219922U, 0x21A8F6U, 0x21B01CU, - 0x21CB5EU, 0x21D3B4U, 0x21E260U, 0x21FA8AU, 0x2209A4U, 0x22114EU, 0x22209AU, 0x223870U, 0x224332U, 0x225BD8U, - 0x226A0CU, 0x2272E6U, 0x228462U, 0x229C88U, 0x22AD5CU, 0x22B5B6U, 0x22CEF4U, 0x22D61EU, 0x22E7CAU, 0x22FF20U, - 0x230AC2U, 0x231228U, 0x2323FCU, 0x233B16U, 0x234054U, 0x2358BEU, 0x23696AU, 0x237180U, 0x238704U, 0x239FEEU, - 0x23AE3AU, 0x23B6D0U, 0x23CD92U, 0x23D578U, 0x23E4ACU, 0x23FC46U, 0x2402F0U, 0x241A1AU, 0x242BCEU, 0x243324U, - 0x244866U, 0x24508CU, 0x246158U, 0x2479B2U, 0x248F36U, 0x2497DCU, 0x24A608U, 0x24BEE2U, 0x24C5A0U, 0x24DD4AU, - 0x24EC9EU, 0x24F474U, 0x250196U, 0x25197CU, 0x2528A8U, 0x253042U, 0x254B00U, 0x2553EAU, 0x25623EU, 0x257AD4U, - 0x258C50U, 0x2594BAU, 0x25A56EU, 0x25BD84U, 0x25C6C6U, 0x25DE2CU, 0x25EFF8U, 0x25F712U, 0x26043CU, 0x261CD6U, - 0x262D02U, 0x2635E8U, 0x264EAAU, 0x265640U, 0x266794U, 0x267F7EU, 0x2689FAU, 0x269110U, 0x26A0C4U, 0x26B82EU, - 0x26C36CU, 0x26DB86U, 0x26EA52U, 0x26F2B8U, 0x27075AU, 0x271FB0U, 0x272E64U, 0x27368EU, 0x274DCCU, 0x275526U, - 0x2764F2U, 0x277C18U, 0x278A9CU, 0x279276U, 0x27A3A2U, 0x27BB48U, 0x27C00AU, 0x27D8E0U, 0x27E934U, 0x27F1DEU, - 0x280CB2U, 0x281458U, 0x28258CU, 0x283D66U, 0x284624U, 0x285ECEU, 0x286F1AU, 0x2877F0U, 0x288174U, 0x28999EU, - 0x28A84AU, 0x28B0A0U, 0x28CBE2U, 0x28D308U, 0x28E2DCU, 0x28FA36U, 0x290FD4U, 0x29173EU, 0x2926EAU, 0x293E00U, - 0x294542U, 0x295DA8U, 0x296C7CU, 0x297496U, 0x298212U, 0x299AF8U, 0x29AB2CU, 0x29B3C6U, 0x29C884U, 0x29D06EU, - 0x29E1BAU, 0x29F950U, 0x2A0A7EU, 0x2A1294U, 0x2A2340U, 0x2A3BAAU, 0x2A40E8U, 0x2A5802U, 0x2A69D6U, 0x2A713CU, - 0x2A87B8U, 0x2A9F52U, 0x2AAE86U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C4U, 0x2AE410U, 0x2AFCFAU, 0x2B0918U, 0x2B11F2U, - 0x2B2026U, 0x2B38CCU, 0x2B438EU, 0x2B5B64U, 0x2B6AB0U, 0x2B725AU, 0x2B84DEU, 0x2B9C34U, 0x2BADE0U, 0x2BB50AU, - 0x2BCE48U, 0x2BD6A2U, 0x2BE776U, 0x2BFF9CU, 0x2C012AU, 0x2C19C0U, 0x2C2814U, 0x2C30FEU, 0x2C4BBCU, 0x2C5356U, - 0x2C6282U, 0x2C7A68U, 0x2C8CECU, 0x2C9406U, 0x2CA5D2U, 0x2CBD38U, 0x2CC67AU, 0x2CDE90U, 0x2CEF44U, 0x2CF7AEU, - 0x2D024CU, 0x2D1AA6U, 0x2D2B72U, 0x2D3398U, 0x2D48DAU, 0x2D5030U, 0x2D61E4U, 0x2D790EU, 0x2D8F8AU, 0x2D9760U, - 0x2DA6B4U, 0x2DBE5EU, 0x2DC51CU, 0x2DDDF6U, 0x2DEC22U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0CU, 0x2E2ED8U, 0x2E3632U, - 0x2E4D70U, 0x2E559AU, 0x2E644EU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CAU, 0x2EA31EU, 0x2EBBF4U, 0x2EC0B6U, 0x2ED85CU, - 0x2EE988U, 0x2EF162U, 0x2F0480U, 0x2F1C6AU, 0x2F2DBEU, 0x2F3554U, 0x2F4E16U, 0x2F56FCU, 0x2F6728U, 0x2F7FC2U, - 0x2F8946U, 0x2F91ACU, 0x2FA078U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3AU, 0x2FEAEEU, 0x2FF204U, 0x3008DCU, 0x301036U, - 0x3021E2U, 0x303908U, 0x30424AU, 0x305AA0U, 0x306B74U, 0x30739EU, 0x30851AU, 0x309DF0U, 0x30AC24U, 0x30B4CEU, - 0x30CF8CU, 0x30D766U, 0x30E6B2U, 0x30FE58U, 0x310BBAU, 0x311350U, 0x312284U, 0x313A6EU, 0x31412CU, 0x3159C6U, - 0x316812U, 0x3170F8U, 0x31867CU, 0x319E96U, 0x31AF42U, 0x31B7A8U, 0x31CCEAU, 0x31D400U, 0x31E5D4U, 0x31FD3EU, - 0x320E10U, 0x3216FAU, 0x32272EU, 0x323FC4U, 0x324486U, 0x325C6CU, 0x326DB8U, 0x327552U, 0x3283D6U, 0x329B3CU, - 0x32AAE8U, 0x32B202U, 0x32C940U, 0x32D1AAU, 0x32E07EU, 0x32F894U, 0x330D76U, 0x33159CU, 0x332448U, 0x333CA2U, - 0x3347E0U, 0x335F0AU, 0x336EDEU, 0x337634U, 0x3380B0U, 0x33985AU, 0x33A98EU, 0x33B164U, 0x33CA26U, 0x33D2CCU, - 0x33E318U, 0x33FBF2U, 0x340544U, 0x341DAEU, 0x342C7AU, 0x343490U, 0x344FD2U, 0x345738U, 0x3466ECU, 0x347E06U, - 0x348882U, 0x349068U, 0x34A1BCU, 0x34B956U, 0x34C214U, 0x34DAFEU, 0x34EB2AU, 0x34F3C0U, 0x350622U, 0x351EC8U, - 0x352F1CU, 0x3537F6U, 0x354CB4U, 0x35545EU, 0x35658AU, 0x357D60U, 0x358BE4U, 0x35930EU, 0x35A2DAU, 0x35BA30U, - 0x35C172U, 0x35D998U, 0x35E84CU, 0x35F0A6U, 0x360388U, 0x361B62U, 0x362AB6U, 0x36325CU, 0x36491EU, 0x3651F4U, - 0x366020U, 0x3678CAU, 0x368E4EU, 0x3696A4U, 0x36A770U, 0x36BF9AU, 0x36C4D8U, 0x36DC32U, 0x36EDE6U, 0x36F50CU, - 0x3700EEU, 0x371804U, 0x3729D0U, 0x37313AU, 0x374A78U, 0x375292U, 0x376346U, 0x377BACU, 0x378D28U, 0x3795C2U, - 0x37A416U, 0x37BCFCU, 0x37C7BEU, 0x37DF54U, 0x37EE80U, 0x37F66AU, 0x380B06U, 0x3813ECU, 0x382238U, 0x383AD2U, - 0x384190U, 0x38597AU, 0x3868AEU, 0x387044U, 0x3886C0U, 0x389E2AU, 0x38AFFEU, 0x38B714U, 0x38CC56U, 0x38D4BCU, - 0x38E568U, 0x38FD82U, 0x390860U, 0x39108AU, 0x39215EU, 0x3939B4U, 0x3942F6U, 0x395A1CU, 0x396BC8U, 0x397322U, - 0x3985A6U, 0x399D4CU, 0x39AC98U, 0x39B472U, 0x39CF30U, 0x39D7DAU, 0x39E60EU, 0x39FEE4U, 0x3A0DCAU, 0x3A1520U, - 0x3A24F4U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB6U, 0x3A6E62U, 0x3A7688U, 0x3A800CU, 0x3A98E6U, 0x3AA932U, 0x3AB1D8U, - 0x3ACA9AU, 0x3AD270U, 0x3AE3A4U, 0x3AFB4EU, 0x3B0EACU, 0x3B1646U, 0x3B2792U, 0x3B3F78U, 0x3B443AU, 0x3B5CD0U, - 0x3B6D04U, 0x3B75EEU, 0x3B836AU, 0x3B9B80U, 0x3BAA54U, 0x3BB2BEU, 0x3BC9FCU, 0x3BD116U, 0x3BE0C2U, 0x3BF828U, - 0x3C069EU, 0x3C1E74U, 0x3C2FA0U, 0x3C374AU, 0x3C4C08U, 0x3C54E2U, 0x3C6536U, 0x3C7DDCU, 0x3C8B58U, 0x3C93B2U, - 0x3CA266U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD924U, 0x3CE8F0U, 0x3CF01AU, 0x3D05F8U, 0x3D1D12U, 0x3D2CC6U, 0x3D342CU, - 0x3D4F6EU, 0x3D5784U, 0x3D6650U, 0x3D7EBAU, 0x3D883EU, 0x3D90D4U, 0x3DA100U, 0x3DB9EAU, 0x3DC2A8U, 0x3DDA42U, - 0x3DEB96U, 0x3DF37CU, 0x3E0052U, 0x3E18B8U, 0x3E296CU, 0x3E3186U, 0x3E4AC4U, 0x3E522EU, 0x3E63FAU, 0x3E7B10U, - 0x3E8D94U, 0x3E957EU, 0x3EA4AAU, 0x3EBC40U, 0x3EC702U, 0x3EDFE8U, 0x3EEE3CU, 0x3EF6D6U, 0x3F0334U, 0x3F1BDEU, - 0x3F2A0AU, 0x3F32E0U, 0x3F49A2U, 0x3F5148U, 0x3F609CU, 0x3F7876U, 0x3F8EF2U, 0x3F9618U, 0x3FA7CCU, 0x3FBF26U, - 0x3FC464U, 0x3FDC8EU, 0x3FED5AU, 0x3FF5B0U, 0x40063AU, 0x401ED0U, 0x402F04U, 0x4037EEU, 0x404CACU, 0x405446U, - 0x406592U, 0x407D78U, 0x408BFCU, 0x409316U, 0x40A2C2U, 0x40BA28U, 0x40C16AU, 0x40D980U, 0x40E854U, 0x40F0BEU, - 0x41055CU, 0x411DB6U, 0x412C62U, 0x413488U, 0x414FCAU, 0x415720U, 0x4166F4U, 0x417E1EU, 0x41889AU, 0x419070U, - 0x41A1A4U, 0x41B94EU, 0x41C20CU, 0x41DAE6U, 0x41EB32U, 0x41F3D8U, 0x4200F6U, 0x42181CU, 0x4229C8U, 0x423122U, - 0x424A60U, 0x42528AU, 0x42635EU, 0x427BB4U, 0x428D30U, 0x4295DAU, 0x42A40EU, 0x42BCE4U, 0x42C7A6U, 0x42DF4CU, - 0x42EE98U, 0x42F672U, 0x430390U, 0x431B7AU, 0x432AAEU, 0x433244U, 0x434906U, 0x4351ECU, 0x436038U, 0x4378D2U, - 0x438E56U, 0x4396BCU, 0x43A768U, 0x43BF82U, 0x43C4C0U, 0x43DC2AU, 0x43EDFEU, 0x43F514U, 0x440BA2U, 0x441348U, - 0x44229CU, 0x443A76U, 0x444134U, 0x4459DEU, 0x44680AU, 0x4470E0U, 0x448664U, 0x449E8EU, 0x44AF5AU, 0x44B7B0U, - 0x44CCF2U, 0x44D418U, 0x44E5CCU, 0x44FD26U, 0x4508C4U, 0x45102EU, 0x4521FAU, 0x453910U, 0x454252U, 0x455AB8U, - 0x456B6CU, 0x457386U, 0x458502U, 0x459DE8U, 0x45AC3CU, 0x45B4D6U, 0x45CF94U, 0x45D77EU, 0x45E6AAU, 0x45FE40U, - 0x460D6EU, 0x461584U, 0x462450U, 0x463CBAU, 0x4647F8U, 0x465F12U, 0x466EC6U, 0x46762CU, 0x4680A8U, 0x469842U, - 0x46A996U, 0x46B17CU, 0x46CA3EU, 0x46D2D4U, 0x46E300U, 0x46FBEAU, 0x470E08U, 0x4716E2U, 0x472736U, 0x473FDCU, - 0x47449EU, 0x475C74U, 0x476DA0U, 0x47754AU, 0x4783CEU, 0x479B24U, 0x47AAF0U, 0x47B21AU, 0x47C958U, 0x47D1B2U, - 0x47E066U, 0x47F88CU, 0x4805E0U, 0x481D0AU, 0x482CDEU, 0x483434U, 0x484F76U, 0x48579CU, 0x486648U, 0x487EA2U, - 0x488826U, 0x4890CCU, 0x48A118U, 0x48B9F2U, 0x48C2B0U, 0x48DA5AU, 0x48EB8EU, 0x48F364U, 0x490686U, 0x491E6CU, - 0x492FB8U, 0x493752U, 0x494C10U, 0x4954FAU, 0x49652EU, 0x497DC4U, 0x498B40U, 0x4993AAU, 0x49A27EU, 0x49BA94U, - 0x49C1D6U, 0x49D93CU, 0x49E8E8U, 0x49F002U, 0x4A032CU, 0x4A1BC6U, 0x4A2A12U, 0x4A32F8U, 0x4A49BAU, 0x4A5150U, - 0x4A6084U, 0x4A786EU, 0x4A8EEAU, 0x4A9600U, 0x4AA7D4U, 0x4ABF3EU, 0x4AC47CU, 0x4ADC96U, 0x4AED42U, 0x4AF5A8U, - 0x4B004AU, 0x4B18A0U, 0x4B2974U, 0x4B319EU, 0x4B4ADCU, 0x4B5236U, 0x4B63E2U, 0x4B7B08U, 0x4B8D8CU, 0x4B9566U, - 0x4BA4B2U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF0U, 0x4BEE24U, 0x4BF6CEU, 0x4C0878U, 0x4C1092U, 0x4C2146U, 0x4C39ACU, - 0x4C42EEU, 0x4C5A04U, 0x4C6BD0U, 0x4C733AU, 0x4C85BEU, 0x4C9D54U, 0x4CAC80U, 0x4CB46AU, 0x4CCF28U, 0x4CD7C2U, - 0x4CE616U, 0x4CFEFCU, 0x4D0B1EU, 0x4D13F4U, 0x4D2220U, 0x4D3ACAU, 0x4D4188U, 0x4D5962U, 0x4D68B6U, 0x4D705CU, - 0x4D86D8U, 0x4D9E32U, 0x4DAFE6U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A4U, 0x4DE570U, 0x4DFD9AU, 0x4E0EB4U, 0x4E165EU, - 0x4E278AU, 0x4E3F60U, 0x4E4422U, 0x4E5CC8U, 0x4E6D1CU, 0x4E75F6U, 0x4E8372U, 0x4E9B98U, 0x4EAA4CU, 0x4EB2A6U, - 0x4EC9E4U, 0x4ED10EU, 0x4EE0DAU, 0x4EF830U, 0x4F0DD2U, 0x4F1538U, 0x4F24ECU, 0x4F3C06U, 0x4F4744U, 0x4F5FAEU, - 0x4F6E7AU, 0x4F7690U, 0x4F8014U, 0x4F98FEU, 0x4FA92AU, 0x4FB1C0U, 0x4FCA82U, 0x4FD268U, 0x4FE3BCU, 0x4FFB56U, - 0x50018EU, 0x501964U, 0x5028B0U, 0x50305AU, 0x504B18U, 0x5053F2U, 0x506226U, 0x507ACCU, 0x508C48U, 0x5094A2U, - 0x50A576U, 0x50BD9CU, 0x50C6DEU, 0x50DE34U, 0x50EFE0U, 0x50F70AU, 0x5102E8U, 0x511A02U, 0x512BD6U, 0x51333CU, - 0x51487EU, 0x515094U, 0x516140U, 0x5179AAU, 0x518F2EU, 0x5197C4U, 0x51A610U, 0x51BEFAU, 0x51C5B8U, 0x51DD52U, - 0x51EC86U, 0x51F46CU, 0x520742U, 0x521FA8U, 0x522E7CU, 0x523696U, 0x524DD4U, 0x52553EU, 0x5264EAU, 0x527C00U, - 0x528A84U, 0x52926EU, 0x52A3BAU, 0x52BB50U, 0x52C012U, 0x52D8F8U, 0x52E92CU, 0x52F1C6U, 0x530424U, 0x531CCEU, - 0x532D1AU, 0x5335F0U, 0x534EB2U, 0x535658U, 0x53678CU, 0x537F66U, 0x5389E2U, 0x539108U, 0x53A0DCU, 0x53B836U, - 0x53C374U, 0x53DB9EU, 0x53EA4AU, 0x53F2A0U, 0x540C16U, 0x5414FCU, 0x542528U, 0x543DC2U, 0x544680U, 0x545E6AU, - 0x546FBEU, 0x547754U, 0x5481D0U, 0x54993AU, 0x54A8EEU, 0x54B004U, 0x54CB46U, 0x54D3ACU, 0x54E278U, 0x54FA92U, - 0x550F70U, 0x55179AU, 0x55264EU, 0x553EA4U, 0x5545E6U, 0x555D0CU, 0x556CD8U, 0x557432U, 0x5582B6U, 0x559A5CU, - 0x55AB88U, 0x55B362U, 0x55C820U, 0x55D0CAU, 0x55E11EU, 0x55F9F4U, 0x560ADAU, 0x561230U, 0x5623E4U, 0x563B0EU, - 0x56404CU, 0x5658A6U, 0x566972U, 0x567198U, 0x56871CU, 0x569FF6U, 0x56AE22U, 0x56B6C8U, 0x56CD8AU, 0x56D560U, - 0x56E4B4U, 0x56FC5EU, 0x5709BCU, 0x571156U, 0x572082U, 0x573868U, 0x57432AU, 0x575BC0U, 0x576A14U, 0x5772FEU, - 0x57847AU, 0x579C90U, 0x57AD44U, 0x57B5AEU, 0x57CEECU, 0x57D606U, 0x57E7D2U, 0x57FF38U, 0x580254U, 0x581ABEU, - 0x582B6AU, 0x583380U, 0x5848C2U, 0x585028U, 0x5861FCU, 0x587916U, 0x588F92U, 0x589778U, 0x58A6ACU, 0x58BE46U, - 0x58C504U, 0x58DDEEU, 0x58EC3AU, 0x58F4D0U, 0x590132U, 0x5919D8U, 0x59280CU, 0x5930E6U, 0x594BA4U, 0x59534EU, - 0x59629AU, 0x597A70U, 0x598CF4U, 0x59941EU, 0x59A5CAU, 0x59BD20U, 0x59C662U, 0x59DE88U, 0x59EF5CU, 0x59F7B6U, - 0x5A0498U, 0x5A1C72U, 0x5A2DA6U, 0x5A354CU, 0x5A4E0EU, 0x5A56E4U, 0x5A6730U, 0x5A7FDAU, 0x5A895EU, 0x5A91B4U, - 0x5AA060U, 0x5AB88AU, 0x5AC3C8U, 0x5ADB22U, 0x5AEAF6U, 0x5AF21CU, 0x5B07FEU, 0x5B1F14U, 0x5B2EC0U, 0x5B362AU, - 0x5B4D68U, 0x5B5582U, 0x5B6456U, 0x5B7CBCU, 0x5B8A38U, 0x5B92D2U, 0x5BA306U, 0x5BBBECU, 0x5BC0AEU, 0x5BD844U, - 0x5BE990U, 0x5BF17AU, 0x5C0FCCU, 0x5C1726U, 0x5C26F2U, 0x5C3E18U, 0x5C455AU, 0x5C5DB0U, 0x5C6C64U, 0x5C748EU, - 0x5C820AU, 0x5C9AE0U, 0x5CAB34U, 0x5CB3DEU, 0x5CC89CU, 0x5CD076U, 0x5CE1A2U, 0x5CF948U, 0x5D0CAAU, 0x5D1440U, - 0x5D2594U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED6U, 0x5D6F02U, 0x5D77E8U, 0x5D816CU, 0x5D9986U, 0x5DA852U, 0x5DB0B8U, - 0x5DCBFAU, 0x5DD310U, 0x5DE2C4U, 0x5DFA2EU, 0x5E0900U, 0x5E11EAU, 0x5E203EU, 0x5E38D4U, 0x5E4396U, 0x5E5B7CU, - 0x5E6AA8U, 0x5E7242U, 0x5E84C6U, 0x5E9C2CU, 0x5EADF8U, 0x5EB512U, 0x5ECE50U, 0x5ED6BAU, 0x5EE76EU, 0x5EFF84U, - 0x5F0A66U, 0x5F128CU, 0x5F2358U, 0x5F3BB2U, 0x5F40F0U, 0x5F581AU, 0x5F69CEU, 0x5F7124U, 0x5F87A0U, 0x5F9F4AU, - 0x5FAE9EU, 0x5FB674U, 0x5FCD36U, 0x5FD5DCU, 0x5FE408U, 0x5FFCE2U, 0x600952U, 0x6011B8U, 0x60206CU, 0x603886U, - 0x6043C4U, 0x605B2EU, 0x606AFAU, 0x607210U, 0x608494U, 0x609C7EU, 0x60ADAAU, 0x60B540U, 0x60CE02U, 0x60D6E8U, - 0x60E73CU, 0x60FFD6U, 0x610A34U, 0x6112DEU, 0x61230AU, 0x613BE0U, 0x6140A2U, 0x615848U, 0x61699CU, 0x617176U, - 0x6187F2U, 0x619F18U, 0x61AECCU, 0x61B626U, 0x61CD64U, 0x61D58EU, 0x61E45AU, 0x61FCB0U, 0x620F9EU, 0x621774U, - 0x6226A0U, 0x623E4AU, 0x624508U, 0x625DE2U, 0x626C36U, 0x6274DCU, 0x628258U, 0x629AB2U, 0x62AB66U, 0x62B38CU, - 0x62C8CEU, 0x62D024U, 0x62E1F0U, 0x62F91AU, 0x630CF8U, 0x631412U, 0x6325C6U, 0x633D2CU, 0x63466EU, 0x635E84U, - 0x636F50U, 0x6377BAU, 0x63813EU, 0x6399D4U, 0x63A800U, 0x63B0EAU, 0x63CBA8U, 0x63D342U, 0x63E296U, 0x63FA7CU, - 0x6404CAU, 0x641C20U, 0x642DF4U, 0x64351EU, 0x644E5CU, 0x6456B6U, 0x646762U, 0x647F88U, 0x64890CU, 0x6491E6U, - 0x64A032U, 0x64B8D8U, 0x64C39AU, 0x64DB70U, 0x64EAA4U, 0x64F24EU, 0x6507ACU, 0x651F46U, 0x652E92U, 0x653678U, - 0x654D3AU, 0x6555D0U, 0x656404U, 0x657CEEU, 0x658A6AU, 0x659280U, 0x65A354U, 0x65BBBEU, 0x65C0FCU, 0x65D816U, - 0x65E9C2U, 0x65F128U, 0x660206U, 0x661AECU, 0x662B38U, 0x6633D2U, 0x664890U, 0x66507AU, 0x6661AEU, 0x667944U, - 0x668FC0U, 0x66972AU, 0x66A6FEU, 0x66BE14U, 0x66C556U, 0x66DDBCU, 0x66EC68U, 0x66F482U, 0x670160U, 0x67198AU, - 0x67285EU, 0x6730B4U, 0x674BF6U, 0x67531CU, 0x6762C8U, 0x677A22U, 0x678CA6U, 0x67944CU, 0x67A598U, 0x67BD72U, - 0x67C630U, 0x67DEDAU, 0x67EF0EU, 0x67F7E4U, 0x680A88U, 0x681262U, 0x6823B6U, 0x683B5CU, 0x68401EU, 0x6858F4U, - 0x686920U, 0x6871CAU, 0x68874EU, 0x689FA4U, 0x68AE70U, 0x68B69AU, 0x68CDD8U, 0x68D532U, 0x68E4E6U, 0x68FC0CU, - 0x6909EEU, 0x691104U, 0x6920D0U, 0x69383AU, 0x694378U, 0x695B92U, 0x696A46U, 0x6972ACU, 0x698428U, 0x699CC2U, - 0x69AD16U, 0x69B5FCU, 0x69CEBEU, 0x69D654U, 0x69E780U, 0x69FF6AU, 0x6A0C44U, 0x6A14AEU, 0x6A257AU, 0x6A3D90U, - 0x6A46D2U, 0x6A5E38U, 0x6A6FECU, 0x6A7706U, 0x6A8182U, 0x6A9968U, 0x6AA8BCU, 0x6AB056U, 0x6ACB14U, 0x6AD3FEU, - 0x6AE22AU, 0x6AFAC0U, 0x6B0F22U, 0x6B17C8U, 0x6B261CU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5EU, 0x6B6C8AU, 0x6B7460U, - 0x6B82E4U, 0x6B9A0EU, 0x6BABDAU, 0x6BB330U, 0x6BC872U, 0x6BD098U, 0x6BE14CU, 0x6BF9A6U, 0x6C0710U, 0x6C1FFAU, - 0x6C2E2EU, 0x6C36C4U, 0x6C4D86U, 0x6C556CU, 0x6C64B8U, 0x6C7C52U, 0x6C8AD6U, 0x6C923CU, 0x6CA3E8U, 0x6CBB02U, - 0x6CC040U, 0x6CD8AAU, 0x6CE97EU, 0x6CF194U, 0x6D0476U, 0x6D1C9CU, 0x6D2D48U, 0x6D35A2U, 0x6D4EE0U, 0x6D560AU, - 0x6D67DEU, 0x6D7F34U, 0x6D89B0U, 0x6D915AU, 0x6DA08EU, 0x6DB864U, 0x6DC326U, 0x6DDBCCU, 0x6DEA18U, 0x6DF2F2U, - 0x6E01DCU, 0x6E1936U, 0x6E28E2U, 0x6E3008U, 0x6E4B4AU, 0x6E53A0U, 0x6E6274U, 0x6E7A9EU, 0x6E8C1AU, 0x6E94F0U, - 0x6EA524U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE66U, 0x6EEFB2U, 0x6EF758U, 0x6F02BAU, 0x6F1A50U, 0x6F2B84U, 0x6F336EU, - 0x6F482CU, 0x6F50C6U, 0x6F6112U, 0x6F79F8U, 0x6F8F7CU, 0x6F9796U, 0x6FA642U, 0x6FBEA8U, 0x6FC5EAU, 0x6FDD00U, - 0x6FECD4U, 0x6FF43EU, 0x700EE6U, 0x70160CU, 0x7027D8U, 0x703F32U, 0x704470U, 0x705C9AU, 0x706D4EU, 0x7075A4U, - 0x708320U, 0x709BCAU, 0x70AA1EU, 0x70B2F4U, 0x70C9B6U, 0x70D15CU, 0x70E088U, 0x70F862U, 0x710D80U, 0x71156AU, - 0x7124BEU, 0x713C54U, 0x714716U, 0x715FFCU, 0x716E28U, 0x7176C2U, 0x718046U, 0x7198ACU, 0x71A978U, 0x71B192U, - 0x71CAD0U, 0x71D23AU, 0x71E3EEU, 0x71FB04U, 0x72082AU, 0x7210C0U, 0x722114U, 0x7239FEU, 0x7242BCU, 0x725A56U, - 0x726B82U, 0x727368U, 0x7285ECU, 0x729D06U, 0x72ACD2U, 0x72B438U, 0x72CF7AU, 0x72D790U, 0x72E644U, 0x72FEAEU, - 0x730B4CU, 0x7313A6U, 0x732272U, 0x733A98U, 0x7341DAU, 0x735930U, 0x7368E4U, 0x73700EU, 0x73868AU, 0x739E60U, - 0x73AFB4U, 0x73B75EU, 0x73CC1CU, 0x73D4F6U, 0x73E522U, 0x73FDC8U, 0x74037EU, 0x741B94U, 0x742A40U, 0x7432AAU, - 0x7449E8U, 0x745102U, 0x7460D6U, 0x74783CU, 0x748EB8U, 0x749652U, 0x74A786U, 0x74BF6CU, 0x74C42EU, 0x74DCC4U, - 0x74ED10U, 0x74F5FAU, 0x750018U, 0x7518F2U, 0x752926U, 0x7531CCU, 0x754A8EU, 0x755264U, 0x7563B0U, 0x757B5AU, - 0x758DDEU, 0x759534U, 0x75A4E0U, 0x75BC0AU, 0x75C748U, 0x75DFA2U, 0x75EE76U, 0x75F69CU, 0x7605B2U, 0x761D58U, - 0x762C8CU, 0x763466U, 0x764F24U, 0x7657CEU, 0x76661AU, 0x767EF0U, 0x768874U, 0x76909EU, 0x76A14AU, 0x76B9A0U, - 0x76C2E2U, 0x76DA08U, 0x76EBDCU, 0x76F336U, 0x7706D4U, 0x771E3EU, 0x772FEAU, 0x773700U, 0x774C42U, 0x7754A8U, - 0x77657CU, 0x777D96U, 0x778B12U, 0x7793F8U, 0x77A22CU, 0x77BAC6U, 0x77C184U, 0x77D96EU, 0x77E8BAU, 0x77F050U, - 0x780D3CU, 0x7815D6U, 0x782402U, 0x783CE8U, 0x7847AAU, 0x785F40U, 0x786E94U, 0x78767EU, 0x7880FAU, 0x789810U, - 0x78A9C4U, 0x78B12EU, 0x78CA6CU, 0x78D286U, 0x78E352U, 0x78FBB8U, 0x790E5AU, 0x7916B0U, 0x792764U, 0x793F8EU, - 0x7944CCU, 0x795C26U, 0x796DF2U, 0x797518U, 0x79839CU, 0x799B76U, 0x79AAA2U, 0x79B248U, 0x79C90AU, 0x79D1E0U, - 0x79E034U, 0x79F8DEU, 0x7A0BF0U, 0x7A131AU, 0x7A22CEU, 0x7A3A24U, 0x7A4166U, 0x7A598CU, 0x7A6858U, 0x7A70B2U, - 0x7A8636U, 0x7A9EDCU, 0x7AAF08U, 0x7AB7E2U, 0x7ACCA0U, 0x7AD44AU, 0x7AE59EU, 0x7AFD74U, 0x7B0896U, 0x7B107CU, - 0x7B21A8U, 0x7B3942U, 0x7B4200U, 0x7B5AEAU, 0x7B6B3EU, 0x7B73D4U, 0x7B8550U, 0x7B9DBAU, 0x7BAC6EU, 0x7BB484U, - 0x7BCFC6U, 0x7BD72CU, 0x7BE6F8U, 0x7BFE12U, 0x7C00A4U, 0x7C184EU, 0x7C299AU, 0x7C3170U, 0x7C4A32U, 0x7C52D8U, - 0x7C630CU, 0x7C7BE6U, 0x7C8D62U, 0x7C9588U, 0x7CA45CU, 0x7CBCB6U, 0x7CC7F4U, 0x7CDF1EU, 0x7CEECAU, 0x7CF620U, - 0x7D03C2U, 0x7D1B28U, 0x7D2AFCU, 0x7D3216U, 0x7D4954U, 0x7D51BEU, 0x7D606AU, 0x7D7880U, 0x7D8E04U, 0x7D96EEU, - 0x7DA73AU, 0x7DBFD0U, 0x7DC492U, 0x7DDC78U, 0x7DEDACU, 0x7DF546U, 0x7E0668U, 0x7E1E82U, 0x7E2F56U, 0x7E37BCU, - 0x7E4CFEU, 0x7E5414U, 0x7E65C0U, 0x7E7D2AU, 0x7E8BAEU, 0x7E9344U, 0x7EA290U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D2U, - 0x7EE806U, 0x7EF0ECU, 0x7F050EU, 0x7F1DE4U, 0x7F2C30U, 0x7F34DAU, 0x7F4F98U, 0x7F5772U, 0x7F66A6U, 0x7F7E4CU, - 0x7F88C8U, 0x7F9022U, 0x7FA1F6U, 0x7FB91CU, 0x7FC25EU, 0x7FDAB4U, 0x7FEB60U, 0x7FF38AU, 0x800C74U, 0x80149EU, - 0x80254AU, 0x803DA0U, 0x8046E2U, 0x805E08U, 0x806FDCU, 0x807736U, 0x8081B2U, 0x809958U, 0x80A88CU, 0x80B066U, - 0x80CB24U, 0x80D3CEU, 0x80E21AU, 0x80FAF0U, 0x810F12U, 0x8117F8U, 0x81262CU, 0x813EC6U, 0x814584U, 0x815D6EU, - 0x816CBAU, 0x817450U, 0x8182D4U, 0x819A3EU, 0x81ABEAU, 0x81B300U, 0x81C842U, 0x81D0A8U, 0x81E17CU, 0x81F996U, - 0x820AB8U, 0x821252U, 0x822386U, 0x823B6CU, 0x82402EU, 0x8258C4U, 0x826910U, 0x8271FAU, 0x82877EU, 0x829F94U, - 0x82AE40U, 0x82B6AAU, 0x82CDE8U, 0x82D502U, 0x82E4D6U, 0x82FC3CU, 0x8309DEU, 0x831134U, 0x8320E0U, 0x83380AU, - 0x834348U, 0x835BA2U, 0x836A76U, 0x83729CU, 0x838418U, 0x839CF2U, 0x83AD26U, 0x83B5CCU, 0x83CE8EU, 0x83D664U, - 0x83E7B0U, 0x83FF5AU, 0x8401ECU, 0x841906U, 0x8428D2U, 0x843038U, 0x844B7AU, 0x845390U, 0x846244U, 0x847AAEU, - 0x848C2AU, 0x8494C0U, 0x84A514U, 0x84BDFEU, 0x84C6BCU, 0x84DE56U, 0x84EF82U, 0x84F768U, 0x85028AU, 0x851A60U, - 0x852BB4U, 0x85335EU, 0x85481CU, 0x8550F6U, 0x856122U, 0x8579C8U, 0x858F4CU, 0x8597A6U, 0x85A672U, 0x85BE98U, - 0x85C5DAU, 0x85DD30U, 0x85ECE4U, 0x85F40EU, 0x860720U, 0x861FCAU, 0x862E1EU, 0x8636F4U, 0x864DB6U, 0x86555CU, - 0x866488U, 0x867C62U, 0x868AE6U, 0x86920CU, 0x86A3D8U, 0x86BB32U, 0x86C070U, 0x86D89AU, 0x86E94EU, 0x86F1A4U, - 0x870446U, 0x871CACU, 0x872D78U, 0x873592U, 0x874ED0U, 0x87563AU, 0x8767EEU, 0x877F04U, 0x878980U, 0x87916AU, - 0x87A0BEU, 0x87B854U, 0x87C316U, 0x87DBFCU, 0x87EA28U, 0x87F2C2U, 0x880FAEU, 0x881744U, 0x882690U, 0x883E7AU, - 0x884538U, 0x885DD2U, 0x886C06U, 0x8874ECU, 0x888268U, 0x889A82U, 0x88AB56U, 0x88B3BCU, 0x88C8FEU, 0x88D014U, - 0x88E1C0U, 0x88F92AU, 0x890CC8U, 0x891422U, 0x8925F6U, 0x893D1CU, 0x89465EU, 0x895EB4U, 0x896F60U, 0x89778AU, - 0x89810EU, 0x8999E4U, 0x89A830U, 0x89B0DAU, 0x89CB98U, 0x89D372U, 0x89E2A6U, 0x89FA4CU, 0x8A0962U, 0x8A1188U, - 0x8A205CU, 0x8A38B6U, 0x8A43F4U, 0x8A5B1EU, 0x8A6ACAU, 0x8A7220U, 0x8A84A4U, 0x8A9C4EU, 0x8AAD9AU, 0x8AB570U, - 0x8ACE32U, 0x8AD6D8U, 0x8AE70CU, 0x8AFFE6U, 0x8B0A04U, 0x8B12EEU, 0x8B233AU, 0x8B3BD0U, 0x8B4092U, 0x8B5878U, - 0x8B69ACU, 0x8B7146U, 0x8B87C2U, 0x8B9F28U, 0x8BAEFCU, 0x8BB616U, 0x8BCD54U, 0x8BD5BEU, 0x8BE46AU, 0x8BFC80U, - 0x8C0236U, 0x8C1ADCU, 0x8C2B08U, 0x8C33E2U, 0x8C48A0U, 0x8C504AU, 0x8C619EU, 0x8C7974U, 0x8C8FF0U, 0x8C971AU, - 0x8CA6CEU, 0x8CBE24U, 0x8CC566U, 0x8CDD8CU, 0x8CEC58U, 0x8CF4B2U, 0x8D0150U, 0x8D19BAU, 0x8D286EU, 0x8D3084U, - 0x8D4BC6U, 0x8D532CU, 0x8D62F8U, 0x8D7A12U, 0x8D8C96U, 0x8D947CU, 0x8DA5A8U, 0x8DBD42U, 0x8DC600U, 0x8DDEEAU, - 0x8DEF3EU, 0x8DF7D4U, 0x8E04FAU, 0x8E1C10U, 0x8E2DC4U, 0x8E352EU, 0x8E4E6CU, 0x8E5686U, 0x8E6752U, 0x8E7FB8U, - 0x8E893CU, 0x8E91D6U, 0x8EA002U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB40U, 0x8EEA94U, 0x8EF27EU, 0x8F079CU, 0x8F1F76U, - 0x8F2EA2U, 0x8F3648U, 0x8F4D0AU, 0x8F55E0U, 0x8F6434U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B0U, 0x8FA364U, 0x8FBB8EU, - 0x8FC0CCU, 0x8FD826U, 0x8FE9F2U, 0x8FF118U, 0x900BC0U, 0x90132AU, 0x9022FEU, 0x903A14U, 0x904156U, 0x9059BCU, - 0x906868U, 0x907082U, 0x908606U, 0x909EECU, 0x90AF38U, 0x90B7D2U, 0x90CC90U, 0x90D47AU, 0x90E5AEU, 0x90FD44U, - 0x9108A6U, 0x91104CU, 0x912198U, 0x913972U, 0x914230U, 0x915ADAU, 0x916B0EU, 0x9173E4U, 0x918560U, 0x919D8AU, - 0x91AC5EU, 0x91B4B4U, 0x91CFF6U, 0x91D71CU, 0x91E6C8U, 0x91FE22U, 0x920D0CU, 0x9215E6U, 0x922432U, 0x923CD8U, - 0x92479AU, 0x925F70U, 0x926EA4U, 0x92764EU, 0x9280CAU, 0x929820U, 0x92A9F4U, 0x92B11EU, 0x92CA5CU, 0x92D2B6U, - 0x92E362U, 0x92FB88U, 0x930E6AU, 0x931680U, 0x932754U, 0x933FBEU, 0x9344FCU, 0x935C16U, 0x936DC2U, 0x937528U, - 0x9383ACU, 0x939B46U, 0x93AA92U, 0x93B278U, 0x93C93AU, 0x93D1D0U, 0x93E004U, 0x93F8EEU, 0x940658U, 0x941EB2U, - 0x942F66U, 0x94378CU, 0x944CCEU, 0x945424U, 0x9465F0U, 0x947D1AU, 0x948B9EU, 0x949374U, 0x94A2A0U, 0x94BA4AU, - 0x94C108U, 0x94D9E2U, 0x94E836U, 0x94F0DCU, 0x95053EU, 0x951DD4U, 0x952C00U, 0x9534EAU, 0x954FA8U, 0x955742U, - 0x956696U, 0x957E7CU, 0x9588F8U, 0x959012U, 0x95A1C6U, 0x95B92CU, 0x95C26EU, 0x95DA84U, 0x95EB50U, 0x95F3BAU, - 0x960094U, 0x96187EU, 0x9629AAU, 0x963140U, 0x964A02U, 0x9652E8U, 0x96633CU, 0x967BD6U, 0x968D52U, 0x9695B8U, - 0x96A46CU, 0x96BC86U, 0x96C7C4U, 0x96DF2EU, 0x96EEFAU, 0x96F610U, 0x9703F2U, 0x971B18U, 0x972ACCU, 0x973226U, - 0x974964U, 0x97518EU, 0x97605AU, 0x9778B0U, 0x978E34U, 0x9796DEU, 0x97A70AU, 0x97BFE0U, 0x97C4A2U, 0x97DC48U, - 0x97ED9CU, 0x97F576U, 0x98081AU, 0x9810F0U, 0x982124U, 0x9839CEU, 0x98428CU, 0x985A66U, 0x986BB2U, 0x987358U, - 0x9885DCU, 0x989D36U, 0x98ACE2U, 0x98B408U, 0x98CF4AU, 0x98D7A0U, 0x98E674U, 0x98FE9EU, 0x990B7CU, 0x991396U, - 0x992242U, 0x993AA8U, 0x9941EAU, 0x995900U, 0x9968D4U, 0x99703EU, 0x9986BAU, 0x999E50U, 0x99AF84U, 0x99B76EU, - 0x99CC2CU, 0x99D4C6U, 0x99E512U, 0x99FDF8U, 0x9A0ED6U, 0x9A163CU, 0x9A27E8U, 0x9A3F02U, 0x9A4440U, 0x9A5CAAU, - 0x9A6D7EU, 0x9A7594U, 0x9A8310U, 0x9A9BFAU, 0x9AAA2EU, 0x9AB2C4U, 0x9AC986U, 0x9AD16CU, 0x9AE0B8U, 0x9AF852U, - 0x9B0DB0U, 0x9B155AU, 0x9B248EU, 0x9B3C64U, 0x9B4726U, 0x9B5FCCU, 0x9B6E18U, 0x9B76F2U, 0x9B8076U, 0x9B989CU, - 0x9BA948U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20AU, 0x9BE3DEU, 0x9BFB34U, 0x9C0582U, 0x9C1D68U, 0x9C2CBCU, 0x9C3456U, - 0x9C4F14U, 0x9C57FEU, 0x9C662AU, 0x9C7EC0U, 0x9C8844U, 0x9C90AEU, 0x9CA17AU, 0x9CB990U, 0x9CC2D2U, 0x9CDA38U, - 0x9CEBECU, 0x9CF306U, 0x9D06E4U, 0x9D1E0EU, 0x9D2FDAU, 0x9D3730U, 0x9D4C72U, 0x9D5498U, 0x9D654CU, 0x9D7DA6U, - 0x9D8B22U, 0x9D93C8U, 0x9DA21CU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95EU, 0x9DE88AU, 0x9DF060U, 0x9E034EU, 0x9E1BA4U, - 0x9E2A70U, 0x9E329AU, 0x9E49D8U, 0x9E5132U, 0x9E60E6U, 0x9E780CU, 0x9E8E88U, 0x9E9662U, 0x9EA7B6U, 0x9EBF5CU, - 0x9EC41EU, 0x9EDCF4U, 0x9EED20U, 0x9EF5CAU, 0x9F0028U, 0x9F18C2U, 0x9F2916U, 0x9F31FCU, 0x9F4ABEU, 0x9F5254U, - 0x9F6380U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9504U, 0x9FA4D0U, 0x9FBC3AU, 0x9FC778U, 0x9FDF92U, 0x9FEE46U, 0x9FF6ACU, - 0xA0031CU, 0xA01BF6U, 0xA02A22U, 0xA032C8U, 0xA0498AU, 0xA05160U, 0xA060B4U, 0xA0785EU, 0xA08EDAU, 0xA09630U, - 0xA0A7E4U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA6U, 0xA0ED72U, 0xA0F598U, 0xA1007AU, 0xA11890U, 0xA12944U, 0xA131AEU, - 0xA14AECU, 0xA15206U, 0xA163D2U, 0xA17B38U, 0xA18DBCU, 0xA19556U, 0xA1A482U, 0xA1BC68U, 0xA1C72AU, 0xA1DFC0U, - 0xA1EE14U, 0xA1F6FEU, 0xA205D0U, 0xA21D3AU, 0xA22CEEU, 0xA23404U, 0xA24F46U, 0xA257ACU, 0xA26678U, 0xA27E92U, - 0xA28816U, 0xA290FCU, 0xA2A128U, 0xA2B9C2U, 0xA2C280U, 0xA2DA6AU, 0xA2EBBEU, 0xA2F354U, 0xA306B6U, 0xA31E5CU, - 0xA32F88U, 0xA33762U, 0xA34C20U, 0xA354CAU, 0xA3651EU, 0xA37DF4U, 0xA38B70U, 0xA3939AU, 0xA3A24EU, 0xA3BAA4U, - 0xA3C1E6U, 0xA3D90CU, 0xA3E8D8U, 0xA3F032U, 0xA40E84U, 0xA4166EU, 0xA427BAU, 0xA43F50U, 0xA44412U, 0xA45CF8U, - 0xA46D2CU, 0xA475C6U, 0xA48342U, 0xA49BA8U, 0xA4AA7CU, 0xA4B296U, 0xA4C9D4U, 0xA4D13EU, 0xA4E0EAU, 0xA4F800U, - 0xA50DE2U, 0xA51508U, 0xA524DCU, 0xA53C36U, 0xA54774U, 0xA55F9EU, 0xA56E4AU, 0xA576A0U, 0xA58024U, 0xA598CEU, - 0xA5A91AU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D258U, 0xA5E38CU, 0xA5FB66U, 0xA60848U, 0xA610A2U, 0xA62176U, 0xA6399CU, - 0xA642DEU, 0xA65A34U, 0xA66BE0U, 0xA6730AU, 0xA6858EU, 0xA69D64U, 0xA6ACB0U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F2U, - 0xA6E626U, 0xA6FECCU, 0xA70B2EU, 0xA713C4U, 0xA72210U, 0xA73AFAU, 0xA741B8U, 0xA75952U, 0xA76886U, 0xA7706CU, - 0xA786E8U, 0xA79E02U, 0xA7AFD6U, 0xA7B73CU, 0xA7CC7EU, 0xA7D494U, 0xA7E540U, 0xA7FDAAU, 0xA800C6U, 0xA8182CU, - 0xA829F8U, 0xA83112U, 0xA84A50U, 0xA852BAU, 0xA8636EU, 0xA87B84U, 0xA88D00U, 0xA895EAU, 0xA8A43EU, 0xA8BCD4U, - 0xA8C796U, 0xA8DF7CU, 0xA8EEA8U, 0xA8F642U, 0xA903A0U, 0xA91B4AU, 0xA92A9EU, 0xA93274U, 0xA94936U, 0xA951DCU, - 0xA96008U, 0xA978E2U, 0xA98E66U, 0xA9968CU, 0xA9A758U, 0xA9BFB2U, 0xA9C4F0U, 0xA9DC1AU, 0xA9EDCEU, 0xA9F524U, - 0xAA060AU, 0xAA1EE0U, 0xAA2F34U, 0xAA37DEU, 0xAA4C9CU, 0xAA5476U, 0xAA65A2U, 0xAA7D48U, 0xAA8BCCU, 0xAA9326U, - 0xAAA2F2U, 0xAABA18U, 0xAAC15AU, 0xAAD9B0U, 0xAAE864U, 0xAAF08EU, 0xAB056CU, 0xAB1D86U, 0xAB2C52U, 0xAB34B8U, - 0xAB4FFAU, 0xAB5710U, 0xAB66C4U, 0xAB7E2EU, 0xAB88AAU, 0xAB9040U, 0xABA194U, 0xABB97EU, 0xABC23CU, 0xABDAD6U, - 0xABEB02U, 0xABF3E8U, 0xAC0D5EU, 0xAC15B4U, 0xAC2460U, 0xAC3C8AU, 0xAC47C8U, 0xAC5F22U, 0xAC6EF6U, 0xAC761CU, - 0xAC8098U, 0xAC9872U, 0xACA9A6U, 0xACB14CU, 0xACCA0EU, 0xACD2E4U, 0xACE330U, 0xACFBDAU, 0xAD0E38U, 0xAD16D2U, - 0xAD2706U, 0xAD3FECU, 0xAD44AEU, 0xAD5C44U, 0xAD6D90U, 0xAD757AU, 0xAD83FEU, 0xAD9B14U, 0xADAAC0U, 0xADB22AU, - 0xADC968U, 0xADD182U, 0xADE056U, 0xADF8BCU, 0xAE0B92U, 0xAE1378U, 0xAE22ACU, 0xAE3A46U, 0xAE4104U, 0xAE59EEU, - 0xAE683AU, 0xAE70D0U, 0xAE8654U, 0xAE9EBEU, 0xAEAF6AU, 0xAEB780U, 0xAECCC2U, 0xAED428U, 0xAEE5FCU, 0xAEFD16U, - 0xAF08F4U, 0xAF101EU, 0xAF21CAU, 0xAF3920U, 0xAF4262U, 0xAF5A88U, 0xAF6B5CU, 0xAF73B6U, 0xAF8532U, 0xAF9DD8U, - 0xAFAC0CU, 0xAFB4E6U, 0xAFCFA4U, 0xAFD74EU, 0xAFE69AU, 0xAFFE70U, 0xB004A8U, 0xB01C42U, 0xB02D96U, 0xB0357CU, - 0xB04E3EU, 0xB056D4U, 0xB06700U, 0xB07FEAU, 0xB0896EU, 0xB09184U, 0xB0A050U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB12U, - 0xB0EAC6U, 0xB0F22CU, 0xB107CEU, 0xB11F24U, 0xB12EF0U, 0xB1361AU, 0xB14D58U, 0xB155B2U, 0xB16466U, 0xB17C8CU, - 0xB18A08U, 0xB192E2U, 0xB1A336U, 0xB1BBDCU, 0xB1C09EU, 0xB1D874U, 0xB1E9A0U, 0xB1F14AU, 0xB20264U, 0xB21A8EU, - 0xB22B5AU, 0xB233B0U, 0xB248F2U, 0xB25018U, 0xB261CCU, 0xB27926U, 0xB28FA2U, 0xB29748U, 0xB2A69CU, 0xB2BE76U, - 0xB2C534U, 0xB2DDDEU, 0xB2EC0AU, 0xB2F4E0U, 0xB30102U, 0xB319E8U, 0xB3283CU, 0xB330D6U, 0xB34B94U, 0xB3537EU, - 0xB362AAU, 0xB37A40U, 0xB38CC4U, 0xB3942EU, 0xB3A5FAU, 0xB3BD10U, 0xB3C652U, 0xB3DEB8U, 0xB3EF6CU, 0xB3F786U, - 0xB40930U, 0xB411DAU, 0xB4200EU, 0xB438E4U, 0xB443A6U, 0xB45B4CU, 0xB46A98U, 0xB47272U, 0xB484F6U, 0xB49C1CU, - 0xB4ADC8U, 0xB4B522U, 0xB4CE60U, 0xB4D68AU, 0xB4E75EU, 0xB4FFB4U, 0xB50A56U, 0xB512BCU, 0xB52368U, 0xB53B82U, - 0xB540C0U, 0xB5582AU, 0xB569FEU, 0xB57114U, 0xB58790U, 0xB59F7AU, 0xB5AEAEU, 0xB5B644U, 0xB5CD06U, 0xB5D5ECU, - 0xB5E438U, 0xB5FCD2U, 0xB60FFCU, 0xB61716U, 0xB626C2U, 0xB63E28U, 0xB6456AU, 0xB65D80U, 0xB66C54U, 0xB674BEU, - 0xB6823AU, 0xB69AD0U, 0xB6AB04U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D046U, 0xB6E192U, 0xB6F978U, 0xB70C9AU, 0xB71470U, - 0xB725A4U, 0xB73D4EU, 0xB7460CU, 0xB75EE6U, 0xB76F32U, 0xB777D8U, 0xB7815CU, 0xB799B6U, 0xB7A862U, 0xB7B088U, - 0xB7CBCAU, 0xB7D320U, 0xB7E2F4U, 0xB7FA1EU, 0xB80772U, 0xB81F98U, 0xB82E4CU, 0xB836A6U, 0xB84DE4U, 0xB8550EU, - 0xB864DAU, 0xB87C30U, 0xB88AB4U, 0xB8925EU, 0xB8A38AU, 0xB8BB60U, 0xB8C022U, 0xB8D8C8U, 0xB8E91CU, 0xB8F1F6U, - 0xB90414U, 0xB91CFEU, 0xB92D2AU, 0xB935C0U, 0xB94E82U, 0xB95668U, 0xB967BCU, 0xB97F56U, 0xB989D2U, 0xB99138U, - 0xB9A0ECU, 0xB9B806U, 0xB9C344U, 0xB9DBAEU, 0xB9EA7AU, 0xB9F290U, 0xBA01BEU, 0xBA1954U, 0xBA2880U, 0xBA306AU, - 0xBA4B28U, 0xBA53C2U, 0xBA6216U, 0xBA7AFCU, 0xBA8C78U, 0xBA9492U, 0xBAA546U, 0xBABDACU, 0xBAC6EEU, 0xBADE04U, - 0xBAEFD0U, 0xBAF73AU, 0xBB02D8U, 0xBB1A32U, 0xBB2BE6U, 0xBB330CU, 0xBB484EU, 0xBB50A4U, 0xBB6170U, 0xBB799AU, - 0xBB8F1EU, 0xBB97F4U, 0xBBA620U, 0xBBBECAU, 0xBBC588U, 0xBBDD62U, 0xBBECB6U, 0xBBF45CU, 0xBC0AEAU, 0xBC1200U, - 0xBC23D4U, 0xBC3B3EU, 0xBC407CU, 0xBC5896U, 0xBC6942U, 0xBC71A8U, 0xBC872CU, 0xBC9FC6U, 0xBCAE12U, 0xBCB6F8U, - 0xBCCDBAU, 0xBCD550U, 0xBCE484U, 0xBCFC6EU, 0xBD098CU, 0xBD1166U, 0xBD20B2U, 0xBD3858U, 0xBD431AU, 0xBD5BF0U, - 0xBD6A24U, 0xBD72CEU, 0xBD844AU, 0xBD9CA0U, 0xBDAD74U, 0xBDB59EU, 0xBDCEDCU, 0xBDD636U, 0xBDE7E2U, 0xBDFF08U, - 0xBE0C26U, 0xBE14CCU, 0xBE2518U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5AU, 0xBE6F8EU, 0xBE7764U, 0xBE81E0U, 0xBE990AU, - 0xBEA8DEU, 0xBEB034U, 0xBECB76U, 0xBED39CU, 0xBEE248U, 0xBEFAA2U, 0xBF0F40U, 0xBF17AAU, 0xBF267EU, 0xBF3E94U, - 0xBF45D6U, 0xBF5D3CU, 0xBF6CE8U, 0xBF7402U, 0xBF8286U, 0xBF9A6CU, 0xBFABB8U, 0xBFB352U, 0xBFC810U, 0xBFD0FAU, - 0xBFE12EU, 0xBFF9C4U, 0xC00A4EU, 0xC012A4U, 0xC02370U, 0xC03B9AU, 0xC040D8U, 0xC05832U, 0xC069E6U, 0xC0710CU, - 0xC08788U, 0xC09F62U, 0xC0AEB6U, 0xC0B65CU, 0xC0CD1EU, 0xC0D5F4U, 0xC0E420U, 0xC0FCCAU, 0xC10928U, 0xC111C2U, - 0xC12016U, 0xC138FCU, 0xC143BEU, 0xC15B54U, 0xC16A80U, 0xC1726AU, 0xC184EEU, 0xC19C04U, 0xC1ADD0U, 0xC1B53AU, - 0xC1CE78U, 0xC1D692U, 0xC1E746U, 0xC1FFACU, 0xC20C82U, 0xC21468U, 0xC225BCU, 0xC23D56U, 0xC24614U, 0xC25EFEU, - 0xC26F2AU, 0xC277C0U, 0xC28144U, 0xC299AEU, 0xC2A87AU, 0xC2B090U, 0xC2CBD2U, 0xC2D338U, 0xC2E2ECU, 0xC2FA06U, - 0xC30FE4U, 0xC3170EU, 0xC326DAU, 0xC33E30U, 0xC34572U, 0xC35D98U, 0xC36C4CU, 0xC374A6U, 0xC38222U, 0xC39AC8U, - 0xC3AB1CU, 0xC3B3F6U, 0xC3C8B4U, 0xC3D05EU, 0xC3E18AU, 0xC3F960U, 0xC407D6U, 0xC41F3CU, 0xC42EE8U, 0xC43602U, - 0xC44D40U, 0xC455AAU, 0xC4647EU, 0xC47C94U, 0xC48A10U, 0xC492FAU, 0xC4A32EU, 0xC4BBC4U, 0xC4C086U, 0xC4D86CU, - 0xC4E9B8U, 0xC4F152U, 0xC504B0U, 0xC51C5AU, 0xC52D8EU, 0xC53564U, 0xC54E26U, 0xC556CCU, 0xC56718U, 0xC57FF2U, - 0xC58976U, 0xC5919CU, 0xC5A048U, 0xC5B8A2U, 0xC5C3E0U, 0xC5DB0AU, 0xC5EADEU, 0xC5F234U, 0xC6011AU, 0xC619F0U, - 0xC62824U, 0xC630CEU, 0xC64B8CU, 0xC65366U, 0xC662B2U, 0xC67A58U, 0xC68CDCU, 0xC69436U, 0xC6A5E2U, 0xC6BD08U, - 0xC6C64AU, 0xC6DEA0U, 0xC6EF74U, 0xC6F79EU, 0xC7027CU, 0xC71A96U, 0xC72B42U, 0xC733A8U, 0xC748EAU, 0xC75000U, - 0xC761D4U, 0xC7793EU, 0xC78FBAU, 0xC79750U, 0xC7A684U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC6U, 0xC7EC12U, 0xC7F4F8U, - 0xC80994U, 0xC8117EU, 0xC820AAU, 0xC83840U, 0xC84302U, 0xC85BE8U, 0xC86A3CU, 0xC872D6U, 0xC88452U, 0xC89CB8U, - 0xC8AD6CU, 0xC8B586U, 0xC8CEC4U, 0xC8D62EU, 0xC8E7FAU, 0xC8FF10U, 0xC90AF2U, 0xC91218U, 0xC923CCU, 0xC93B26U, - 0xC94064U, 0xC9588EU, 0xC9695AU, 0xC971B0U, 0xC98734U, 0xC99FDEU, 0xC9AE0AU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D548U, - 0xC9E49CU, 0xC9FC76U, 0xCA0F58U, 0xCA17B2U, 0xCA2666U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D24U, 0xCA6CF0U, 0xCA741AU, - 0xCA829EU, 0xCA9A74U, 0xCAABA0U, 0xCAB34AU, 0xCAC808U, 0xCAD0E2U, 0xCAE136U, 0xCAF9DCU, 0xCB0C3EU, 0xCB14D4U, - 0xCB2500U, 0xCB3DEAU, 0xCB46A8U, 0xCB5E42U, 0xCB6F96U, 0xCB777CU, 0xCB81F8U, 0xCB9912U, 0xCBA8C6U, 0xCBB02CU, - 0xCBCB6EU, 0xCBD384U, 0xCBE250U, 0xCBFABAU, 0xCC040CU, 0xCC1CE6U, 0xCC2D32U, 0xCC35D8U, 0xCC4E9AU, 0xCC5670U, - 0xCC67A4U, 0xCC7F4EU, 0xCC89CAU, 0xCC9120U, 0xCCA0F4U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB6U, 0xCCEA62U, 0xCCF288U, - 0xCD076AU, 0xCD1F80U, 0xCD2E54U, 0xCD36BEU, 0xCD4DFCU, 0xCD5516U, 0xCD64C2U, 0xCD7C28U, 0xCD8AACU, 0xCD9246U, - 0xCDA392U, 0xCDBB78U, 0xCDC03AU, 0xCDD8D0U, 0xCDE904U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2AU, 0xCE2BFEU, 0xCE3314U, - 0xCE4856U, 0xCE50BCU, 0xCE6168U, 0xCE7982U, 0xCE8F06U, 0xCE97ECU, 0xCEA638U, 0xCEBED2U, 0xCEC590U, 0xCEDD7AU, - 0xCEECAEU, 0xCEF444U, 0xCF01A6U, 0xCF194CU, 0xCF2898U, 0xCF3072U, 0xCF4B30U, 0xCF53DAU, 0xCF620EU, 0xCF7AE4U, - 0xCF8C60U, 0xCF948AU, 0xCFA55EU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1CU, 0xCFEFC8U, 0xCFF722U, 0xD00DFAU, 0xD01510U, - 0xD024C4U, 0xD03C2EU, 0xD0476CU, 0xD05F86U, 0xD06E52U, 0xD076B8U, 0xD0803CU, 0xD098D6U, 0xD0A902U, 0xD0B1E8U, - 0xD0CAAAU, 0xD0D240U, 0xD0E394U, 0xD0FB7EU, 0xD10E9CU, 0xD11676U, 0xD127A2U, 0xD13F48U, 0xD1440AU, 0xD15CE0U, - 0xD16D34U, 0xD175DEU, 0xD1835AU, 0xD19BB0U, 0xD1AA64U, 0xD1B28EU, 0xD1C9CCU, 0xD1D126U, 0xD1E0F2U, 0xD1F818U, - 0xD20B36U, 0xD213DCU, 0xD22208U, 0xD23AE2U, 0xD241A0U, 0xD2594AU, 0xD2689EU, 0xD27074U, 0xD286F0U, 0xD29E1AU, - 0xD2AFCEU, 0xD2B724U, 0xD2CC66U, 0xD2D48CU, 0xD2E558U, 0xD2FDB2U, 0xD30850U, 0xD310BAU, 0xD3216EU, 0xD33984U, - 0xD342C6U, 0xD35A2CU, 0xD36BF8U, 0xD37312U, 0xD38596U, 0xD39D7CU, 0xD3ACA8U, 0xD3B442U, 0xD3CF00U, 0xD3D7EAU, - 0xD3E63EU, 0xD3FED4U, 0xD40062U, 0xD41888U, 0xD4295CU, 0xD431B6U, 0xD44AF4U, 0xD4521EU, 0xD463CAU, 0xD47B20U, - 0xD48DA4U, 0xD4954EU, 0xD4A49AU, 0xD4BC70U, 0xD4C732U, 0xD4DFD8U, 0xD4EE0CU, 0xD4F6E6U, 0xD50304U, 0xD51BEEU, - 0xD52A3AU, 0xD532D0U, 0xD54992U, 0xD55178U, 0xD560ACU, 0xD57846U, 0xD58EC2U, 0xD59628U, 0xD5A7FCU, 0xD5BF16U, - 0xD5C454U, 0xD5DCBEU, 0xD5ED6AU, 0xD5F580U, 0xD606AEU, 0xD61E44U, 0xD62F90U, 0xD6377AU, 0xD64C38U, 0xD654D2U, - 0xD66506U, 0xD67DECU, 0xD68B68U, 0xD69382U, 0xD6A256U, 0xD6BABCU, 0xD6C1FEU, 0xD6D914U, 0xD6E8C0U, 0xD6F02AU, - 0xD705C8U, 0xD71D22U, 0xD72CF6U, 0xD7341CU, 0xD74F5EU, 0xD757B4U, 0xD76660U, 0xD77E8AU, 0xD7880EU, 0xD790E4U, - 0xD7A130U, 0xD7B9DAU, 0xD7C298U, 0xD7DA72U, 0xD7EBA6U, 0xD7F34CU, 0xD80E20U, 0xD816CAU, 0xD8271EU, 0xD83FF4U, - 0xD844B6U, 0xD85C5CU, 0xD86D88U, 0xD87562U, 0xD883E6U, 0xD89B0CU, 0xD8AAD8U, 0xD8B232U, 0xD8C970U, 0xD8D19AU, - 0xD8E04EU, 0xD8F8A4U, 0xD90D46U, 0xD915ACU, 0xD92478U, 0xD93C92U, 0xD947D0U, 0xD95F3AU, 0xD96EEEU, 0xD97604U, - 0xD98080U, 0xD9986AU, 0xD9A9BEU, 0xD9B154U, 0xD9CA16U, 0xD9D2FCU, 0xD9E328U, 0xD9FBC2U, 0xDA08ECU, 0xDA1006U, - 0xDA21D2U, 0xDA3938U, 0xDA427AU, 0xDA5A90U, 0xDA6B44U, 0xDA73AEU, 0xDA852AU, 0xDA9DC0U, 0xDAAC14U, 0xDAB4FEU, - 0xDACFBCU, 0xDAD756U, 0xDAE682U, 0xDAFE68U, 0xDB0B8AU, 0xDB1360U, 0xDB22B4U, 0xDB3A5EU, 0xDB411CU, 0xDB59F6U, - 0xDB6822U, 0xDB70C8U, 0xDB864CU, 0xDB9EA6U, 0xDBAF72U, 0xDBB798U, 0xDBCCDAU, 0xDBD430U, 0xDBE5E4U, 0xDBFD0EU, - 0xDC03B8U, 0xDC1B52U, 0xDC2A86U, 0xDC326CU, 0xDC492EU, 0xDC51C4U, 0xDC6010U, 0xDC78FAU, 0xDC8E7EU, 0xDC9694U, - 0xDCA740U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC02U, 0xDCEDD6U, 0xDCF53CU, 0xDD00DEU, 0xDD1834U, 0xDD29E0U, 0xDD310AU, - 0xDD4A48U, 0xDD52A2U, 0xDD6376U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F2U, 0xDDA426U, 0xDDBCCCU, 0xDDC78EU, 0xDDDF64U, - 0xDDEEB0U, 0xDDF65AU, 0xDE0574U, 0xDE1D9EU, 0xDE2C4AU, 0xDE34A0U, 0xDE4FE2U, 0xDE5708U, 0xDE66DCU, 0xDE7E36U, - 0xDE88B2U, 0xDE9058U, 0xDEA18CU, 0xDEB966U, 0xDEC224U, 0xDEDACEU, 0xDEEB1AU, 0xDEF3F0U, 0xDF0612U, 0xDF1EF8U, - 0xDF2F2CU, 0xDF37C6U, 0xDF4C84U, 0xDF546EU, 0xDF65BAU, 0xDF7D50U, 0xDF8BD4U, 0xDF933EU, 0xDFA2EAU, 0xDFBA00U, - 0xDFC142U, 0xDFD9A8U, 0xDFE87CU, 0xDFF096U, 0xE00526U, 0xE01DCCU, 0xE02C18U, 0xE034F2U, 0xE04FB0U, 0xE0575AU, - 0xE0668EU, 0xE07E64U, 0xE088E0U, 0xE0900AU, 0xE0A1DEU, 0xE0B934U, 0xE0C276U, 0xE0DA9CU, 0xE0EB48U, 0xE0F3A2U, - 0xE10640U, 0xE11EAAU, 0xE12F7EU, 0xE13794U, 0xE14CD6U, 0xE1543CU, 0xE165E8U, 0xE17D02U, 0xE18B86U, 0xE1936CU, - 0xE1A2B8U, 0xE1BA52U, 0xE1C110U, 0xE1D9FAU, 0xE1E82EU, 0xE1F0C4U, 0xE203EAU, 0xE21B00U, 0xE22AD4U, 0xE2323EU, - 0xE2497CU, 0xE25196U, 0xE26042U, 0xE278A8U, 0xE28E2CU, 0xE296C6U, 0xE2A712U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC50U, - 0xE2ED84U, 0xE2F56EU, 0xE3008CU, 0xE31866U, 0xE329B2U, 0xE33158U, 0xE34A1AU, 0xE352F0U, 0xE36324U, 0xE37BCEU, - 0xE38D4AU, 0xE395A0U, 0xE3A474U, 0xE3BC9EU, 0xE3C7DCU, 0xE3DF36U, 0xE3EEE2U, 0xE3F608U, 0xE408BEU, 0xE41054U, - 0xE42180U, 0xE4396AU, 0xE44228U, 0xE45AC2U, 0xE46B16U, 0xE473FCU, 0xE48578U, 0xE49D92U, 0xE4AC46U, 0xE4B4ACU, - 0xE4CFEEU, 0xE4D704U, 0xE4E6D0U, 0xE4FE3AU, 0xE50BD8U, 0xE51332U, 0xE522E6U, 0xE53A0CU, 0xE5414EU, 0xE559A4U, - 0xE56870U, 0xE5709AU, 0xE5861EU, 0xE59EF4U, 0xE5AF20U, 0xE5B7CAU, 0xE5CC88U, 0xE5D462U, 0xE5E5B6U, 0xE5FD5CU, - 0xE60E72U, 0xE61698U, 0xE6274CU, 0xE63FA6U, 0xE644E4U, 0xE65C0EU, 0xE66DDAU, 0xE67530U, 0xE683B4U, 0xE69B5EU, - 0xE6AA8AU, 0xE6B260U, 0xE6C922U, 0xE6D1C8U, 0xE6E01CU, 0xE6F8F6U, 0xE70D14U, 0xE715FEU, 0xE7242AU, 0xE73CC0U, - 0xE74782U, 0xE75F68U, 0xE76EBCU, 0xE77656U, 0xE780D2U, 0xE79838U, 0xE7A9ECU, 0xE7B106U, 0xE7CA44U, 0xE7D2AEU, - 0xE7E37AU, 0xE7FB90U, 0xE806FCU, 0xE81E16U, 0xE82FC2U, 0xE83728U, 0xE84C6AU, 0xE85480U, 0xE86554U, 0xE87DBEU, - 0xE88B3AU, 0xE893D0U, 0xE8A204U, 0xE8BAEEU, 0xE8C1ACU, 0xE8D946U, 0xE8E892U, 0xE8F078U, 0xE9059AU, 0xE91D70U, - 0xE92CA4U, 0xE9344EU, 0xE94F0CU, 0xE957E6U, 0xE96632U, 0xE97ED8U, 0xE9885CU, 0xE990B6U, 0xE9A162U, 0xE9B988U, - 0xE9C2CAU, 0xE9DA20U, 0xE9EBF4U, 0xE9F31EU, 0xEA0030U, 0xEA18DAU, 0xEA290EU, 0xEA31E4U, 0xEA4AA6U, 0xEA524CU, - 0xEA6398U, 0xEA7B72U, 0xEA8DF6U, 0xEA951CU, 0xEAA4C8U, 0xEABC22U, 0xEAC760U, 0xEADF8AU, 0xEAEE5EU, 0xEAF6B4U, - 0xEB0356U, 0xEB1BBCU, 0xEB2A68U, 0xEB3282U, 0xEB49C0U, 0xEB512AU, 0xEB60FEU, 0xEB7814U, 0xEB8E90U, 0xEB967AU, - 0xEBA7AEU, 0xEBBF44U, 0xEBC406U, 0xEBDCECU, 0xEBED38U, 0xEBF5D2U, 0xEC0B64U, 0xEC138EU, 0xEC225AU, 0xEC3AB0U, - 0xEC41F2U, 0xEC5918U, 0xEC68CCU, 0xEC7026U, 0xEC86A2U, 0xEC9E48U, 0xECAF9CU, 0xECB776U, 0xECCC34U, 0xECD4DEU, - 0xECE50AU, 0xECFDE0U, 0xED0802U, 0xED10E8U, 0xED213CU, 0xED39D6U, 0xED4294U, 0xED5A7EU, 0xED6BAAU, 0xED7340U, - 0xED85C4U, 0xED9D2EU, 0xEDACFAU, 0xEDB410U, 0xEDCF52U, 0xEDD7B8U, 0xEDE66CU, 0xEDFE86U, 0xEE0DA8U, 0xEE1542U, - 0xEE2496U, 0xEE3C7CU, 0xEE473EU, 0xEE5FD4U, 0xEE6E00U, 0xEE76EAU, 0xEE806EU, 0xEE9884U, 0xEEA950U, 0xEEB1BAU, - 0xEECAF8U, 0xEED212U, 0xEEE3C6U, 0xEEFB2CU, 0xEF0ECEU, 0xEF1624U, 0xEF27F0U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB2U, - 0xEF6D66U, 0xEF758CU, 0xEF8308U, 0xEF9BE2U, 0xEFAA36U, 0xEFB2DCU, 0xEFC99EU, 0xEFD174U, 0xEFE0A0U, 0xEFF84AU, - 0xF00292U, 0xF01A78U, 0xF02BACU, 0xF03346U, 0xF04804U, 0xF050EEU, 0xF0613AU, 0xF079D0U, 0xF08F54U, 0xF097BEU, - 0xF0A66AU, 0xF0BE80U, 0xF0C5C2U, 0xF0DD28U, 0xF0ECFCU, 0xF0F416U, 0xF101F4U, 0xF1191EU, 0xF128CAU, 0xF13020U, - 0xF14B62U, 0xF15388U, 0xF1625CU, 0xF17AB6U, 0xF18C32U, 0xF194D8U, 0xF1A50CU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4EU, - 0xF1EF9AU, 0xF1F770U, 0xF2045EU, 0xF21CB4U, 0xF22D60U, 0xF2358AU, 0xF24EC8U, 0xF25622U, 0xF267F6U, 0xF27F1CU, - 0xF28998U, 0xF29172U, 0xF2A0A6U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE4U, 0xF2EA30U, 0xF2F2DAU, 0xF30738U, 0xF31FD2U, - 0xF32E06U, 0xF336ECU, 0xF34DAEU, 0xF35544U, 0xF36490U, 0xF37C7AU, 0xF38AFEU, 0xF39214U, 0xF3A3C0U, 0xF3BB2AU, - 0xF3C068U, 0xF3D882U, 0xF3E956U, 0xF3F1BCU, 0xF40F0AU, 0xF417E0U, 0xF42634U, 0xF43EDEU, 0xF4459CU, 0xF45D76U, - 0xF46CA2U, 0xF47448U, 0xF482CCU, 0xF49A26U, 0xF4ABF2U, 0xF4B318U, 0xF4C85AU, 0xF4D0B0U, 0xF4E164U, 0xF4F98EU, - 0xF50C6CU, 0xF51486U, 0xF52552U, 0xF53DB8U, 0xF546FAU, 0xF55E10U, 0xF56FC4U, 0xF5772EU, 0xF581AAU, 0xF59940U, - 0xF5A894U, 0xF5B07EU, 0xF5CB3CU, 0xF5D3D6U, 0xF5E202U, 0xF5FAE8U, 0xF609C6U, 0xF6112CU, 0xF620F8U, 0xF63812U, - 0xF64350U, 0xF65BBAU, 0xF66A6EU, 0xF67284U, 0xF68400U, 0xF69CEAU, 0xF6AD3EU, 0xF6B5D4U, 0xF6CE96U, 0xF6D67CU, - 0xF6E7A8U, 0xF6FF42U, 0xF70AA0U, 0xF7124AU, 0xF7239EU, 0xF73B74U, 0xF74036U, 0xF758DCU, 0xF76908U, 0xF771E2U, - 0xF78766U, 0xF79F8CU, 0xF7AE58U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51AU, 0xF7E4CEU, 0xF7FC24U, 0xF80148U, 0xF819A2U, - 0xF82876U, 0xF8309CU, 0xF84BDEU, 0xF85334U, 0xF862E0U, 0xF87A0AU, 0xF88C8EU, 0xF89464U, 0xF8A5B0U, 0xF8BD5AU, - 0xF8C618U, 0xF8DEF2U, 0xF8EF26U, 0xF8F7CCU, 0xF9022EU, 0xF91AC4U, 0xF92B10U, 0xF933FAU, 0xF948B8U, 0xF95052U, - 0xF96186U, 0xF9796CU, 0xF98FE8U, 0xF99702U, 0xF9A6D6U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD94U, 0xF9EC40U, 0xF9F4AAU, - 0xFA0784U, 0xFA1F6EU, 0xFA2EBAU, 0xFA3650U, 0xFA4D12U, 0xFA55F8U, 0xFA642CU, 0xFA7CC6U, 0xFA8A42U, 0xFA92A8U, - 0xFAA37CU, 0xFABB96U, 0xFAC0D4U, 0xFAD83EU, 0xFAE9EAU, 0xFAF100U, 0xFB04E2U, 0xFB1C08U, 0xFB2DDCU, 0xFB3536U, - 0xFB4E74U, 0xFB569EU, 0xFB674AU, 0xFB7FA0U, 0xFB8924U, 0xFB91CEU, 0xFBA01AU, 0xFBB8F0U, 0xFBC3B2U, 0xFBDB58U, - 0xFBEA8CU, 0xFBF266U, 0xFC0CD0U, 0xFC143AU, 0xFC25EEU, 0xFC3D04U, 0xFC4646U, 0xFC5EACU, 0xFC6F78U, 0xFC7792U, - 0xFC8116U, 0xFC99FCU, 0xFCA828U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36AU, 0xFCE2BEU, 0xFCFA54U, 0xFD0FB6U, 0xFD175CU, - 0xFD2688U, 0xFD3E62U, 0xFD4520U, 0xFD5DCAU, 0xFD6C1EU, 0xFD74F4U, 0xFD8270U, 0xFD9A9AU, 0xFDAB4EU, 0xFDB3A4U, - 0xFDC8E6U, 0xFDD00CU, 0xFDE1D8U, 0xFDF932U, 0xFE0A1CU, 0xFE12F6U, 0xFE2322U, 0xFE3BC8U, 0xFE408AU, 0xFE5860U, - 0xFE69B4U, 0xFE715EU, 0xFE87DAU, 0xFE9F30U, 0xFEAEE4U, 0xFEB60EU, 0xFECD4CU, 0xFED5A6U, 0xFEE472U, 0xFEFC98U, - 0xFF097AU, 0xFF1190U, 0xFF2044U, 0xFF38AEU, 0xFF43ECU, 0xFF5B06U, 0xFF6AD2U, 0xFF7238U, 0xFF84BCU, 0xFF9C56U, - 0xFFAD82U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C0U, 0xFFE714U, 0xFFFFFEU + 0x000000U, 0x0018EAU, 0x00293EU, 0x0031D4U, 0x004A96U, 0x00527CU, 0x0063A8U, 0x007B42U, 0x008DC6U, 0x00952CU, + 0x00A4F8U, 0x00BC12U, 0x00C750U, 0x00DFBAU, 0x00EE6EU, 0x00F684U, 0x010366U, 0x011B8CU, 0x012A58U, 0x0132B2U, + 0x0149F0U, 0x01511AU, 0x0160CEU, 0x017824U, 0x018EA0U, 0x01964AU, 0x01A79EU, 0x01BF74U, 0x01C436U, 0x01DCDCU, + 0x01ED08U, 0x01F5E2U, 0x0206CCU, 0x021E26U, 0x022FF2U, 0x023718U, 0x024C5AU, 0x0254B0U, 0x026564U, 0x027D8EU, + 0x028B0AU, 0x0293E0U, 0x02A234U, 0x02BADEU, 0x02C19CU, 0x02D976U, 0x02E8A2U, 0x02F048U, 0x0305AAU, 0x031D40U, + 0x032C94U, 0x03347EU, 0x034F3CU, 0x0357D6U, 0x036602U, 0x037EE8U, 0x03886CU, 0x039086U, 0x03A152U, 0x03B9B8U, + 0x03C2FAU, 0x03DA10U, 0x03EBC4U, 0x03F32EU, 0x040D98U, 0x041572U, 0x0424A6U, 0x043C4CU, 0x04470EU, 0x045FE4U, + 0x046E30U, 0x0476DAU, 0x04805EU, 0x0498B4U, 0x04A960U, 0x04B18AU, 0x04CAC8U, 0x04D222U, 0x04E3F6U, 0x04FB1CU, + 0x050EFEU, 0x051614U, 0x0527C0U, 0x053F2AU, 0x054468U, 0x055C82U, 0x056D56U, 0x0575BCU, 0x058338U, 0x059BD2U, + 0x05AA06U, 0x05B2ECU, 0x05C9AEU, 0x05D144U, 0x05E090U, 0x05F87AU, 0x060B54U, 0x0613BEU, 0x06226AU, 0x063A80U, + 0x0641C2U, 0x065928U, 0x0668FCU, 0x067016U, 0x068692U, 0x069E78U, 0x06AFACU, 0x06B746U, 0x06CC04U, 0x06D4EEU, + 0x06E53AU, 0x06FDD0U, 0x070832U, 0x0710D8U, 0x07210CU, 0x0739E6U, 0x0742A4U, 0x075A4EU, 0x076B9AU, 0x077370U, + 0x0785F4U, 0x079D1EU, 0x07ACCAU, 0x07B420U, 0x07CF62U, 0x07D788U, 0x07E65CU, 0x07FEB6U, 0x0803DAU, 0x081B30U, + 0x082AE4U, 0x08320EU, 0x08494CU, 0x0851A6U, 0x086072U, 0x087898U, 0x088E1CU, 0x0896F6U, 0x08A722U, 0x08BFC8U, + 0x08C48AU, 0x08DC60U, 0x08EDB4U, 0x08F55EU, 0x0900BCU, 0x091856U, 0x092982U, 0x093168U, 0x094A2AU, 0x0952C0U, + 0x096314U, 0x097BFEU, 0x098D7AU, 0x099590U, 0x09A444U, 0x09BCAEU, 0x09C7ECU, 0x09DF06U, 0x09EED2U, 0x09F638U, + 0x0A0516U, 0x0A1DFCU, 0x0A2C28U, 0x0A34C2U, 0x0A4F80U, 0x0A576AU, 0x0A66BEU, 0x0A7E54U, 0x0A88D0U, 0x0A903AU, + 0x0AA1EEU, 0x0AB904U, 0x0AC246U, 0x0ADAACU, 0x0AEB78U, 0x0AF392U, 0x0B0670U, 0x0B1E9AU, 0x0B2F4EU, 0x0B37A4U, + 0x0B4CE6U, 0x0B540CU, 0x0B65D8U, 0x0B7D32U, 0x0B8BB6U, 0x0B935CU, 0x0BA288U, 0x0BBA62U, 0x0BC120U, 0x0BD9CAU, + 0x0BE81EU, 0x0BF0F4U, 0x0C0E42U, 0x0C16A8U, 0x0C277CU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3EU, 0x0C6DEAU, 0x0C7500U, + 0x0C8384U, 0x0C9B6EU, 0x0CAABAU, 0x0CB250U, 0x0CC912U, 0x0CD1F8U, 0x0CE02CU, 0x0CF8C6U, 0x0D0D24U, 0x0D15CEU, + 0x0D241AU, 0x0D3CF0U, 0x0D47B2U, 0x0D5F58U, 0x0D6E8CU, 0x0D7666U, 0x0D80E2U, 0x0D9808U, 0x0DA9DCU, 0x0DB136U, + 0x0DCA74U, 0x0DD29EU, 0x0DE34AU, 0x0DFBA0U, 0x0E088EU, 0x0E1064U, 0x0E21B0U, 0x0E395AU, 0x0E4218U, 0x0E5AF2U, + 0x0E6B26U, 0x0E73CCU, 0x0E8548U, 0x0E9DA2U, 0x0EAC76U, 0x0EB49CU, 0x0ECFDEU, 0x0ED734U, 0x0EE6E0U, 0x0EFE0AU, + 0x0F0BE8U, 0x0F1302U, 0x0F22D6U, 0x0F3A3CU, 0x0F417EU, 0x0F5994U, 0x0F6840U, 0x0F70AAU, 0x0F862EU, 0x0F9EC4U, + 0x0FAF10U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD452U, 0x0FE586U, 0x0FFD6CU, 0x1007B4U, 0x101F5EU, 0x102E8AU, 0x103660U, + 0x104D22U, 0x1055C8U, 0x10641CU, 0x107CF6U, 0x108A72U, 0x109298U, 0x10A34CU, 0x10BBA6U, 0x10C0E4U, 0x10D80EU, + 0x10E9DAU, 0x10F130U, 0x1104D2U, 0x111C38U, 0x112DECU, 0x113506U, 0x114E44U, 0x1156AEU, 0x11677AU, 0x117F90U, + 0x118914U, 0x1191FEU, 0x11A02AU, 0x11B8C0U, 0x11C382U, 0x11DB68U, 0x11EABCU, 0x11F256U, 0x120178U, 0x121992U, + 0x122846U, 0x1230ACU, 0x124BEEU, 0x125304U, 0x1262D0U, 0x127A3AU, 0x128CBEU, 0x129454U, 0x12A580U, 0x12BD6AU, + 0x12C628U, 0x12DEC2U, 0x12EF16U, 0x12F7FCU, 0x13021EU, 0x131AF4U, 0x132B20U, 0x1333CAU, 0x134888U, 0x135062U, + 0x1361B6U, 0x13795CU, 0x138FD8U, 0x139732U, 0x13A6E6U, 0x13BE0CU, 0x13C54EU, 0x13DDA4U, 0x13EC70U, 0x13F49AU, + 0x140A2CU, 0x1412C6U, 0x142312U, 0x143BF8U, 0x1440BAU, 0x145850U, 0x146984U, 0x14716EU, 0x1487EAU, 0x149F00U, + 0x14AED4U, 0x14B63EU, 0x14CD7CU, 0x14D596U, 0x14E442U, 0x14FCA8U, 0x15094AU, 0x1511A0U, 0x152074U, 0x15389EU, + 0x1543DCU, 0x155B36U, 0x156AE2U, 0x157208U, 0x15848CU, 0x159C66U, 0x15ADB2U, 0x15B558U, 0x15CE1AU, 0x15D6F0U, + 0x15E724U, 0x15FFCEU, 0x160CE0U, 0x16140AU, 0x1625DEU, 0x163D34U, 0x164676U, 0x165E9CU, 0x166F48U, 0x1677A2U, + 0x168126U, 0x1699CCU, 0x16A818U, 0x16B0F2U, 0x16CBB0U, 0x16D35AU, 0x16E28EU, 0x16FA64U, 0x170F86U, 0x17176CU, + 0x1726B8U, 0x173E52U, 0x174510U, 0x175DFAU, 0x176C2EU, 0x1774C4U, 0x178240U, 0x179AAAU, 0x17AB7EU, 0x17B394U, + 0x17C8D6U, 0x17D03CU, 0x17E1E8U, 0x17F902U, 0x18046EU, 0x181C84U, 0x182D50U, 0x1835BAU, 0x184EF8U, 0x185612U, + 0x1867C6U, 0x187F2CU, 0x1889A8U, 0x189142U, 0x18A096U, 0x18B87CU, 0x18C33EU, 0x18DBD4U, 0x18EA00U, 0x18F2EAU, + 0x190708U, 0x191FE2U, 0x192E36U, 0x1936DCU, 0x194D9EU, 0x195574U, 0x1964A0U, 0x197C4AU, 0x198ACEU, 0x199224U, + 0x19A3F0U, 0x19BB1AU, 0x19C058U, 0x19D8B2U, 0x19E966U, 0x19F18CU, 0x1A02A2U, 0x1A1A48U, 0x1A2B9CU, 0x1A3376U, + 0x1A4834U, 0x1A50DEU, 0x1A610AU, 0x1A79E0U, 0x1A8F64U, 0x1A978EU, 0x1AA65AU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD18U, + 0x1AECCCU, 0x1AF426U, 0x1B01C4U, 0x1B192EU, 0x1B28FAU, 0x1B3010U, 0x1B4B52U, 0x1B53B8U, 0x1B626CU, 0x1B7A86U, + 0x1B8C02U, 0x1B94E8U, 0x1BA53CU, 0x1BBDD6U, 0x1BC694U, 0x1BDE7EU, 0x1BEFAAU, 0x1BF740U, 0x1C09F6U, 0x1C111CU, + 0x1C20C8U, 0x1C3822U, 0x1C4360U, 0x1C5B8AU, 0x1C6A5EU, 0x1C72B4U, 0x1C8430U, 0x1C9CDAU, 0x1CAD0EU, 0x1CB5E4U, + 0x1CCEA6U, 0x1CD64CU, 0x1CE798U, 0x1CFF72U, 0x1D0A90U, 0x1D127AU, 0x1D23AEU, 0x1D3B44U, 0x1D4006U, 0x1D58ECU, + 0x1D6938U, 0x1D71D2U, 0x1D8756U, 0x1D9FBCU, 0x1DAE68U, 0x1DB682U, 0x1DCDC0U, 0x1DD52AU, 0x1DE4FEU, 0x1DFC14U, + 0x1E0F3AU, 0x1E17D0U, 0x1E2604U, 0x1E3EEEU, 0x1E45ACU, 0x1E5D46U, 0x1E6C92U, 0x1E7478U, 0x1E82FCU, 0x1E9A16U, + 0x1EABC2U, 0x1EB328U, 0x1EC86AU, 0x1ED080U, 0x1EE154U, 0x1EF9BEU, 0x1F0C5CU, 0x1F14B6U, 0x1F2562U, 0x1F3D88U, + 0x1F46CAU, 0x1F5E20U, 0x1F6FF4U, 0x1F771EU, 0x1F819AU, 0x1F9970U, 0x1FA8A4U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E6U, + 0x1FE232U, 0x1FFAD8U, 0x200F68U, 0x201782U, 0x202656U, 0x203EBCU, 0x2045FEU, 0x205D14U, 0x206CC0U, 0x20742AU, + 0x2082AEU, 0x209A44U, 0x20AB90U, 0x20B37AU, 0x20C838U, 0x20D0D2U, 0x20E106U, 0x20F9ECU, 0x210C0EU, 0x2114E4U, + 0x212530U, 0x213DDAU, 0x214698U, 0x215E72U, 0x216FA6U, 0x21774CU, 0x2181C8U, 0x219922U, 0x21A8F6U, 0x21B01CU, + 0x21CB5EU, 0x21D3B4U, 0x21E260U, 0x21FA8AU, 0x2209A4U, 0x22114EU, 0x22209AU, 0x223870U, 0x224332U, 0x225BD8U, + 0x226A0CU, 0x2272E6U, 0x228462U, 0x229C88U, 0x22AD5CU, 0x22B5B6U, 0x22CEF4U, 0x22D61EU, 0x22E7CAU, 0x22FF20U, + 0x230AC2U, 0x231228U, 0x2323FCU, 0x233B16U, 0x234054U, 0x2358BEU, 0x23696AU, 0x237180U, 0x238704U, 0x239FEEU, + 0x23AE3AU, 0x23B6D0U, 0x23CD92U, 0x23D578U, 0x23E4ACU, 0x23FC46U, 0x2402F0U, 0x241A1AU, 0x242BCEU, 0x243324U, + 0x244866U, 0x24508CU, 0x246158U, 0x2479B2U, 0x248F36U, 0x2497DCU, 0x24A608U, 0x24BEE2U, 0x24C5A0U, 0x24DD4AU, + 0x24EC9EU, 0x24F474U, 0x250196U, 0x25197CU, 0x2528A8U, 0x253042U, 0x254B00U, 0x2553EAU, 0x25623EU, 0x257AD4U, + 0x258C50U, 0x2594BAU, 0x25A56EU, 0x25BD84U, 0x25C6C6U, 0x25DE2CU, 0x25EFF8U, 0x25F712U, 0x26043CU, 0x261CD6U, + 0x262D02U, 0x2635E8U, 0x264EAAU, 0x265640U, 0x266794U, 0x267F7EU, 0x2689FAU, 0x269110U, 0x26A0C4U, 0x26B82EU, + 0x26C36CU, 0x26DB86U, 0x26EA52U, 0x26F2B8U, 0x27075AU, 0x271FB0U, 0x272E64U, 0x27368EU, 0x274DCCU, 0x275526U, + 0x2764F2U, 0x277C18U, 0x278A9CU, 0x279276U, 0x27A3A2U, 0x27BB48U, 0x27C00AU, 0x27D8E0U, 0x27E934U, 0x27F1DEU, + 0x280CB2U, 0x281458U, 0x28258CU, 0x283D66U, 0x284624U, 0x285ECEU, 0x286F1AU, 0x2877F0U, 0x288174U, 0x28999EU, + 0x28A84AU, 0x28B0A0U, 0x28CBE2U, 0x28D308U, 0x28E2DCU, 0x28FA36U, 0x290FD4U, 0x29173EU, 0x2926EAU, 0x293E00U, + 0x294542U, 0x295DA8U, 0x296C7CU, 0x297496U, 0x298212U, 0x299AF8U, 0x29AB2CU, 0x29B3C6U, 0x29C884U, 0x29D06EU, + 0x29E1BAU, 0x29F950U, 0x2A0A7EU, 0x2A1294U, 0x2A2340U, 0x2A3BAAU, 0x2A40E8U, 0x2A5802U, 0x2A69D6U, 0x2A713CU, + 0x2A87B8U, 0x2A9F52U, 0x2AAE86U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C4U, 0x2AE410U, 0x2AFCFAU, 0x2B0918U, 0x2B11F2U, + 0x2B2026U, 0x2B38CCU, 0x2B438EU, 0x2B5B64U, 0x2B6AB0U, 0x2B725AU, 0x2B84DEU, 0x2B9C34U, 0x2BADE0U, 0x2BB50AU, + 0x2BCE48U, 0x2BD6A2U, 0x2BE776U, 0x2BFF9CU, 0x2C012AU, 0x2C19C0U, 0x2C2814U, 0x2C30FEU, 0x2C4BBCU, 0x2C5356U, + 0x2C6282U, 0x2C7A68U, 0x2C8CECU, 0x2C9406U, 0x2CA5D2U, 0x2CBD38U, 0x2CC67AU, 0x2CDE90U, 0x2CEF44U, 0x2CF7AEU, + 0x2D024CU, 0x2D1AA6U, 0x2D2B72U, 0x2D3398U, 0x2D48DAU, 0x2D5030U, 0x2D61E4U, 0x2D790EU, 0x2D8F8AU, 0x2D9760U, + 0x2DA6B4U, 0x2DBE5EU, 0x2DC51CU, 0x2DDDF6U, 0x2DEC22U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0CU, 0x2E2ED8U, 0x2E3632U, + 0x2E4D70U, 0x2E559AU, 0x2E644EU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CAU, 0x2EA31EU, 0x2EBBF4U, 0x2EC0B6U, 0x2ED85CU, + 0x2EE988U, 0x2EF162U, 0x2F0480U, 0x2F1C6AU, 0x2F2DBEU, 0x2F3554U, 0x2F4E16U, 0x2F56FCU, 0x2F6728U, 0x2F7FC2U, + 0x2F8946U, 0x2F91ACU, 0x2FA078U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3AU, 0x2FEAEEU, 0x2FF204U, 0x3008DCU, 0x301036U, + 0x3021E2U, 0x303908U, 0x30424AU, 0x305AA0U, 0x306B74U, 0x30739EU, 0x30851AU, 0x309DF0U, 0x30AC24U, 0x30B4CEU, + 0x30CF8CU, 0x30D766U, 0x30E6B2U, 0x30FE58U, 0x310BBAU, 0x311350U, 0x312284U, 0x313A6EU, 0x31412CU, 0x3159C6U, + 0x316812U, 0x3170F8U, 0x31867CU, 0x319E96U, 0x31AF42U, 0x31B7A8U, 0x31CCEAU, 0x31D400U, 0x31E5D4U, 0x31FD3EU, + 0x320E10U, 0x3216FAU, 0x32272EU, 0x323FC4U, 0x324486U, 0x325C6CU, 0x326DB8U, 0x327552U, 0x3283D6U, 0x329B3CU, + 0x32AAE8U, 0x32B202U, 0x32C940U, 0x32D1AAU, 0x32E07EU, 0x32F894U, 0x330D76U, 0x33159CU, 0x332448U, 0x333CA2U, + 0x3347E0U, 0x335F0AU, 0x336EDEU, 0x337634U, 0x3380B0U, 0x33985AU, 0x33A98EU, 0x33B164U, 0x33CA26U, 0x33D2CCU, + 0x33E318U, 0x33FBF2U, 0x340544U, 0x341DAEU, 0x342C7AU, 0x343490U, 0x344FD2U, 0x345738U, 0x3466ECU, 0x347E06U, + 0x348882U, 0x349068U, 0x34A1BCU, 0x34B956U, 0x34C214U, 0x34DAFEU, 0x34EB2AU, 0x34F3C0U, 0x350622U, 0x351EC8U, + 0x352F1CU, 0x3537F6U, 0x354CB4U, 0x35545EU, 0x35658AU, 0x357D60U, 0x358BE4U, 0x35930EU, 0x35A2DAU, 0x35BA30U, + 0x35C172U, 0x35D998U, 0x35E84CU, 0x35F0A6U, 0x360388U, 0x361B62U, 0x362AB6U, 0x36325CU, 0x36491EU, 0x3651F4U, + 0x366020U, 0x3678CAU, 0x368E4EU, 0x3696A4U, 0x36A770U, 0x36BF9AU, 0x36C4D8U, 0x36DC32U, 0x36EDE6U, 0x36F50CU, + 0x3700EEU, 0x371804U, 0x3729D0U, 0x37313AU, 0x374A78U, 0x375292U, 0x376346U, 0x377BACU, 0x378D28U, 0x3795C2U, + 0x37A416U, 0x37BCFCU, 0x37C7BEU, 0x37DF54U, 0x37EE80U, 0x37F66AU, 0x380B06U, 0x3813ECU, 0x382238U, 0x383AD2U, + 0x384190U, 0x38597AU, 0x3868AEU, 0x387044U, 0x3886C0U, 0x389E2AU, 0x38AFFEU, 0x38B714U, 0x38CC56U, 0x38D4BCU, + 0x38E568U, 0x38FD82U, 0x390860U, 0x39108AU, 0x39215EU, 0x3939B4U, 0x3942F6U, 0x395A1CU, 0x396BC8U, 0x397322U, + 0x3985A6U, 0x399D4CU, 0x39AC98U, 0x39B472U, 0x39CF30U, 0x39D7DAU, 0x39E60EU, 0x39FEE4U, 0x3A0DCAU, 0x3A1520U, + 0x3A24F4U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB6U, 0x3A6E62U, 0x3A7688U, 0x3A800CU, 0x3A98E6U, 0x3AA932U, 0x3AB1D8U, + 0x3ACA9AU, 0x3AD270U, 0x3AE3A4U, 0x3AFB4EU, 0x3B0EACU, 0x3B1646U, 0x3B2792U, 0x3B3F78U, 0x3B443AU, 0x3B5CD0U, + 0x3B6D04U, 0x3B75EEU, 0x3B836AU, 0x3B9B80U, 0x3BAA54U, 0x3BB2BEU, 0x3BC9FCU, 0x3BD116U, 0x3BE0C2U, 0x3BF828U, + 0x3C069EU, 0x3C1E74U, 0x3C2FA0U, 0x3C374AU, 0x3C4C08U, 0x3C54E2U, 0x3C6536U, 0x3C7DDCU, 0x3C8B58U, 0x3C93B2U, + 0x3CA266U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD924U, 0x3CE8F0U, 0x3CF01AU, 0x3D05F8U, 0x3D1D12U, 0x3D2CC6U, 0x3D342CU, + 0x3D4F6EU, 0x3D5784U, 0x3D6650U, 0x3D7EBAU, 0x3D883EU, 0x3D90D4U, 0x3DA100U, 0x3DB9EAU, 0x3DC2A8U, 0x3DDA42U, + 0x3DEB96U, 0x3DF37CU, 0x3E0052U, 0x3E18B8U, 0x3E296CU, 0x3E3186U, 0x3E4AC4U, 0x3E522EU, 0x3E63FAU, 0x3E7B10U, + 0x3E8D94U, 0x3E957EU, 0x3EA4AAU, 0x3EBC40U, 0x3EC702U, 0x3EDFE8U, 0x3EEE3CU, 0x3EF6D6U, 0x3F0334U, 0x3F1BDEU, + 0x3F2A0AU, 0x3F32E0U, 0x3F49A2U, 0x3F5148U, 0x3F609CU, 0x3F7876U, 0x3F8EF2U, 0x3F9618U, 0x3FA7CCU, 0x3FBF26U, + 0x3FC464U, 0x3FDC8EU, 0x3FED5AU, 0x3FF5B0U, 0x40063AU, 0x401ED0U, 0x402F04U, 0x4037EEU, 0x404CACU, 0x405446U, + 0x406592U, 0x407D78U, 0x408BFCU, 0x409316U, 0x40A2C2U, 0x40BA28U, 0x40C16AU, 0x40D980U, 0x40E854U, 0x40F0BEU, + 0x41055CU, 0x411DB6U, 0x412C62U, 0x413488U, 0x414FCAU, 0x415720U, 0x4166F4U, 0x417E1EU, 0x41889AU, 0x419070U, + 0x41A1A4U, 0x41B94EU, 0x41C20CU, 0x41DAE6U, 0x41EB32U, 0x41F3D8U, 0x4200F6U, 0x42181CU, 0x4229C8U, 0x423122U, + 0x424A60U, 0x42528AU, 0x42635EU, 0x427BB4U, 0x428D30U, 0x4295DAU, 0x42A40EU, 0x42BCE4U, 0x42C7A6U, 0x42DF4CU, + 0x42EE98U, 0x42F672U, 0x430390U, 0x431B7AU, 0x432AAEU, 0x433244U, 0x434906U, 0x4351ECU, 0x436038U, 0x4378D2U, + 0x438E56U, 0x4396BCU, 0x43A768U, 0x43BF82U, 0x43C4C0U, 0x43DC2AU, 0x43EDFEU, 0x43F514U, 0x440BA2U, 0x441348U, + 0x44229CU, 0x443A76U, 0x444134U, 0x4459DEU, 0x44680AU, 0x4470E0U, 0x448664U, 0x449E8EU, 0x44AF5AU, 0x44B7B0U, + 0x44CCF2U, 0x44D418U, 0x44E5CCU, 0x44FD26U, 0x4508C4U, 0x45102EU, 0x4521FAU, 0x453910U, 0x454252U, 0x455AB8U, + 0x456B6CU, 0x457386U, 0x458502U, 0x459DE8U, 0x45AC3CU, 0x45B4D6U, 0x45CF94U, 0x45D77EU, 0x45E6AAU, 0x45FE40U, + 0x460D6EU, 0x461584U, 0x462450U, 0x463CBAU, 0x4647F8U, 0x465F12U, 0x466EC6U, 0x46762CU, 0x4680A8U, 0x469842U, + 0x46A996U, 0x46B17CU, 0x46CA3EU, 0x46D2D4U, 0x46E300U, 0x46FBEAU, 0x470E08U, 0x4716E2U, 0x472736U, 0x473FDCU, + 0x47449EU, 0x475C74U, 0x476DA0U, 0x47754AU, 0x4783CEU, 0x479B24U, 0x47AAF0U, 0x47B21AU, 0x47C958U, 0x47D1B2U, + 0x47E066U, 0x47F88CU, 0x4805E0U, 0x481D0AU, 0x482CDEU, 0x483434U, 0x484F76U, 0x48579CU, 0x486648U, 0x487EA2U, + 0x488826U, 0x4890CCU, 0x48A118U, 0x48B9F2U, 0x48C2B0U, 0x48DA5AU, 0x48EB8EU, 0x48F364U, 0x490686U, 0x491E6CU, + 0x492FB8U, 0x493752U, 0x494C10U, 0x4954FAU, 0x49652EU, 0x497DC4U, 0x498B40U, 0x4993AAU, 0x49A27EU, 0x49BA94U, + 0x49C1D6U, 0x49D93CU, 0x49E8E8U, 0x49F002U, 0x4A032CU, 0x4A1BC6U, 0x4A2A12U, 0x4A32F8U, 0x4A49BAU, 0x4A5150U, + 0x4A6084U, 0x4A786EU, 0x4A8EEAU, 0x4A9600U, 0x4AA7D4U, 0x4ABF3EU, 0x4AC47CU, 0x4ADC96U, 0x4AED42U, 0x4AF5A8U, + 0x4B004AU, 0x4B18A0U, 0x4B2974U, 0x4B319EU, 0x4B4ADCU, 0x4B5236U, 0x4B63E2U, 0x4B7B08U, 0x4B8D8CU, 0x4B9566U, + 0x4BA4B2U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF0U, 0x4BEE24U, 0x4BF6CEU, 0x4C0878U, 0x4C1092U, 0x4C2146U, 0x4C39ACU, + 0x4C42EEU, 0x4C5A04U, 0x4C6BD0U, 0x4C733AU, 0x4C85BEU, 0x4C9D54U, 0x4CAC80U, 0x4CB46AU, 0x4CCF28U, 0x4CD7C2U, + 0x4CE616U, 0x4CFEFCU, 0x4D0B1EU, 0x4D13F4U, 0x4D2220U, 0x4D3ACAU, 0x4D4188U, 0x4D5962U, 0x4D68B6U, 0x4D705CU, + 0x4D86D8U, 0x4D9E32U, 0x4DAFE6U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A4U, 0x4DE570U, 0x4DFD9AU, 0x4E0EB4U, 0x4E165EU, + 0x4E278AU, 0x4E3F60U, 0x4E4422U, 0x4E5CC8U, 0x4E6D1CU, 0x4E75F6U, 0x4E8372U, 0x4E9B98U, 0x4EAA4CU, 0x4EB2A6U, + 0x4EC9E4U, 0x4ED10EU, 0x4EE0DAU, 0x4EF830U, 0x4F0DD2U, 0x4F1538U, 0x4F24ECU, 0x4F3C06U, 0x4F4744U, 0x4F5FAEU, + 0x4F6E7AU, 0x4F7690U, 0x4F8014U, 0x4F98FEU, 0x4FA92AU, 0x4FB1C0U, 0x4FCA82U, 0x4FD268U, 0x4FE3BCU, 0x4FFB56U, + 0x50018EU, 0x501964U, 0x5028B0U, 0x50305AU, 0x504B18U, 0x5053F2U, 0x506226U, 0x507ACCU, 0x508C48U, 0x5094A2U, + 0x50A576U, 0x50BD9CU, 0x50C6DEU, 0x50DE34U, 0x50EFE0U, 0x50F70AU, 0x5102E8U, 0x511A02U, 0x512BD6U, 0x51333CU, + 0x51487EU, 0x515094U, 0x516140U, 0x5179AAU, 0x518F2EU, 0x5197C4U, 0x51A610U, 0x51BEFAU, 0x51C5B8U, 0x51DD52U, + 0x51EC86U, 0x51F46CU, 0x520742U, 0x521FA8U, 0x522E7CU, 0x523696U, 0x524DD4U, 0x52553EU, 0x5264EAU, 0x527C00U, + 0x528A84U, 0x52926EU, 0x52A3BAU, 0x52BB50U, 0x52C012U, 0x52D8F8U, 0x52E92CU, 0x52F1C6U, 0x530424U, 0x531CCEU, + 0x532D1AU, 0x5335F0U, 0x534EB2U, 0x535658U, 0x53678CU, 0x537F66U, 0x5389E2U, 0x539108U, 0x53A0DCU, 0x53B836U, + 0x53C374U, 0x53DB9EU, 0x53EA4AU, 0x53F2A0U, 0x540C16U, 0x5414FCU, 0x542528U, 0x543DC2U, 0x544680U, 0x545E6AU, + 0x546FBEU, 0x547754U, 0x5481D0U, 0x54993AU, 0x54A8EEU, 0x54B004U, 0x54CB46U, 0x54D3ACU, 0x54E278U, 0x54FA92U, + 0x550F70U, 0x55179AU, 0x55264EU, 0x553EA4U, 0x5545E6U, 0x555D0CU, 0x556CD8U, 0x557432U, 0x5582B6U, 0x559A5CU, + 0x55AB88U, 0x55B362U, 0x55C820U, 0x55D0CAU, 0x55E11EU, 0x55F9F4U, 0x560ADAU, 0x561230U, 0x5623E4U, 0x563B0EU, + 0x56404CU, 0x5658A6U, 0x566972U, 0x567198U, 0x56871CU, 0x569FF6U, 0x56AE22U, 0x56B6C8U, 0x56CD8AU, 0x56D560U, + 0x56E4B4U, 0x56FC5EU, 0x5709BCU, 0x571156U, 0x572082U, 0x573868U, 0x57432AU, 0x575BC0U, 0x576A14U, 0x5772FEU, + 0x57847AU, 0x579C90U, 0x57AD44U, 0x57B5AEU, 0x57CEECU, 0x57D606U, 0x57E7D2U, 0x57FF38U, 0x580254U, 0x581ABEU, + 0x582B6AU, 0x583380U, 0x5848C2U, 0x585028U, 0x5861FCU, 0x587916U, 0x588F92U, 0x589778U, 0x58A6ACU, 0x58BE46U, + 0x58C504U, 0x58DDEEU, 0x58EC3AU, 0x58F4D0U, 0x590132U, 0x5919D8U, 0x59280CU, 0x5930E6U, 0x594BA4U, 0x59534EU, + 0x59629AU, 0x597A70U, 0x598CF4U, 0x59941EU, 0x59A5CAU, 0x59BD20U, 0x59C662U, 0x59DE88U, 0x59EF5CU, 0x59F7B6U, + 0x5A0498U, 0x5A1C72U, 0x5A2DA6U, 0x5A354CU, 0x5A4E0EU, 0x5A56E4U, 0x5A6730U, 0x5A7FDAU, 0x5A895EU, 0x5A91B4U, + 0x5AA060U, 0x5AB88AU, 0x5AC3C8U, 0x5ADB22U, 0x5AEAF6U, 0x5AF21CU, 0x5B07FEU, 0x5B1F14U, 0x5B2EC0U, 0x5B362AU, + 0x5B4D68U, 0x5B5582U, 0x5B6456U, 0x5B7CBCU, 0x5B8A38U, 0x5B92D2U, 0x5BA306U, 0x5BBBECU, 0x5BC0AEU, 0x5BD844U, + 0x5BE990U, 0x5BF17AU, 0x5C0FCCU, 0x5C1726U, 0x5C26F2U, 0x5C3E18U, 0x5C455AU, 0x5C5DB0U, 0x5C6C64U, 0x5C748EU, + 0x5C820AU, 0x5C9AE0U, 0x5CAB34U, 0x5CB3DEU, 0x5CC89CU, 0x5CD076U, 0x5CE1A2U, 0x5CF948U, 0x5D0CAAU, 0x5D1440U, + 0x5D2594U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED6U, 0x5D6F02U, 0x5D77E8U, 0x5D816CU, 0x5D9986U, 0x5DA852U, 0x5DB0B8U, + 0x5DCBFAU, 0x5DD310U, 0x5DE2C4U, 0x5DFA2EU, 0x5E0900U, 0x5E11EAU, 0x5E203EU, 0x5E38D4U, 0x5E4396U, 0x5E5B7CU, + 0x5E6AA8U, 0x5E7242U, 0x5E84C6U, 0x5E9C2CU, 0x5EADF8U, 0x5EB512U, 0x5ECE50U, 0x5ED6BAU, 0x5EE76EU, 0x5EFF84U, + 0x5F0A66U, 0x5F128CU, 0x5F2358U, 0x5F3BB2U, 0x5F40F0U, 0x5F581AU, 0x5F69CEU, 0x5F7124U, 0x5F87A0U, 0x5F9F4AU, + 0x5FAE9EU, 0x5FB674U, 0x5FCD36U, 0x5FD5DCU, 0x5FE408U, 0x5FFCE2U, 0x600952U, 0x6011B8U, 0x60206CU, 0x603886U, + 0x6043C4U, 0x605B2EU, 0x606AFAU, 0x607210U, 0x608494U, 0x609C7EU, 0x60ADAAU, 0x60B540U, 0x60CE02U, 0x60D6E8U, + 0x60E73CU, 0x60FFD6U, 0x610A34U, 0x6112DEU, 0x61230AU, 0x613BE0U, 0x6140A2U, 0x615848U, 0x61699CU, 0x617176U, + 0x6187F2U, 0x619F18U, 0x61AECCU, 0x61B626U, 0x61CD64U, 0x61D58EU, 0x61E45AU, 0x61FCB0U, 0x620F9EU, 0x621774U, + 0x6226A0U, 0x623E4AU, 0x624508U, 0x625DE2U, 0x626C36U, 0x6274DCU, 0x628258U, 0x629AB2U, 0x62AB66U, 0x62B38CU, + 0x62C8CEU, 0x62D024U, 0x62E1F0U, 0x62F91AU, 0x630CF8U, 0x631412U, 0x6325C6U, 0x633D2CU, 0x63466EU, 0x635E84U, + 0x636F50U, 0x6377BAU, 0x63813EU, 0x6399D4U, 0x63A800U, 0x63B0EAU, 0x63CBA8U, 0x63D342U, 0x63E296U, 0x63FA7CU, + 0x6404CAU, 0x641C20U, 0x642DF4U, 0x64351EU, 0x644E5CU, 0x6456B6U, 0x646762U, 0x647F88U, 0x64890CU, 0x6491E6U, + 0x64A032U, 0x64B8D8U, 0x64C39AU, 0x64DB70U, 0x64EAA4U, 0x64F24EU, 0x6507ACU, 0x651F46U, 0x652E92U, 0x653678U, + 0x654D3AU, 0x6555D0U, 0x656404U, 0x657CEEU, 0x658A6AU, 0x659280U, 0x65A354U, 0x65BBBEU, 0x65C0FCU, 0x65D816U, + 0x65E9C2U, 0x65F128U, 0x660206U, 0x661AECU, 0x662B38U, 0x6633D2U, 0x664890U, 0x66507AU, 0x6661AEU, 0x667944U, + 0x668FC0U, 0x66972AU, 0x66A6FEU, 0x66BE14U, 0x66C556U, 0x66DDBCU, 0x66EC68U, 0x66F482U, 0x670160U, 0x67198AU, + 0x67285EU, 0x6730B4U, 0x674BF6U, 0x67531CU, 0x6762C8U, 0x677A22U, 0x678CA6U, 0x67944CU, 0x67A598U, 0x67BD72U, + 0x67C630U, 0x67DEDAU, 0x67EF0EU, 0x67F7E4U, 0x680A88U, 0x681262U, 0x6823B6U, 0x683B5CU, 0x68401EU, 0x6858F4U, + 0x686920U, 0x6871CAU, 0x68874EU, 0x689FA4U, 0x68AE70U, 0x68B69AU, 0x68CDD8U, 0x68D532U, 0x68E4E6U, 0x68FC0CU, + 0x6909EEU, 0x691104U, 0x6920D0U, 0x69383AU, 0x694378U, 0x695B92U, 0x696A46U, 0x6972ACU, 0x698428U, 0x699CC2U, + 0x69AD16U, 0x69B5FCU, 0x69CEBEU, 0x69D654U, 0x69E780U, 0x69FF6AU, 0x6A0C44U, 0x6A14AEU, 0x6A257AU, 0x6A3D90U, + 0x6A46D2U, 0x6A5E38U, 0x6A6FECU, 0x6A7706U, 0x6A8182U, 0x6A9968U, 0x6AA8BCU, 0x6AB056U, 0x6ACB14U, 0x6AD3FEU, + 0x6AE22AU, 0x6AFAC0U, 0x6B0F22U, 0x6B17C8U, 0x6B261CU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5EU, 0x6B6C8AU, 0x6B7460U, + 0x6B82E4U, 0x6B9A0EU, 0x6BABDAU, 0x6BB330U, 0x6BC872U, 0x6BD098U, 0x6BE14CU, 0x6BF9A6U, 0x6C0710U, 0x6C1FFAU, + 0x6C2E2EU, 0x6C36C4U, 0x6C4D86U, 0x6C556CU, 0x6C64B8U, 0x6C7C52U, 0x6C8AD6U, 0x6C923CU, 0x6CA3E8U, 0x6CBB02U, + 0x6CC040U, 0x6CD8AAU, 0x6CE97EU, 0x6CF194U, 0x6D0476U, 0x6D1C9CU, 0x6D2D48U, 0x6D35A2U, 0x6D4EE0U, 0x6D560AU, + 0x6D67DEU, 0x6D7F34U, 0x6D89B0U, 0x6D915AU, 0x6DA08EU, 0x6DB864U, 0x6DC326U, 0x6DDBCCU, 0x6DEA18U, 0x6DF2F2U, + 0x6E01DCU, 0x6E1936U, 0x6E28E2U, 0x6E3008U, 0x6E4B4AU, 0x6E53A0U, 0x6E6274U, 0x6E7A9EU, 0x6E8C1AU, 0x6E94F0U, + 0x6EA524U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE66U, 0x6EEFB2U, 0x6EF758U, 0x6F02BAU, 0x6F1A50U, 0x6F2B84U, 0x6F336EU, + 0x6F482CU, 0x6F50C6U, 0x6F6112U, 0x6F79F8U, 0x6F8F7CU, 0x6F9796U, 0x6FA642U, 0x6FBEA8U, 0x6FC5EAU, 0x6FDD00U, + 0x6FECD4U, 0x6FF43EU, 0x700EE6U, 0x70160CU, 0x7027D8U, 0x703F32U, 0x704470U, 0x705C9AU, 0x706D4EU, 0x7075A4U, + 0x708320U, 0x709BCAU, 0x70AA1EU, 0x70B2F4U, 0x70C9B6U, 0x70D15CU, 0x70E088U, 0x70F862U, 0x710D80U, 0x71156AU, + 0x7124BEU, 0x713C54U, 0x714716U, 0x715FFCU, 0x716E28U, 0x7176C2U, 0x718046U, 0x7198ACU, 0x71A978U, 0x71B192U, + 0x71CAD0U, 0x71D23AU, 0x71E3EEU, 0x71FB04U, 0x72082AU, 0x7210C0U, 0x722114U, 0x7239FEU, 0x7242BCU, 0x725A56U, + 0x726B82U, 0x727368U, 0x7285ECU, 0x729D06U, 0x72ACD2U, 0x72B438U, 0x72CF7AU, 0x72D790U, 0x72E644U, 0x72FEAEU, + 0x730B4CU, 0x7313A6U, 0x732272U, 0x733A98U, 0x7341DAU, 0x735930U, 0x7368E4U, 0x73700EU, 0x73868AU, 0x739E60U, + 0x73AFB4U, 0x73B75EU, 0x73CC1CU, 0x73D4F6U, 0x73E522U, 0x73FDC8U, 0x74037EU, 0x741B94U, 0x742A40U, 0x7432AAU, + 0x7449E8U, 0x745102U, 0x7460D6U, 0x74783CU, 0x748EB8U, 0x749652U, 0x74A786U, 0x74BF6CU, 0x74C42EU, 0x74DCC4U, + 0x74ED10U, 0x74F5FAU, 0x750018U, 0x7518F2U, 0x752926U, 0x7531CCU, 0x754A8EU, 0x755264U, 0x7563B0U, 0x757B5AU, + 0x758DDEU, 0x759534U, 0x75A4E0U, 0x75BC0AU, 0x75C748U, 0x75DFA2U, 0x75EE76U, 0x75F69CU, 0x7605B2U, 0x761D58U, + 0x762C8CU, 0x763466U, 0x764F24U, 0x7657CEU, 0x76661AU, 0x767EF0U, 0x768874U, 0x76909EU, 0x76A14AU, 0x76B9A0U, + 0x76C2E2U, 0x76DA08U, 0x76EBDCU, 0x76F336U, 0x7706D4U, 0x771E3EU, 0x772FEAU, 0x773700U, 0x774C42U, 0x7754A8U, + 0x77657CU, 0x777D96U, 0x778B12U, 0x7793F8U, 0x77A22CU, 0x77BAC6U, 0x77C184U, 0x77D96EU, 0x77E8BAU, 0x77F050U, + 0x780D3CU, 0x7815D6U, 0x782402U, 0x783CE8U, 0x7847AAU, 0x785F40U, 0x786E94U, 0x78767EU, 0x7880FAU, 0x789810U, + 0x78A9C4U, 0x78B12EU, 0x78CA6CU, 0x78D286U, 0x78E352U, 0x78FBB8U, 0x790E5AU, 0x7916B0U, 0x792764U, 0x793F8EU, + 0x7944CCU, 0x795C26U, 0x796DF2U, 0x797518U, 0x79839CU, 0x799B76U, 0x79AAA2U, 0x79B248U, 0x79C90AU, 0x79D1E0U, + 0x79E034U, 0x79F8DEU, 0x7A0BF0U, 0x7A131AU, 0x7A22CEU, 0x7A3A24U, 0x7A4166U, 0x7A598CU, 0x7A6858U, 0x7A70B2U, + 0x7A8636U, 0x7A9EDCU, 0x7AAF08U, 0x7AB7E2U, 0x7ACCA0U, 0x7AD44AU, 0x7AE59EU, 0x7AFD74U, 0x7B0896U, 0x7B107CU, + 0x7B21A8U, 0x7B3942U, 0x7B4200U, 0x7B5AEAU, 0x7B6B3EU, 0x7B73D4U, 0x7B8550U, 0x7B9DBAU, 0x7BAC6EU, 0x7BB484U, + 0x7BCFC6U, 0x7BD72CU, 0x7BE6F8U, 0x7BFE12U, 0x7C00A4U, 0x7C184EU, 0x7C299AU, 0x7C3170U, 0x7C4A32U, 0x7C52D8U, + 0x7C630CU, 0x7C7BE6U, 0x7C8D62U, 0x7C9588U, 0x7CA45CU, 0x7CBCB6U, 0x7CC7F4U, 0x7CDF1EU, 0x7CEECAU, 0x7CF620U, + 0x7D03C2U, 0x7D1B28U, 0x7D2AFCU, 0x7D3216U, 0x7D4954U, 0x7D51BEU, 0x7D606AU, 0x7D7880U, 0x7D8E04U, 0x7D96EEU, + 0x7DA73AU, 0x7DBFD0U, 0x7DC492U, 0x7DDC78U, 0x7DEDACU, 0x7DF546U, 0x7E0668U, 0x7E1E82U, 0x7E2F56U, 0x7E37BCU, + 0x7E4CFEU, 0x7E5414U, 0x7E65C0U, 0x7E7D2AU, 0x7E8BAEU, 0x7E9344U, 0x7EA290U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D2U, + 0x7EE806U, 0x7EF0ECU, 0x7F050EU, 0x7F1DE4U, 0x7F2C30U, 0x7F34DAU, 0x7F4F98U, 0x7F5772U, 0x7F66A6U, 0x7F7E4CU, + 0x7F88C8U, 0x7F9022U, 0x7FA1F6U, 0x7FB91CU, 0x7FC25EU, 0x7FDAB4U, 0x7FEB60U, 0x7FF38AU, 0x800C74U, 0x80149EU, + 0x80254AU, 0x803DA0U, 0x8046E2U, 0x805E08U, 0x806FDCU, 0x807736U, 0x8081B2U, 0x809958U, 0x80A88CU, 0x80B066U, + 0x80CB24U, 0x80D3CEU, 0x80E21AU, 0x80FAF0U, 0x810F12U, 0x8117F8U, 0x81262CU, 0x813EC6U, 0x814584U, 0x815D6EU, + 0x816CBAU, 0x817450U, 0x8182D4U, 0x819A3EU, 0x81ABEAU, 0x81B300U, 0x81C842U, 0x81D0A8U, 0x81E17CU, 0x81F996U, + 0x820AB8U, 0x821252U, 0x822386U, 0x823B6CU, 0x82402EU, 0x8258C4U, 0x826910U, 0x8271FAU, 0x82877EU, 0x829F94U, + 0x82AE40U, 0x82B6AAU, 0x82CDE8U, 0x82D502U, 0x82E4D6U, 0x82FC3CU, 0x8309DEU, 0x831134U, 0x8320E0U, 0x83380AU, + 0x834348U, 0x835BA2U, 0x836A76U, 0x83729CU, 0x838418U, 0x839CF2U, 0x83AD26U, 0x83B5CCU, 0x83CE8EU, 0x83D664U, + 0x83E7B0U, 0x83FF5AU, 0x8401ECU, 0x841906U, 0x8428D2U, 0x843038U, 0x844B7AU, 0x845390U, 0x846244U, 0x847AAEU, + 0x848C2AU, 0x8494C0U, 0x84A514U, 0x84BDFEU, 0x84C6BCU, 0x84DE56U, 0x84EF82U, 0x84F768U, 0x85028AU, 0x851A60U, + 0x852BB4U, 0x85335EU, 0x85481CU, 0x8550F6U, 0x856122U, 0x8579C8U, 0x858F4CU, 0x8597A6U, 0x85A672U, 0x85BE98U, + 0x85C5DAU, 0x85DD30U, 0x85ECE4U, 0x85F40EU, 0x860720U, 0x861FCAU, 0x862E1EU, 0x8636F4U, 0x864DB6U, 0x86555CU, + 0x866488U, 0x867C62U, 0x868AE6U, 0x86920CU, 0x86A3D8U, 0x86BB32U, 0x86C070U, 0x86D89AU, 0x86E94EU, 0x86F1A4U, + 0x870446U, 0x871CACU, 0x872D78U, 0x873592U, 0x874ED0U, 0x87563AU, 0x8767EEU, 0x877F04U, 0x878980U, 0x87916AU, + 0x87A0BEU, 0x87B854U, 0x87C316U, 0x87DBFCU, 0x87EA28U, 0x87F2C2U, 0x880FAEU, 0x881744U, 0x882690U, 0x883E7AU, + 0x884538U, 0x885DD2U, 0x886C06U, 0x8874ECU, 0x888268U, 0x889A82U, 0x88AB56U, 0x88B3BCU, 0x88C8FEU, 0x88D014U, + 0x88E1C0U, 0x88F92AU, 0x890CC8U, 0x891422U, 0x8925F6U, 0x893D1CU, 0x89465EU, 0x895EB4U, 0x896F60U, 0x89778AU, + 0x89810EU, 0x8999E4U, 0x89A830U, 0x89B0DAU, 0x89CB98U, 0x89D372U, 0x89E2A6U, 0x89FA4CU, 0x8A0962U, 0x8A1188U, + 0x8A205CU, 0x8A38B6U, 0x8A43F4U, 0x8A5B1EU, 0x8A6ACAU, 0x8A7220U, 0x8A84A4U, 0x8A9C4EU, 0x8AAD9AU, 0x8AB570U, + 0x8ACE32U, 0x8AD6D8U, 0x8AE70CU, 0x8AFFE6U, 0x8B0A04U, 0x8B12EEU, 0x8B233AU, 0x8B3BD0U, 0x8B4092U, 0x8B5878U, + 0x8B69ACU, 0x8B7146U, 0x8B87C2U, 0x8B9F28U, 0x8BAEFCU, 0x8BB616U, 0x8BCD54U, 0x8BD5BEU, 0x8BE46AU, 0x8BFC80U, + 0x8C0236U, 0x8C1ADCU, 0x8C2B08U, 0x8C33E2U, 0x8C48A0U, 0x8C504AU, 0x8C619EU, 0x8C7974U, 0x8C8FF0U, 0x8C971AU, + 0x8CA6CEU, 0x8CBE24U, 0x8CC566U, 0x8CDD8CU, 0x8CEC58U, 0x8CF4B2U, 0x8D0150U, 0x8D19BAU, 0x8D286EU, 0x8D3084U, + 0x8D4BC6U, 0x8D532CU, 0x8D62F8U, 0x8D7A12U, 0x8D8C96U, 0x8D947CU, 0x8DA5A8U, 0x8DBD42U, 0x8DC600U, 0x8DDEEAU, + 0x8DEF3EU, 0x8DF7D4U, 0x8E04FAU, 0x8E1C10U, 0x8E2DC4U, 0x8E352EU, 0x8E4E6CU, 0x8E5686U, 0x8E6752U, 0x8E7FB8U, + 0x8E893CU, 0x8E91D6U, 0x8EA002U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB40U, 0x8EEA94U, 0x8EF27EU, 0x8F079CU, 0x8F1F76U, + 0x8F2EA2U, 0x8F3648U, 0x8F4D0AU, 0x8F55E0U, 0x8F6434U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B0U, 0x8FA364U, 0x8FBB8EU, + 0x8FC0CCU, 0x8FD826U, 0x8FE9F2U, 0x8FF118U, 0x900BC0U, 0x90132AU, 0x9022FEU, 0x903A14U, 0x904156U, 0x9059BCU, + 0x906868U, 0x907082U, 0x908606U, 0x909EECU, 0x90AF38U, 0x90B7D2U, 0x90CC90U, 0x90D47AU, 0x90E5AEU, 0x90FD44U, + 0x9108A6U, 0x91104CU, 0x912198U, 0x913972U, 0x914230U, 0x915ADAU, 0x916B0EU, 0x9173E4U, 0x918560U, 0x919D8AU, + 0x91AC5EU, 0x91B4B4U, 0x91CFF6U, 0x91D71CU, 0x91E6C8U, 0x91FE22U, 0x920D0CU, 0x9215E6U, 0x922432U, 0x923CD8U, + 0x92479AU, 0x925F70U, 0x926EA4U, 0x92764EU, 0x9280CAU, 0x929820U, 0x92A9F4U, 0x92B11EU, 0x92CA5CU, 0x92D2B6U, + 0x92E362U, 0x92FB88U, 0x930E6AU, 0x931680U, 0x932754U, 0x933FBEU, 0x9344FCU, 0x935C16U, 0x936DC2U, 0x937528U, + 0x9383ACU, 0x939B46U, 0x93AA92U, 0x93B278U, 0x93C93AU, 0x93D1D0U, 0x93E004U, 0x93F8EEU, 0x940658U, 0x941EB2U, + 0x942F66U, 0x94378CU, 0x944CCEU, 0x945424U, 0x9465F0U, 0x947D1AU, 0x948B9EU, 0x949374U, 0x94A2A0U, 0x94BA4AU, + 0x94C108U, 0x94D9E2U, 0x94E836U, 0x94F0DCU, 0x95053EU, 0x951DD4U, 0x952C00U, 0x9534EAU, 0x954FA8U, 0x955742U, + 0x956696U, 0x957E7CU, 0x9588F8U, 0x959012U, 0x95A1C6U, 0x95B92CU, 0x95C26EU, 0x95DA84U, 0x95EB50U, 0x95F3BAU, + 0x960094U, 0x96187EU, 0x9629AAU, 0x963140U, 0x964A02U, 0x9652E8U, 0x96633CU, 0x967BD6U, 0x968D52U, 0x9695B8U, + 0x96A46CU, 0x96BC86U, 0x96C7C4U, 0x96DF2EU, 0x96EEFAU, 0x96F610U, 0x9703F2U, 0x971B18U, 0x972ACCU, 0x973226U, + 0x974964U, 0x97518EU, 0x97605AU, 0x9778B0U, 0x978E34U, 0x9796DEU, 0x97A70AU, 0x97BFE0U, 0x97C4A2U, 0x97DC48U, + 0x97ED9CU, 0x97F576U, 0x98081AU, 0x9810F0U, 0x982124U, 0x9839CEU, 0x98428CU, 0x985A66U, 0x986BB2U, 0x987358U, + 0x9885DCU, 0x989D36U, 0x98ACE2U, 0x98B408U, 0x98CF4AU, 0x98D7A0U, 0x98E674U, 0x98FE9EU, 0x990B7CU, 0x991396U, + 0x992242U, 0x993AA8U, 0x9941EAU, 0x995900U, 0x9968D4U, 0x99703EU, 0x9986BAU, 0x999E50U, 0x99AF84U, 0x99B76EU, + 0x99CC2CU, 0x99D4C6U, 0x99E512U, 0x99FDF8U, 0x9A0ED6U, 0x9A163CU, 0x9A27E8U, 0x9A3F02U, 0x9A4440U, 0x9A5CAAU, + 0x9A6D7EU, 0x9A7594U, 0x9A8310U, 0x9A9BFAU, 0x9AAA2EU, 0x9AB2C4U, 0x9AC986U, 0x9AD16CU, 0x9AE0B8U, 0x9AF852U, + 0x9B0DB0U, 0x9B155AU, 0x9B248EU, 0x9B3C64U, 0x9B4726U, 0x9B5FCCU, 0x9B6E18U, 0x9B76F2U, 0x9B8076U, 0x9B989CU, + 0x9BA948U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20AU, 0x9BE3DEU, 0x9BFB34U, 0x9C0582U, 0x9C1D68U, 0x9C2CBCU, 0x9C3456U, + 0x9C4F14U, 0x9C57FEU, 0x9C662AU, 0x9C7EC0U, 0x9C8844U, 0x9C90AEU, 0x9CA17AU, 0x9CB990U, 0x9CC2D2U, 0x9CDA38U, + 0x9CEBECU, 0x9CF306U, 0x9D06E4U, 0x9D1E0EU, 0x9D2FDAU, 0x9D3730U, 0x9D4C72U, 0x9D5498U, 0x9D654CU, 0x9D7DA6U, + 0x9D8B22U, 0x9D93C8U, 0x9DA21CU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95EU, 0x9DE88AU, 0x9DF060U, 0x9E034EU, 0x9E1BA4U, + 0x9E2A70U, 0x9E329AU, 0x9E49D8U, 0x9E5132U, 0x9E60E6U, 0x9E780CU, 0x9E8E88U, 0x9E9662U, 0x9EA7B6U, 0x9EBF5CU, + 0x9EC41EU, 0x9EDCF4U, 0x9EED20U, 0x9EF5CAU, 0x9F0028U, 0x9F18C2U, 0x9F2916U, 0x9F31FCU, 0x9F4ABEU, 0x9F5254U, + 0x9F6380U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9504U, 0x9FA4D0U, 0x9FBC3AU, 0x9FC778U, 0x9FDF92U, 0x9FEE46U, 0x9FF6ACU, + 0xA0031CU, 0xA01BF6U, 0xA02A22U, 0xA032C8U, 0xA0498AU, 0xA05160U, 0xA060B4U, 0xA0785EU, 0xA08EDAU, 0xA09630U, + 0xA0A7E4U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA6U, 0xA0ED72U, 0xA0F598U, 0xA1007AU, 0xA11890U, 0xA12944U, 0xA131AEU, + 0xA14AECU, 0xA15206U, 0xA163D2U, 0xA17B38U, 0xA18DBCU, 0xA19556U, 0xA1A482U, 0xA1BC68U, 0xA1C72AU, 0xA1DFC0U, + 0xA1EE14U, 0xA1F6FEU, 0xA205D0U, 0xA21D3AU, 0xA22CEEU, 0xA23404U, 0xA24F46U, 0xA257ACU, 0xA26678U, 0xA27E92U, + 0xA28816U, 0xA290FCU, 0xA2A128U, 0xA2B9C2U, 0xA2C280U, 0xA2DA6AU, 0xA2EBBEU, 0xA2F354U, 0xA306B6U, 0xA31E5CU, + 0xA32F88U, 0xA33762U, 0xA34C20U, 0xA354CAU, 0xA3651EU, 0xA37DF4U, 0xA38B70U, 0xA3939AU, 0xA3A24EU, 0xA3BAA4U, + 0xA3C1E6U, 0xA3D90CU, 0xA3E8D8U, 0xA3F032U, 0xA40E84U, 0xA4166EU, 0xA427BAU, 0xA43F50U, 0xA44412U, 0xA45CF8U, + 0xA46D2CU, 0xA475C6U, 0xA48342U, 0xA49BA8U, 0xA4AA7CU, 0xA4B296U, 0xA4C9D4U, 0xA4D13EU, 0xA4E0EAU, 0xA4F800U, + 0xA50DE2U, 0xA51508U, 0xA524DCU, 0xA53C36U, 0xA54774U, 0xA55F9EU, 0xA56E4AU, 0xA576A0U, 0xA58024U, 0xA598CEU, + 0xA5A91AU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D258U, 0xA5E38CU, 0xA5FB66U, 0xA60848U, 0xA610A2U, 0xA62176U, 0xA6399CU, + 0xA642DEU, 0xA65A34U, 0xA66BE0U, 0xA6730AU, 0xA6858EU, 0xA69D64U, 0xA6ACB0U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F2U, + 0xA6E626U, 0xA6FECCU, 0xA70B2EU, 0xA713C4U, 0xA72210U, 0xA73AFAU, 0xA741B8U, 0xA75952U, 0xA76886U, 0xA7706CU, + 0xA786E8U, 0xA79E02U, 0xA7AFD6U, 0xA7B73CU, 0xA7CC7EU, 0xA7D494U, 0xA7E540U, 0xA7FDAAU, 0xA800C6U, 0xA8182CU, + 0xA829F8U, 0xA83112U, 0xA84A50U, 0xA852BAU, 0xA8636EU, 0xA87B84U, 0xA88D00U, 0xA895EAU, 0xA8A43EU, 0xA8BCD4U, + 0xA8C796U, 0xA8DF7CU, 0xA8EEA8U, 0xA8F642U, 0xA903A0U, 0xA91B4AU, 0xA92A9EU, 0xA93274U, 0xA94936U, 0xA951DCU, + 0xA96008U, 0xA978E2U, 0xA98E66U, 0xA9968CU, 0xA9A758U, 0xA9BFB2U, 0xA9C4F0U, 0xA9DC1AU, 0xA9EDCEU, 0xA9F524U, + 0xAA060AU, 0xAA1EE0U, 0xAA2F34U, 0xAA37DEU, 0xAA4C9CU, 0xAA5476U, 0xAA65A2U, 0xAA7D48U, 0xAA8BCCU, 0xAA9326U, + 0xAAA2F2U, 0xAABA18U, 0xAAC15AU, 0xAAD9B0U, 0xAAE864U, 0xAAF08EU, 0xAB056CU, 0xAB1D86U, 0xAB2C52U, 0xAB34B8U, + 0xAB4FFAU, 0xAB5710U, 0xAB66C4U, 0xAB7E2EU, 0xAB88AAU, 0xAB9040U, 0xABA194U, 0xABB97EU, 0xABC23CU, 0xABDAD6U, + 0xABEB02U, 0xABF3E8U, 0xAC0D5EU, 0xAC15B4U, 0xAC2460U, 0xAC3C8AU, 0xAC47C8U, 0xAC5F22U, 0xAC6EF6U, 0xAC761CU, + 0xAC8098U, 0xAC9872U, 0xACA9A6U, 0xACB14CU, 0xACCA0EU, 0xACD2E4U, 0xACE330U, 0xACFBDAU, 0xAD0E38U, 0xAD16D2U, + 0xAD2706U, 0xAD3FECU, 0xAD44AEU, 0xAD5C44U, 0xAD6D90U, 0xAD757AU, 0xAD83FEU, 0xAD9B14U, 0xADAAC0U, 0xADB22AU, + 0xADC968U, 0xADD182U, 0xADE056U, 0xADF8BCU, 0xAE0B92U, 0xAE1378U, 0xAE22ACU, 0xAE3A46U, 0xAE4104U, 0xAE59EEU, + 0xAE683AU, 0xAE70D0U, 0xAE8654U, 0xAE9EBEU, 0xAEAF6AU, 0xAEB780U, 0xAECCC2U, 0xAED428U, 0xAEE5FCU, 0xAEFD16U, + 0xAF08F4U, 0xAF101EU, 0xAF21CAU, 0xAF3920U, 0xAF4262U, 0xAF5A88U, 0xAF6B5CU, 0xAF73B6U, 0xAF8532U, 0xAF9DD8U, + 0xAFAC0CU, 0xAFB4E6U, 0xAFCFA4U, 0xAFD74EU, 0xAFE69AU, 0xAFFE70U, 0xB004A8U, 0xB01C42U, 0xB02D96U, 0xB0357CU, + 0xB04E3EU, 0xB056D4U, 0xB06700U, 0xB07FEAU, 0xB0896EU, 0xB09184U, 0xB0A050U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB12U, + 0xB0EAC6U, 0xB0F22CU, 0xB107CEU, 0xB11F24U, 0xB12EF0U, 0xB1361AU, 0xB14D58U, 0xB155B2U, 0xB16466U, 0xB17C8CU, + 0xB18A08U, 0xB192E2U, 0xB1A336U, 0xB1BBDCU, 0xB1C09EU, 0xB1D874U, 0xB1E9A0U, 0xB1F14AU, 0xB20264U, 0xB21A8EU, + 0xB22B5AU, 0xB233B0U, 0xB248F2U, 0xB25018U, 0xB261CCU, 0xB27926U, 0xB28FA2U, 0xB29748U, 0xB2A69CU, 0xB2BE76U, + 0xB2C534U, 0xB2DDDEU, 0xB2EC0AU, 0xB2F4E0U, 0xB30102U, 0xB319E8U, 0xB3283CU, 0xB330D6U, 0xB34B94U, 0xB3537EU, + 0xB362AAU, 0xB37A40U, 0xB38CC4U, 0xB3942EU, 0xB3A5FAU, 0xB3BD10U, 0xB3C652U, 0xB3DEB8U, 0xB3EF6CU, 0xB3F786U, + 0xB40930U, 0xB411DAU, 0xB4200EU, 0xB438E4U, 0xB443A6U, 0xB45B4CU, 0xB46A98U, 0xB47272U, 0xB484F6U, 0xB49C1CU, + 0xB4ADC8U, 0xB4B522U, 0xB4CE60U, 0xB4D68AU, 0xB4E75EU, 0xB4FFB4U, 0xB50A56U, 0xB512BCU, 0xB52368U, 0xB53B82U, + 0xB540C0U, 0xB5582AU, 0xB569FEU, 0xB57114U, 0xB58790U, 0xB59F7AU, 0xB5AEAEU, 0xB5B644U, 0xB5CD06U, 0xB5D5ECU, + 0xB5E438U, 0xB5FCD2U, 0xB60FFCU, 0xB61716U, 0xB626C2U, 0xB63E28U, 0xB6456AU, 0xB65D80U, 0xB66C54U, 0xB674BEU, + 0xB6823AU, 0xB69AD0U, 0xB6AB04U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D046U, 0xB6E192U, 0xB6F978U, 0xB70C9AU, 0xB71470U, + 0xB725A4U, 0xB73D4EU, 0xB7460CU, 0xB75EE6U, 0xB76F32U, 0xB777D8U, 0xB7815CU, 0xB799B6U, 0xB7A862U, 0xB7B088U, + 0xB7CBCAU, 0xB7D320U, 0xB7E2F4U, 0xB7FA1EU, 0xB80772U, 0xB81F98U, 0xB82E4CU, 0xB836A6U, 0xB84DE4U, 0xB8550EU, + 0xB864DAU, 0xB87C30U, 0xB88AB4U, 0xB8925EU, 0xB8A38AU, 0xB8BB60U, 0xB8C022U, 0xB8D8C8U, 0xB8E91CU, 0xB8F1F6U, + 0xB90414U, 0xB91CFEU, 0xB92D2AU, 0xB935C0U, 0xB94E82U, 0xB95668U, 0xB967BCU, 0xB97F56U, 0xB989D2U, 0xB99138U, + 0xB9A0ECU, 0xB9B806U, 0xB9C344U, 0xB9DBAEU, 0xB9EA7AU, 0xB9F290U, 0xBA01BEU, 0xBA1954U, 0xBA2880U, 0xBA306AU, + 0xBA4B28U, 0xBA53C2U, 0xBA6216U, 0xBA7AFCU, 0xBA8C78U, 0xBA9492U, 0xBAA546U, 0xBABDACU, 0xBAC6EEU, 0xBADE04U, + 0xBAEFD0U, 0xBAF73AU, 0xBB02D8U, 0xBB1A32U, 0xBB2BE6U, 0xBB330CU, 0xBB484EU, 0xBB50A4U, 0xBB6170U, 0xBB799AU, + 0xBB8F1EU, 0xBB97F4U, 0xBBA620U, 0xBBBECAU, 0xBBC588U, 0xBBDD62U, 0xBBECB6U, 0xBBF45CU, 0xBC0AEAU, 0xBC1200U, + 0xBC23D4U, 0xBC3B3EU, 0xBC407CU, 0xBC5896U, 0xBC6942U, 0xBC71A8U, 0xBC872CU, 0xBC9FC6U, 0xBCAE12U, 0xBCB6F8U, + 0xBCCDBAU, 0xBCD550U, 0xBCE484U, 0xBCFC6EU, 0xBD098CU, 0xBD1166U, 0xBD20B2U, 0xBD3858U, 0xBD431AU, 0xBD5BF0U, + 0xBD6A24U, 0xBD72CEU, 0xBD844AU, 0xBD9CA0U, 0xBDAD74U, 0xBDB59EU, 0xBDCEDCU, 0xBDD636U, 0xBDE7E2U, 0xBDFF08U, + 0xBE0C26U, 0xBE14CCU, 0xBE2518U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5AU, 0xBE6F8EU, 0xBE7764U, 0xBE81E0U, 0xBE990AU, + 0xBEA8DEU, 0xBEB034U, 0xBECB76U, 0xBED39CU, 0xBEE248U, 0xBEFAA2U, 0xBF0F40U, 0xBF17AAU, 0xBF267EU, 0xBF3E94U, + 0xBF45D6U, 0xBF5D3CU, 0xBF6CE8U, 0xBF7402U, 0xBF8286U, 0xBF9A6CU, 0xBFABB8U, 0xBFB352U, 0xBFC810U, 0xBFD0FAU, + 0xBFE12EU, 0xBFF9C4U, 0xC00A4EU, 0xC012A4U, 0xC02370U, 0xC03B9AU, 0xC040D8U, 0xC05832U, 0xC069E6U, 0xC0710CU, + 0xC08788U, 0xC09F62U, 0xC0AEB6U, 0xC0B65CU, 0xC0CD1EU, 0xC0D5F4U, 0xC0E420U, 0xC0FCCAU, 0xC10928U, 0xC111C2U, + 0xC12016U, 0xC138FCU, 0xC143BEU, 0xC15B54U, 0xC16A80U, 0xC1726AU, 0xC184EEU, 0xC19C04U, 0xC1ADD0U, 0xC1B53AU, + 0xC1CE78U, 0xC1D692U, 0xC1E746U, 0xC1FFACU, 0xC20C82U, 0xC21468U, 0xC225BCU, 0xC23D56U, 0xC24614U, 0xC25EFEU, + 0xC26F2AU, 0xC277C0U, 0xC28144U, 0xC299AEU, 0xC2A87AU, 0xC2B090U, 0xC2CBD2U, 0xC2D338U, 0xC2E2ECU, 0xC2FA06U, + 0xC30FE4U, 0xC3170EU, 0xC326DAU, 0xC33E30U, 0xC34572U, 0xC35D98U, 0xC36C4CU, 0xC374A6U, 0xC38222U, 0xC39AC8U, + 0xC3AB1CU, 0xC3B3F6U, 0xC3C8B4U, 0xC3D05EU, 0xC3E18AU, 0xC3F960U, 0xC407D6U, 0xC41F3CU, 0xC42EE8U, 0xC43602U, + 0xC44D40U, 0xC455AAU, 0xC4647EU, 0xC47C94U, 0xC48A10U, 0xC492FAU, 0xC4A32EU, 0xC4BBC4U, 0xC4C086U, 0xC4D86CU, + 0xC4E9B8U, 0xC4F152U, 0xC504B0U, 0xC51C5AU, 0xC52D8EU, 0xC53564U, 0xC54E26U, 0xC556CCU, 0xC56718U, 0xC57FF2U, + 0xC58976U, 0xC5919CU, 0xC5A048U, 0xC5B8A2U, 0xC5C3E0U, 0xC5DB0AU, 0xC5EADEU, 0xC5F234U, 0xC6011AU, 0xC619F0U, + 0xC62824U, 0xC630CEU, 0xC64B8CU, 0xC65366U, 0xC662B2U, 0xC67A58U, 0xC68CDCU, 0xC69436U, 0xC6A5E2U, 0xC6BD08U, + 0xC6C64AU, 0xC6DEA0U, 0xC6EF74U, 0xC6F79EU, 0xC7027CU, 0xC71A96U, 0xC72B42U, 0xC733A8U, 0xC748EAU, 0xC75000U, + 0xC761D4U, 0xC7793EU, 0xC78FBAU, 0xC79750U, 0xC7A684U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC6U, 0xC7EC12U, 0xC7F4F8U, + 0xC80994U, 0xC8117EU, 0xC820AAU, 0xC83840U, 0xC84302U, 0xC85BE8U, 0xC86A3CU, 0xC872D6U, 0xC88452U, 0xC89CB8U, + 0xC8AD6CU, 0xC8B586U, 0xC8CEC4U, 0xC8D62EU, 0xC8E7FAU, 0xC8FF10U, 0xC90AF2U, 0xC91218U, 0xC923CCU, 0xC93B26U, + 0xC94064U, 0xC9588EU, 0xC9695AU, 0xC971B0U, 0xC98734U, 0xC99FDEU, 0xC9AE0AU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D548U, + 0xC9E49CU, 0xC9FC76U, 0xCA0F58U, 0xCA17B2U, 0xCA2666U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D24U, 0xCA6CF0U, 0xCA741AU, + 0xCA829EU, 0xCA9A74U, 0xCAABA0U, 0xCAB34AU, 0xCAC808U, 0xCAD0E2U, 0xCAE136U, 0xCAF9DCU, 0xCB0C3EU, 0xCB14D4U, + 0xCB2500U, 0xCB3DEAU, 0xCB46A8U, 0xCB5E42U, 0xCB6F96U, 0xCB777CU, 0xCB81F8U, 0xCB9912U, 0xCBA8C6U, 0xCBB02CU, + 0xCBCB6EU, 0xCBD384U, 0xCBE250U, 0xCBFABAU, 0xCC040CU, 0xCC1CE6U, 0xCC2D32U, 0xCC35D8U, 0xCC4E9AU, 0xCC5670U, + 0xCC67A4U, 0xCC7F4EU, 0xCC89CAU, 0xCC9120U, 0xCCA0F4U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB6U, 0xCCEA62U, 0xCCF288U, + 0xCD076AU, 0xCD1F80U, 0xCD2E54U, 0xCD36BEU, 0xCD4DFCU, 0xCD5516U, 0xCD64C2U, 0xCD7C28U, 0xCD8AACU, 0xCD9246U, + 0xCDA392U, 0xCDBB78U, 0xCDC03AU, 0xCDD8D0U, 0xCDE904U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2AU, 0xCE2BFEU, 0xCE3314U, + 0xCE4856U, 0xCE50BCU, 0xCE6168U, 0xCE7982U, 0xCE8F06U, 0xCE97ECU, 0xCEA638U, 0xCEBED2U, 0xCEC590U, 0xCEDD7AU, + 0xCEECAEU, 0xCEF444U, 0xCF01A6U, 0xCF194CU, 0xCF2898U, 0xCF3072U, 0xCF4B30U, 0xCF53DAU, 0xCF620EU, 0xCF7AE4U, + 0xCF8C60U, 0xCF948AU, 0xCFA55EU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1CU, 0xCFEFC8U, 0xCFF722U, 0xD00DFAU, 0xD01510U, + 0xD024C4U, 0xD03C2EU, 0xD0476CU, 0xD05F86U, 0xD06E52U, 0xD076B8U, 0xD0803CU, 0xD098D6U, 0xD0A902U, 0xD0B1E8U, + 0xD0CAAAU, 0xD0D240U, 0xD0E394U, 0xD0FB7EU, 0xD10E9CU, 0xD11676U, 0xD127A2U, 0xD13F48U, 0xD1440AU, 0xD15CE0U, + 0xD16D34U, 0xD175DEU, 0xD1835AU, 0xD19BB0U, 0xD1AA64U, 0xD1B28EU, 0xD1C9CCU, 0xD1D126U, 0xD1E0F2U, 0xD1F818U, + 0xD20B36U, 0xD213DCU, 0xD22208U, 0xD23AE2U, 0xD241A0U, 0xD2594AU, 0xD2689EU, 0xD27074U, 0xD286F0U, 0xD29E1AU, + 0xD2AFCEU, 0xD2B724U, 0xD2CC66U, 0xD2D48CU, 0xD2E558U, 0xD2FDB2U, 0xD30850U, 0xD310BAU, 0xD3216EU, 0xD33984U, + 0xD342C6U, 0xD35A2CU, 0xD36BF8U, 0xD37312U, 0xD38596U, 0xD39D7CU, 0xD3ACA8U, 0xD3B442U, 0xD3CF00U, 0xD3D7EAU, + 0xD3E63EU, 0xD3FED4U, 0xD40062U, 0xD41888U, 0xD4295CU, 0xD431B6U, 0xD44AF4U, 0xD4521EU, 0xD463CAU, 0xD47B20U, + 0xD48DA4U, 0xD4954EU, 0xD4A49AU, 0xD4BC70U, 0xD4C732U, 0xD4DFD8U, 0xD4EE0CU, 0xD4F6E6U, 0xD50304U, 0xD51BEEU, + 0xD52A3AU, 0xD532D0U, 0xD54992U, 0xD55178U, 0xD560ACU, 0xD57846U, 0xD58EC2U, 0xD59628U, 0xD5A7FCU, 0xD5BF16U, + 0xD5C454U, 0xD5DCBEU, 0xD5ED6AU, 0xD5F580U, 0xD606AEU, 0xD61E44U, 0xD62F90U, 0xD6377AU, 0xD64C38U, 0xD654D2U, + 0xD66506U, 0xD67DECU, 0xD68B68U, 0xD69382U, 0xD6A256U, 0xD6BABCU, 0xD6C1FEU, 0xD6D914U, 0xD6E8C0U, 0xD6F02AU, + 0xD705C8U, 0xD71D22U, 0xD72CF6U, 0xD7341CU, 0xD74F5EU, 0xD757B4U, 0xD76660U, 0xD77E8AU, 0xD7880EU, 0xD790E4U, + 0xD7A130U, 0xD7B9DAU, 0xD7C298U, 0xD7DA72U, 0xD7EBA6U, 0xD7F34CU, 0xD80E20U, 0xD816CAU, 0xD8271EU, 0xD83FF4U, + 0xD844B6U, 0xD85C5CU, 0xD86D88U, 0xD87562U, 0xD883E6U, 0xD89B0CU, 0xD8AAD8U, 0xD8B232U, 0xD8C970U, 0xD8D19AU, + 0xD8E04EU, 0xD8F8A4U, 0xD90D46U, 0xD915ACU, 0xD92478U, 0xD93C92U, 0xD947D0U, 0xD95F3AU, 0xD96EEEU, 0xD97604U, + 0xD98080U, 0xD9986AU, 0xD9A9BEU, 0xD9B154U, 0xD9CA16U, 0xD9D2FCU, 0xD9E328U, 0xD9FBC2U, 0xDA08ECU, 0xDA1006U, + 0xDA21D2U, 0xDA3938U, 0xDA427AU, 0xDA5A90U, 0xDA6B44U, 0xDA73AEU, 0xDA852AU, 0xDA9DC0U, 0xDAAC14U, 0xDAB4FEU, + 0xDACFBCU, 0xDAD756U, 0xDAE682U, 0xDAFE68U, 0xDB0B8AU, 0xDB1360U, 0xDB22B4U, 0xDB3A5EU, 0xDB411CU, 0xDB59F6U, + 0xDB6822U, 0xDB70C8U, 0xDB864CU, 0xDB9EA6U, 0xDBAF72U, 0xDBB798U, 0xDBCCDAU, 0xDBD430U, 0xDBE5E4U, 0xDBFD0EU, + 0xDC03B8U, 0xDC1B52U, 0xDC2A86U, 0xDC326CU, 0xDC492EU, 0xDC51C4U, 0xDC6010U, 0xDC78FAU, 0xDC8E7EU, 0xDC9694U, + 0xDCA740U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC02U, 0xDCEDD6U, 0xDCF53CU, 0xDD00DEU, 0xDD1834U, 0xDD29E0U, 0xDD310AU, + 0xDD4A48U, 0xDD52A2U, 0xDD6376U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F2U, 0xDDA426U, 0xDDBCCCU, 0xDDC78EU, 0xDDDF64U, + 0xDDEEB0U, 0xDDF65AU, 0xDE0574U, 0xDE1D9EU, 0xDE2C4AU, 0xDE34A0U, 0xDE4FE2U, 0xDE5708U, 0xDE66DCU, 0xDE7E36U, + 0xDE88B2U, 0xDE9058U, 0xDEA18CU, 0xDEB966U, 0xDEC224U, 0xDEDACEU, 0xDEEB1AU, 0xDEF3F0U, 0xDF0612U, 0xDF1EF8U, + 0xDF2F2CU, 0xDF37C6U, 0xDF4C84U, 0xDF546EU, 0xDF65BAU, 0xDF7D50U, 0xDF8BD4U, 0xDF933EU, 0xDFA2EAU, 0xDFBA00U, + 0xDFC142U, 0xDFD9A8U, 0xDFE87CU, 0xDFF096U, 0xE00526U, 0xE01DCCU, 0xE02C18U, 0xE034F2U, 0xE04FB0U, 0xE0575AU, + 0xE0668EU, 0xE07E64U, 0xE088E0U, 0xE0900AU, 0xE0A1DEU, 0xE0B934U, 0xE0C276U, 0xE0DA9CU, 0xE0EB48U, 0xE0F3A2U, + 0xE10640U, 0xE11EAAU, 0xE12F7EU, 0xE13794U, 0xE14CD6U, 0xE1543CU, 0xE165E8U, 0xE17D02U, 0xE18B86U, 0xE1936CU, + 0xE1A2B8U, 0xE1BA52U, 0xE1C110U, 0xE1D9FAU, 0xE1E82EU, 0xE1F0C4U, 0xE203EAU, 0xE21B00U, 0xE22AD4U, 0xE2323EU, + 0xE2497CU, 0xE25196U, 0xE26042U, 0xE278A8U, 0xE28E2CU, 0xE296C6U, 0xE2A712U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC50U, + 0xE2ED84U, 0xE2F56EU, 0xE3008CU, 0xE31866U, 0xE329B2U, 0xE33158U, 0xE34A1AU, 0xE352F0U, 0xE36324U, 0xE37BCEU, + 0xE38D4AU, 0xE395A0U, 0xE3A474U, 0xE3BC9EU, 0xE3C7DCU, 0xE3DF36U, 0xE3EEE2U, 0xE3F608U, 0xE408BEU, 0xE41054U, + 0xE42180U, 0xE4396AU, 0xE44228U, 0xE45AC2U, 0xE46B16U, 0xE473FCU, 0xE48578U, 0xE49D92U, 0xE4AC46U, 0xE4B4ACU, + 0xE4CFEEU, 0xE4D704U, 0xE4E6D0U, 0xE4FE3AU, 0xE50BD8U, 0xE51332U, 0xE522E6U, 0xE53A0CU, 0xE5414EU, 0xE559A4U, + 0xE56870U, 0xE5709AU, 0xE5861EU, 0xE59EF4U, 0xE5AF20U, 0xE5B7CAU, 0xE5CC88U, 0xE5D462U, 0xE5E5B6U, 0xE5FD5CU, + 0xE60E72U, 0xE61698U, 0xE6274CU, 0xE63FA6U, 0xE644E4U, 0xE65C0EU, 0xE66DDAU, 0xE67530U, 0xE683B4U, 0xE69B5EU, + 0xE6AA8AU, 0xE6B260U, 0xE6C922U, 0xE6D1C8U, 0xE6E01CU, 0xE6F8F6U, 0xE70D14U, 0xE715FEU, 0xE7242AU, 0xE73CC0U, + 0xE74782U, 0xE75F68U, 0xE76EBCU, 0xE77656U, 0xE780D2U, 0xE79838U, 0xE7A9ECU, 0xE7B106U, 0xE7CA44U, 0xE7D2AEU, + 0xE7E37AU, 0xE7FB90U, 0xE806FCU, 0xE81E16U, 0xE82FC2U, 0xE83728U, 0xE84C6AU, 0xE85480U, 0xE86554U, 0xE87DBEU, + 0xE88B3AU, 0xE893D0U, 0xE8A204U, 0xE8BAEEU, 0xE8C1ACU, 0xE8D946U, 0xE8E892U, 0xE8F078U, 0xE9059AU, 0xE91D70U, + 0xE92CA4U, 0xE9344EU, 0xE94F0CU, 0xE957E6U, 0xE96632U, 0xE97ED8U, 0xE9885CU, 0xE990B6U, 0xE9A162U, 0xE9B988U, + 0xE9C2CAU, 0xE9DA20U, 0xE9EBF4U, 0xE9F31EU, 0xEA0030U, 0xEA18DAU, 0xEA290EU, 0xEA31E4U, 0xEA4AA6U, 0xEA524CU, + 0xEA6398U, 0xEA7B72U, 0xEA8DF6U, 0xEA951CU, 0xEAA4C8U, 0xEABC22U, 0xEAC760U, 0xEADF8AU, 0xEAEE5EU, 0xEAF6B4U, + 0xEB0356U, 0xEB1BBCU, 0xEB2A68U, 0xEB3282U, 0xEB49C0U, 0xEB512AU, 0xEB60FEU, 0xEB7814U, 0xEB8E90U, 0xEB967AU, + 0xEBA7AEU, 0xEBBF44U, 0xEBC406U, 0xEBDCECU, 0xEBED38U, 0xEBF5D2U, 0xEC0B64U, 0xEC138EU, 0xEC225AU, 0xEC3AB0U, + 0xEC41F2U, 0xEC5918U, 0xEC68CCU, 0xEC7026U, 0xEC86A2U, 0xEC9E48U, 0xECAF9CU, 0xECB776U, 0xECCC34U, 0xECD4DEU, + 0xECE50AU, 0xECFDE0U, 0xED0802U, 0xED10E8U, 0xED213CU, 0xED39D6U, 0xED4294U, 0xED5A7EU, 0xED6BAAU, 0xED7340U, + 0xED85C4U, 0xED9D2EU, 0xEDACFAU, 0xEDB410U, 0xEDCF52U, 0xEDD7B8U, 0xEDE66CU, 0xEDFE86U, 0xEE0DA8U, 0xEE1542U, + 0xEE2496U, 0xEE3C7CU, 0xEE473EU, 0xEE5FD4U, 0xEE6E00U, 0xEE76EAU, 0xEE806EU, 0xEE9884U, 0xEEA950U, 0xEEB1BAU, + 0xEECAF8U, 0xEED212U, 0xEEE3C6U, 0xEEFB2CU, 0xEF0ECEU, 0xEF1624U, 0xEF27F0U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB2U, + 0xEF6D66U, 0xEF758CU, 0xEF8308U, 0xEF9BE2U, 0xEFAA36U, 0xEFB2DCU, 0xEFC99EU, 0xEFD174U, 0xEFE0A0U, 0xEFF84AU, + 0xF00292U, 0xF01A78U, 0xF02BACU, 0xF03346U, 0xF04804U, 0xF050EEU, 0xF0613AU, 0xF079D0U, 0xF08F54U, 0xF097BEU, + 0xF0A66AU, 0xF0BE80U, 0xF0C5C2U, 0xF0DD28U, 0xF0ECFCU, 0xF0F416U, 0xF101F4U, 0xF1191EU, 0xF128CAU, 0xF13020U, + 0xF14B62U, 0xF15388U, 0xF1625CU, 0xF17AB6U, 0xF18C32U, 0xF194D8U, 0xF1A50CU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4EU, + 0xF1EF9AU, 0xF1F770U, 0xF2045EU, 0xF21CB4U, 0xF22D60U, 0xF2358AU, 0xF24EC8U, 0xF25622U, 0xF267F6U, 0xF27F1CU, + 0xF28998U, 0xF29172U, 0xF2A0A6U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE4U, 0xF2EA30U, 0xF2F2DAU, 0xF30738U, 0xF31FD2U, + 0xF32E06U, 0xF336ECU, 0xF34DAEU, 0xF35544U, 0xF36490U, 0xF37C7AU, 0xF38AFEU, 0xF39214U, 0xF3A3C0U, 0xF3BB2AU, + 0xF3C068U, 0xF3D882U, 0xF3E956U, 0xF3F1BCU, 0xF40F0AU, 0xF417E0U, 0xF42634U, 0xF43EDEU, 0xF4459CU, 0xF45D76U, + 0xF46CA2U, 0xF47448U, 0xF482CCU, 0xF49A26U, 0xF4ABF2U, 0xF4B318U, 0xF4C85AU, 0xF4D0B0U, 0xF4E164U, 0xF4F98EU, + 0xF50C6CU, 0xF51486U, 0xF52552U, 0xF53DB8U, 0xF546FAU, 0xF55E10U, 0xF56FC4U, 0xF5772EU, 0xF581AAU, 0xF59940U, + 0xF5A894U, 0xF5B07EU, 0xF5CB3CU, 0xF5D3D6U, 0xF5E202U, 0xF5FAE8U, 0xF609C6U, 0xF6112CU, 0xF620F8U, 0xF63812U, + 0xF64350U, 0xF65BBAU, 0xF66A6EU, 0xF67284U, 0xF68400U, 0xF69CEAU, 0xF6AD3EU, 0xF6B5D4U, 0xF6CE96U, 0xF6D67CU, + 0xF6E7A8U, 0xF6FF42U, 0xF70AA0U, 0xF7124AU, 0xF7239EU, 0xF73B74U, 0xF74036U, 0xF758DCU, 0xF76908U, 0xF771E2U, + 0xF78766U, 0xF79F8CU, 0xF7AE58U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51AU, 0xF7E4CEU, 0xF7FC24U, 0xF80148U, 0xF819A2U, + 0xF82876U, 0xF8309CU, 0xF84BDEU, 0xF85334U, 0xF862E0U, 0xF87A0AU, 0xF88C8EU, 0xF89464U, 0xF8A5B0U, 0xF8BD5AU, + 0xF8C618U, 0xF8DEF2U, 0xF8EF26U, 0xF8F7CCU, 0xF9022EU, 0xF91AC4U, 0xF92B10U, 0xF933FAU, 0xF948B8U, 0xF95052U, + 0xF96186U, 0xF9796CU, 0xF98FE8U, 0xF99702U, 0xF9A6D6U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD94U, 0xF9EC40U, 0xF9F4AAU, + 0xFA0784U, 0xFA1F6EU, 0xFA2EBAU, 0xFA3650U, 0xFA4D12U, 0xFA55F8U, 0xFA642CU, 0xFA7CC6U, 0xFA8A42U, 0xFA92A8U, + 0xFAA37CU, 0xFABB96U, 0xFAC0D4U, 0xFAD83EU, 0xFAE9EAU, 0xFAF100U, 0xFB04E2U, 0xFB1C08U, 0xFB2DDCU, 0xFB3536U, + 0xFB4E74U, 0xFB569EU, 0xFB674AU, 0xFB7FA0U, 0xFB8924U, 0xFB91CEU, 0xFBA01AU, 0xFBB8F0U, 0xFBC3B2U, 0xFBDB58U, + 0xFBEA8CU, 0xFBF266U, 0xFC0CD0U, 0xFC143AU, 0xFC25EEU, 0xFC3D04U, 0xFC4646U, 0xFC5EACU, 0xFC6F78U, 0xFC7792U, + 0xFC8116U, 0xFC99FCU, 0xFCA828U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36AU, 0xFCE2BEU, 0xFCFA54U, 0xFD0FB6U, 0xFD175CU, + 0xFD2688U, 0xFD3E62U, 0xFD4520U, 0xFD5DCAU, 0xFD6C1EU, 0xFD74F4U, 0xFD8270U, 0xFD9A9AU, 0xFDAB4EU, 0xFDB3A4U, + 0xFDC8E6U, 0xFDD00CU, 0xFDE1D8U, 0xFDF932U, 0xFE0A1CU, 0xFE12F6U, 0xFE2322U, 0xFE3BC8U, 0xFE408AU, 0xFE5860U, + 0xFE69B4U, 0xFE715EU, 0xFE87DAU, 0xFE9F30U, 0xFEAEE4U, 0xFEB60EU, 0xFECD4CU, 0xFED5A6U, 0xFEE472U, 0xFEFC98U, + 0xFF097AU, 0xFF1190U, 0xFF2044U, 0xFF38AEU, 0xFF43ECU, 0xFF5B06U, 0xFF6AD2U, 0xFF7238U, 0xFF84BCU, 0xFF9C56U, + 0xFFAD82U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C0U, 0xFFE714U, 0xFFFFFEU }; static const U32 ENCODING_TABLE_24128[] = { - 0x000000U, 0x0018EBU, 0x00293EU, 0x0031D5U, 0x004A97U, 0x00527CU, 0x0063A9U, 0x007B42U, 0x008DC6U, 0x00952DU, - 0x00A4F8U, 0x00BC13U, 0x00C751U, 0x00DFBAU, 0x00EE6FU, 0x00F684U, 0x010367U, 0x011B8CU, 0x012A59U, 0x0132B2U, - 0x0149F0U, 0x01511BU, 0x0160CEU, 0x017825U, 0x018EA1U, 0x01964AU, 0x01A79FU, 0x01BF74U, 0x01C436U, 0x01DCDDU, - 0x01ED08U, 0x01F5E3U, 0x0206CDU, 0x021E26U, 0x022FF3U, 0x023718U, 0x024C5AU, 0x0254B1U, 0x026564U, 0x027D8FU, - 0x028B0BU, 0x0293E0U, 0x02A235U, 0x02BADEU, 0x02C19CU, 0x02D977U, 0x02E8A2U, 0x02F049U, 0x0305AAU, 0x031D41U, - 0x032C94U, 0x03347FU, 0x034F3DU, 0x0357D6U, 0x036603U, 0x037EE8U, 0x03886CU, 0x039087U, 0x03A152U, 0x03B9B9U, - 0x03C2FBU, 0x03DA10U, 0x03EBC5U, 0x03F32EU, 0x040D99U, 0x041572U, 0x0424A7U, 0x043C4CU, 0x04470EU, 0x045FE5U, - 0x046E30U, 0x0476DBU, 0x04805FU, 0x0498B4U, 0x04A961U, 0x04B18AU, 0x04CAC8U, 0x04D223U, 0x04E3F6U, 0x04FB1DU, - 0x050EFEU, 0x051615U, 0x0527C0U, 0x053F2BU, 0x054469U, 0x055C82U, 0x056D57U, 0x0575BCU, 0x058338U, 0x059BD3U, - 0x05AA06U, 0x05B2EDU, 0x05C9AFU, 0x05D144U, 0x05E091U, 0x05F87AU, 0x060B54U, 0x0613BFU, 0x06226AU, 0x063A81U, - 0x0641C3U, 0x065928U, 0x0668FDU, 0x067016U, 0x068692U, 0x069E79U, 0x06AFACU, 0x06B747U, 0x06CC05U, 0x06D4EEU, - 0x06E53BU, 0x06FDD0U, 0x070833U, 0x0710D8U, 0x07210DU, 0x0739E6U, 0x0742A4U, 0x075A4FU, 0x076B9AU, 0x077371U, - 0x0785F5U, 0x079D1EU, 0x07ACCBU, 0x07B420U, 0x07CF62U, 0x07D789U, 0x07E65CU, 0x07FEB7U, 0x0803DAU, 0x081B31U, - 0x082AE4U, 0x08320FU, 0x08494DU, 0x0851A6U, 0x086073U, 0x087898U, 0x088E1CU, 0x0896F7U, 0x08A722U, 0x08BFC9U, - 0x08C48BU, 0x08DC60U, 0x08EDB5U, 0x08F55EU, 0x0900BDU, 0x091856U, 0x092983U, 0x093168U, 0x094A2AU, 0x0952C1U, - 0x096314U, 0x097BFFU, 0x098D7BU, 0x099590U, 0x09A445U, 0x09BCAEU, 0x09C7ECU, 0x09DF07U, 0x09EED2U, 0x09F639U, - 0x0A0517U, 0x0A1DFCU, 0x0A2C29U, 0x0A34C2U, 0x0A4F80U, 0x0A576BU, 0x0A66BEU, 0x0A7E55U, 0x0A88D1U, 0x0A903AU, - 0x0AA1EFU, 0x0AB904U, 0x0AC246U, 0x0ADAADU, 0x0AEB78U, 0x0AF393U, 0x0B0670U, 0x0B1E9BU, 0x0B2F4EU, 0x0B37A5U, - 0x0B4CE7U, 0x0B540CU, 0x0B65D9U, 0x0B7D32U, 0x0B8BB6U, 0x0B935DU, 0x0BA288U, 0x0BBA63U, 0x0BC121U, 0x0BD9CAU, - 0x0BE81FU, 0x0BF0F4U, 0x0C0E43U, 0x0C16A8U, 0x0C277DU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3FU, 0x0C6DEAU, 0x0C7501U, - 0x0C8385U, 0x0C9B6EU, 0x0CAABBU, 0x0CB250U, 0x0CC912U, 0x0CD1F9U, 0x0CE02CU, 0x0CF8C7U, 0x0D0D24U, 0x0D15CFU, - 0x0D241AU, 0x0D3CF1U, 0x0D47B3U, 0x0D5F58U, 0x0D6E8DU, 0x0D7666U, 0x0D80E2U, 0x0D9809U, 0x0DA9DCU, 0x0DB137U, - 0x0DCA75U, 0x0DD29EU, 0x0DE34BU, 0x0DFBA0U, 0x0E088EU, 0x0E1065U, 0x0E21B0U, 0x0E395BU, 0x0E4219U, 0x0E5AF2U, - 0x0E6B27U, 0x0E73CCU, 0x0E8548U, 0x0E9DA3U, 0x0EAC76U, 0x0EB49DU, 0x0ECFDFU, 0x0ED734U, 0x0EE6E1U, 0x0EFE0AU, - 0x0F0BE9U, 0x0F1302U, 0x0F22D7U, 0x0F3A3CU, 0x0F417EU, 0x0F5995U, 0x0F6840U, 0x0F70ABU, 0x0F862FU, 0x0F9EC4U, - 0x0FAF11U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD453U, 0x0FE586U, 0x0FFD6DU, 0x1007B4U, 0x101F5FU, 0x102E8AU, 0x103661U, - 0x104D23U, 0x1055C8U, 0x10641DU, 0x107CF6U, 0x108A72U, 0x109299U, 0x10A34CU, 0x10BBA7U, 0x10C0E5U, 0x10D80EU, - 0x10E9DBU, 0x10F130U, 0x1104D3U, 0x111C38U, 0x112DEDU, 0x113506U, 0x114E44U, 0x1156AFU, 0x11677AU, 0x117F91U, - 0x118915U, 0x1191FEU, 0x11A02BU, 0x11B8C0U, 0x11C382U, 0x11DB69U, 0x11EABCU, 0x11F257U, 0x120179U, 0x121992U, - 0x122847U, 0x1230ACU, 0x124BEEU, 0x125305U, 0x1262D0U, 0x127A3BU, 0x128CBFU, 0x129454U, 0x12A581U, 0x12BD6AU, - 0x12C628U, 0x12DEC3U, 0x12EF16U, 0x12F7FDU, 0x13021EU, 0x131AF5U, 0x132B20U, 0x1333CBU, 0x134889U, 0x135062U, - 0x1361B7U, 0x13795CU, 0x138FD8U, 0x139733U, 0x13A6E6U, 0x13BE0DU, 0x13C54FU, 0x13DDA4U, 0x13EC71U, 0x13F49AU, - 0x140A2DU, 0x1412C6U, 0x142313U, 0x143BF8U, 0x1440BAU, 0x145851U, 0x146984U, 0x14716FU, 0x1487EBU, 0x149F00U, - 0x14AED5U, 0x14B63EU, 0x14CD7CU, 0x14D597U, 0x14E442U, 0x14FCA9U, 0x15094AU, 0x1511A1U, 0x152074U, 0x15389FU, - 0x1543DDU, 0x155B36U, 0x156AE3U, 0x157208U, 0x15848CU, 0x159C67U, 0x15ADB2U, 0x15B559U, 0x15CE1BU, 0x15D6F0U, - 0x15E725U, 0x15FFCEU, 0x160CE0U, 0x16140BU, 0x1625DEU, 0x163D35U, 0x164677U, 0x165E9CU, 0x166F49U, 0x1677A2U, - 0x168126U, 0x1699CDU, 0x16A818U, 0x16B0F3U, 0x16CBB1U, 0x16D35AU, 0x16E28FU, 0x16FA64U, 0x170F87U, 0x17176CU, - 0x1726B9U, 0x173E52U, 0x174510U, 0x175DFBU, 0x176C2EU, 0x1774C5U, 0x178241U, 0x179AAAU, 0x17AB7FU, 0x17B394U, - 0x17C8D6U, 0x17D03DU, 0x17E1E8U, 0x17F903U, 0x18046EU, 0x181C85U, 0x182D50U, 0x1835BBU, 0x184EF9U, 0x185612U, - 0x1867C7U, 0x187F2CU, 0x1889A8U, 0x189143U, 0x18A096U, 0x18B87DU, 0x18C33FU, 0x18DBD4U, 0x18EA01U, 0x18F2EAU, - 0x190709U, 0x191FE2U, 0x192E37U, 0x1936DCU, 0x194D9EU, 0x195575U, 0x1964A0U, 0x197C4BU, 0x198ACFU, 0x199224U, - 0x19A3F1U, 0x19BB1AU, 0x19C058U, 0x19D8B3U, 0x19E966U, 0x19F18DU, 0x1A02A3U, 0x1A1A48U, 0x1A2B9DU, 0x1A3376U, - 0x1A4834U, 0x1A50DFU, 0x1A610AU, 0x1A79E1U, 0x1A8F65U, 0x1A978EU, 0x1AA65BU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD19U, - 0x1AECCCU, 0x1AF427U, 0x1B01C4U, 0x1B192FU, 0x1B28FAU, 0x1B3011U, 0x1B4B53U, 0x1B53B8U, 0x1B626DU, 0x1B7A86U, - 0x1B8C02U, 0x1B94E9U, 0x1BA53CU, 0x1BBDD7U, 0x1BC695U, 0x1BDE7EU, 0x1BEFABU, 0x1BF740U, 0x1C09F7U, 0x1C111CU, - 0x1C20C9U, 0x1C3822U, 0x1C4360U, 0x1C5B8BU, 0x1C6A5EU, 0x1C72B5U, 0x1C8431U, 0x1C9CDAU, 0x1CAD0FU, 0x1CB5E4U, - 0x1CCEA6U, 0x1CD64DU, 0x1CE798U, 0x1CFF73U, 0x1D0A90U, 0x1D127BU, 0x1D23AEU, 0x1D3B45U, 0x1D4007U, 0x1D58ECU, - 0x1D6939U, 0x1D71D2U, 0x1D8756U, 0x1D9FBDU, 0x1DAE68U, 0x1DB683U, 0x1DCDC1U, 0x1DD52AU, 0x1DE4FFU, 0x1DFC14U, - 0x1E0F3AU, 0x1E17D1U, 0x1E2604U, 0x1E3EEFU, 0x1E45ADU, 0x1E5D46U, 0x1E6C93U, 0x1E7478U, 0x1E82FCU, 0x1E9A17U, - 0x1EABC2U, 0x1EB329U, 0x1EC86BU, 0x1ED080U, 0x1EE155U, 0x1EF9BEU, 0x1F0C5DU, 0x1F14B6U, 0x1F2563U, 0x1F3D88U, - 0x1F46CAU, 0x1F5E21U, 0x1F6FF4U, 0x1F771FU, 0x1F819BU, 0x1F9970U, 0x1FA8A5U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E7U, - 0x1FE232U, 0x1FFAD9U, 0x200F68U, 0x201783U, 0x202656U, 0x203EBDU, 0x2045FFU, 0x205D14U, 0x206CC1U, 0x20742AU, - 0x2082AEU, 0x209A45U, 0x20AB90U, 0x20B37BU, 0x20C839U, 0x20D0D2U, 0x20E107U, 0x20F9ECU, 0x210C0FU, 0x2114E4U, - 0x212531U, 0x213DDAU, 0x214698U, 0x215E73U, 0x216FA6U, 0x21774DU, 0x2181C9U, 0x219922U, 0x21A8F7U, 0x21B01CU, - 0x21CB5EU, 0x21D3B5U, 0x21E260U, 0x21FA8BU, 0x2209A5U, 0x22114EU, 0x22209BU, 0x223870U, 0x224332U, 0x225BD9U, - 0x226A0CU, 0x2272E7U, 0x228463U, 0x229C88U, 0x22AD5DU, 0x22B5B6U, 0x22CEF4U, 0x22D61FU, 0x22E7CAU, 0x22FF21U, - 0x230AC2U, 0x231229U, 0x2323FCU, 0x233B17U, 0x234055U, 0x2358BEU, 0x23696BU, 0x237180U, 0x238704U, 0x239FEFU, - 0x23AE3AU, 0x23B6D1U, 0x23CD93U, 0x23D578U, 0x23E4ADU, 0x23FC46U, 0x2402F1U, 0x241A1AU, 0x242BCFU, 0x243324U, - 0x244866U, 0x24508DU, 0x246158U, 0x2479B3U, 0x248F37U, 0x2497DCU, 0x24A609U, 0x24BEE2U, 0x24C5A0U, 0x24DD4BU, - 0x24EC9EU, 0x24F475U, 0x250196U, 0x25197DU, 0x2528A8U, 0x253043U, 0x254B01U, 0x2553EAU, 0x25623FU, 0x257AD4U, - 0x258C50U, 0x2594BBU, 0x25A56EU, 0x25BD85U, 0x25C6C7U, 0x25DE2CU, 0x25EFF9U, 0x25F712U, 0x26043CU, 0x261CD7U, - 0x262D02U, 0x2635E9U, 0x264EABU, 0x265640U, 0x266795U, 0x267F7EU, 0x2689FAU, 0x269111U, 0x26A0C4U, 0x26B82FU, - 0x26C36DU, 0x26DB86U, 0x26EA53U, 0x26F2B8U, 0x27075BU, 0x271FB0U, 0x272E65U, 0x27368EU, 0x274DCCU, 0x275527U, - 0x2764F2U, 0x277C19U, 0x278A9DU, 0x279276U, 0x27A3A3U, 0x27BB48U, 0x27C00AU, 0x27D8E1U, 0x27E934U, 0x27F1DFU, - 0x280CB2U, 0x281459U, 0x28258CU, 0x283D67U, 0x284625U, 0x285ECEU, 0x286F1BU, 0x2877F0U, 0x288174U, 0x28999FU, - 0x28A84AU, 0x28B0A1U, 0x28CBE3U, 0x28D308U, 0x28E2DDU, 0x28FA36U, 0x290FD5U, 0x29173EU, 0x2926EBU, 0x293E00U, - 0x294542U, 0x295DA9U, 0x296C7CU, 0x297497U, 0x298213U, 0x299AF8U, 0x29AB2DU, 0x29B3C6U, 0x29C884U, 0x29D06FU, - 0x29E1BAU, 0x29F951U, 0x2A0A7FU, 0x2A1294U, 0x2A2341U, 0x2A3BAAU, 0x2A40E8U, 0x2A5803U, 0x2A69D6U, 0x2A713DU, - 0x2A87B9U, 0x2A9F52U, 0x2AAE87U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C5U, 0x2AE410U, 0x2AFCFBU, 0x2B0918U, 0x2B11F3U, - 0x2B2026U, 0x2B38CDU, 0x2B438FU, 0x2B5B64U, 0x2B6AB1U, 0x2B725AU, 0x2B84DEU, 0x2B9C35U, 0x2BADE0U, 0x2BB50BU, - 0x2BCE49U, 0x2BD6A2U, 0x2BE777U, 0x2BFF9CU, 0x2C012BU, 0x2C19C0U, 0x2C2815U, 0x2C30FEU, 0x2C4BBCU, 0x2C5357U, - 0x2C6282U, 0x2C7A69U, 0x2C8CEDU, 0x2C9406U, 0x2CA5D3U, 0x2CBD38U, 0x2CC67AU, 0x2CDE91U, 0x2CEF44U, 0x2CF7AFU, - 0x2D024CU, 0x2D1AA7U, 0x2D2B72U, 0x2D3399U, 0x2D48DBU, 0x2D5030U, 0x2D61E5U, 0x2D790EU, 0x2D8F8AU, 0x2D9761U, - 0x2DA6B4U, 0x2DBE5FU, 0x2DC51DU, 0x2DDDF6U, 0x2DEC23U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0DU, 0x2E2ED8U, 0x2E3633U, - 0x2E4D71U, 0x2E559AU, 0x2E644FU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CBU, 0x2EA31EU, 0x2EBBF5U, 0x2EC0B7U, 0x2ED85CU, - 0x2EE989U, 0x2EF162U, 0x2F0481U, 0x2F1C6AU, 0x2F2DBFU, 0x2F3554U, 0x2F4E16U, 0x2F56FDU, 0x2F6728U, 0x2F7FC3U, - 0x2F8947U, 0x2F91ACU, 0x2FA079U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3BU, 0x2FEAEEU, 0x2FF205U, 0x3008DCU, 0x301037U, - 0x3021E2U, 0x303909U, 0x30424BU, 0x305AA0U, 0x306B75U, 0x30739EU, 0x30851AU, 0x309DF1U, 0x30AC24U, 0x30B4CFU, - 0x30CF8DU, 0x30D766U, 0x30E6B3U, 0x30FE58U, 0x310BBBU, 0x311350U, 0x312285U, 0x313A6EU, 0x31412CU, 0x3159C7U, - 0x316812U, 0x3170F9U, 0x31867DU, 0x319E96U, 0x31AF43U, 0x31B7A8U, 0x31CCEAU, 0x31D401U, 0x31E5D4U, 0x31FD3FU, - 0x320E11U, 0x3216FAU, 0x32272FU, 0x323FC4U, 0x324486U, 0x325C6DU, 0x326DB8U, 0x327553U, 0x3283D7U, 0x329B3CU, - 0x32AAE9U, 0x32B202U, 0x32C940U, 0x32D1ABU, 0x32E07EU, 0x32F895U, 0x330D76U, 0x33159DU, 0x332448U, 0x333CA3U, - 0x3347E1U, 0x335F0AU, 0x336EDFU, 0x337634U, 0x3380B0U, 0x33985BU, 0x33A98EU, 0x33B165U, 0x33CA27U, 0x33D2CCU, - 0x33E319U, 0x33FBF2U, 0x340545U, 0x341DAEU, 0x342C7BU, 0x343490U, 0x344FD2U, 0x345739U, 0x3466ECU, 0x347E07U, - 0x348883U, 0x349068U, 0x34A1BDU, 0x34B956U, 0x34C214U, 0x34DAFFU, 0x34EB2AU, 0x34F3C1U, 0x350622U, 0x351EC9U, - 0x352F1CU, 0x3537F7U, 0x354CB5U, 0x35545EU, 0x35658BU, 0x357D60U, 0x358BE4U, 0x35930FU, 0x35A2DAU, 0x35BA31U, - 0x35C173U, 0x35D998U, 0x35E84DU, 0x35F0A6U, 0x360388U, 0x361B63U, 0x362AB6U, 0x36325DU, 0x36491FU, 0x3651F4U, - 0x366021U, 0x3678CAU, 0x368E4EU, 0x3696A5U, 0x36A770U, 0x36BF9BU, 0x36C4D9U, 0x36DC32U, 0x36EDE7U, 0x36F50CU, - 0x3700EFU, 0x371804U, 0x3729D1U, 0x37313AU, 0x374A78U, 0x375293U, 0x376346U, 0x377BADU, 0x378D29U, 0x3795C2U, - 0x37A417U, 0x37BCFCU, 0x37C7BEU, 0x37DF55U, 0x37EE80U, 0x37F66BU, 0x380B06U, 0x3813EDU, 0x382238U, 0x383AD3U, - 0x384191U, 0x38597AU, 0x3868AFU, 0x387044U, 0x3886C0U, 0x389E2BU, 0x38AFFEU, 0x38B715U, 0x38CC57U, 0x38D4BCU, - 0x38E569U, 0x38FD82U, 0x390861U, 0x39108AU, 0x39215FU, 0x3939B4U, 0x3942F6U, 0x395A1DU, 0x396BC8U, 0x397323U, - 0x3985A7U, 0x399D4CU, 0x39AC99U, 0x39B472U, 0x39CF30U, 0x39D7DBU, 0x39E60EU, 0x39FEE5U, 0x3A0DCBU, 0x3A1520U, - 0x3A24F5U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB7U, 0x3A6E62U, 0x3A7689U, 0x3A800DU, 0x3A98E6U, 0x3AA933U, 0x3AB1D8U, - 0x3ACA9AU, 0x3AD271U, 0x3AE3A4U, 0x3AFB4FU, 0x3B0EACU, 0x3B1647U, 0x3B2792U, 0x3B3F79U, 0x3B443BU, 0x3B5CD0U, - 0x3B6D05U, 0x3B75EEU, 0x3B836AU, 0x3B9B81U, 0x3BAA54U, 0x3BB2BFU, 0x3BC9FDU, 0x3BD116U, 0x3BE0C3U, 0x3BF828U, - 0x3C069FU, 0x3C1E74U, 0x3C2FA1U, 0x3C374AU, 0x3C4C08U, 0x3C54E3U, 0x3C6536U, 0x3C7DDDU, 0x3C8B59U, 0x3C93B2U, - 0x3CA267U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD925U, 0x3CE8F0U, 0x3CF01BU, 0x3D05F8U, 0x3D1D13U, 0x3D2CC6U, 0x3D342DU, - 0x3D4F6FU, 0x3D5784U, 0x3D6651U, 0x3D7EBAU, 0x3D883EU, 0x3D90D5U, 0x3DA100U, 0x3DB9EBU, 0x3DC2A9U, 0x3DDA42U, - 0x3DEB97U, 0x3DF37CU, 0x3E0052U, 0x3E18B9U, 0x3E296CU, 0x3E3187U, 0x3E4AC5U, 0x3E522EU, 0x3E63FBU, 0x3E7B10U, - 0x3E8D94U, 0x3E957FU, 0x3EA4AAU, 0x3EBC41U, 0x3EC703U, 0x3EDFE8U, 0x3EEE3DU, 0x3EF6D6U, 0x3F0335U, 0x3F1BDEU, - 0x3F2A0BU, 0x3F32E0U, 0x3F49A2U, 0x3F5149U, 0x3F609CU, 0x3F7877U, 0x3F8EF3U, 0x3F9618U, 0x3FA7CDU, 0x3FBF26U, - 0x3FC464U, 0x3FDC8FU, 0x3FED5AU, 0x3FF5B1U, 0x40063BU, 0x401ED0U, 0x402F05U, 0x4037EEU, 0x404CACU, 0x405447U, - 0x406592U, 0x407D79U, 0x408BFDU, 0x409316U, 0x40A2C3U, 0x40BA28U, 0x40C16AU, 0x40D981U, 0x40E854U, 0x40F0BFU, - 0x41055CU, 0x411DB7U, 0x412C62U, 0x413489U, 0x414FCBU, 0x415720U, 0x4166F5U, 0x417E1EU, 0x41889AU, 0x419071U, - 0x41A1A4U, 0x41B94FU, 0x41C20DU, 0x41DAE6U, 0x41EB33U, 0x41F3D8U, 0x4200F6U, 0x42181DU, 0x4229C8U, 0x423123U, - 0x424A61U, 0x42528AU, 0x42635FU, 0x427BB4U, 0x428D30U, 0x4295DBU, 0x42A40EU, 0x42BCE5U, 0x42C7A7U, 0x42DF4CU, - 0x42EE99U, 0x42F672U, 0x430391U, 0x431B7AU, 0x432AAFU, 0x433244U, 0x434906U, 0x4351EDU, 0x436038U, 0x4378D3U, - 0x438E57U, 0x4396BCU, 0x43A769U, 0x43BF82U, 0x43C4C0U, 0x43DC2BU, 0x43EDFEU, 0x43F515U, 0x440BA2U, 0x441349U, - 0x44229CU, 0x443A77U, 0x444135U, 0x4459DEU, 0x44680BU, 0x4470E0U, 0x448664U, 0x449E8FU, 0x44AF5AU, 0x44B7B1U, - 0x44CCF3U, 0x44D418U, 0x44E5CDU, 0x44FD26U, 0x4508C5U, 0x45102EU, 0x4521FBU, 0x453910U, 0x454252U, 0x455AB9U, - 0x456B6CU, 0x457387U, 0x458503U, 0x459DE8U, 0x45AC3DU, 0x45B4D6U, 0x45CF94U, 0x45D77FU, 0x45E6AAU, 0x45FE41U, - 0x460D6FU, 0x461584U, 0x462451U, 0x463CBAU, 0x4647F8U, 0x465F13U, 0x466EC6U, 0x46762DU, 0x4680A9U, 0x469842U, - 0x46A997U, 0x46B17CU, 0x46CA3EU, 0x46D2D5U, 0x46E300U, 0x46FBEBU, 0x470E08U, 0x4716E3U, 0x472736U, 0x473FDDU, - 0x47449FU, 0x475C74U, 0x476DA1U, 0x47754AU, 0x4783CEU, 0x479B25U, 0x47AAF0U, 0x47B21BU, 0x47C959U, 0x47D1B2U, - 0x47E067U, 0x47F88CU, 0x4805E1U, 0x481D0AU, 0x482CDFU, 0x483434U, 0x484F76U, 0x48579DU, 0x486648U, 0x487EA3U, - 0x488827U, 0x4890CCU, 0x48A119U, 0x48B9F2U, 0x48C2B0U, 0x48DA5BU, 0x48EB8EU, 0x48F365U, 0x490686U, 0x491E6DU, - 0x492FB8U, 0x493753U, 0x494C11U, 0x4954FAU, 0x49652FU, 0x497DC4U, 0x498B40U, 0x4993ABU, 0x49A27EU, 0x49BA95U, - 0x49C1D7U, 0x49D93CU, 0x49E8E9U, 0x49F002U, 0x4A032CU, 0x4A1BC7U, 0x4A2A12U, 0x4A32F9U, 0x4A49BBU, 0x4A5150U, - 0x4A6085U, 0x4A786EU, 0x4A8EEAU, 0x4A9601U, 0x4AA7D4U, 0x4ABF3FU, 0x4AC47DU, 0x4ADC96U, 0x4AED43U, 0x4AF5A8U, - 0x4B004BU, 0x4B18A0U, 0x4B2975U, 0x4B319EU, 0x4B4ADCU, 0x4B5237U, 0x4B63E2U, 0x4B7B09U, 0x4B8D8DU, 0x4B9566U, - 0x4BA4B3U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF1U, 0x4BEE24U, 0x4BF6CFU, 0x4C0878U, 0x4C1093U, 0x4C2146U, 0x4C39ADU, - 0x4C42EFU, 0x4C5A04U, 0x4C6BD1U, 0x4C733AU, 0x4C85BEU, 0x4C9D55U, 0x4CAC80U, 0x4CB46BU, 0x4CCF29U, 0x4CD7C2U, - 0x4CE617U, 0x4CFEFCU, 0x4D0B1FU, 0x4D13F4U, 0x4D2221U, 0x4D3ACAU, 0x4D4188U, 0x4D5963U, 0x4D68B6U, 0x4D705DU, - 0x4D86D9U, 0x4D9E32U, 0x4DAFE7U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A5U, 0x4DE570U, 0x4DFD9BU, 0x4E0EB5U, 0x4E165EU, - 0x4E278BU, 0x4E3F60U, 0x4E4422U, 0x4E5CC9U, 0x4E6D1CU, 0x4E75F7U, 0x4E8373U, 0x4E9B98U, 0x4EAA4DU, 0x4EB2A6U, - 0x4EC9E4U, 0x4ED10FU, 0x4EE0DAU, 0x4EF831U, 0x4F0DD2U, 0x4F1539U, 0x4F24ECU, 0x4F3C07U, 0x4F4745U, 0x4F5FAEU, - 0x4F6E7BU, 0x4F7690U, 0x4F8014U, 0x4F98FFU, 0x4FA92AU, 0x4FB1C1U, 0x4FCA83U, 0x4FD268U, 0x4FE3BDU, 0x4FFB56U, - 0x50018FU, 0x501964U, 0x5028B1U, 0x50305AU, 0x504B18U, 0x5053F3U, 0x506226U, 0x507ACDU, 0x508C49U, 0x5094A2U, - 0x50A577U, 0x50BD9CU, 0x50C6DEU, 0x50DE35U, 0x50EFE0U, 0x50F70BU, 0x5102E8U, 0x511A03U, 0x512BD6U, 0x51333DU, - 0x51487FU, 0x515094U, 0x516141U, 0x5179AAU, 0x518F2EU, 0x5197C5U, 0x51A610U, 0x51BEFBU, 0x51C5B9U, 0x51DD52U, - 0x51EC87U, 0x51F46CU, 0x520742U, 0x521FA9U, 0x522E7CU, 0x523697U, 0x524DD5U, 0x52553EU, 0x5264EBU, 0x527C00U, - 0x528A84U, 0x52926FU, 0x52A3BAU, 0x52BB51U, 0x52C013U, 0x52D8F8U, 0x52E92DU, 0x52F1C6U, 0x530425U, 0x531CCEU, - 0x532D1BU, 0x5335F0U, 0x534EB2U, 0x535659U, 0x53678CU, 0x537F67U, 0x5389E3U, 0x539108U, 0x53A0DDU, 0x53B836U, - 0x53C374U, 0x53DB9FU, 0x53EA4AU, 0x53F2A1U, 0x540C16U, 0x5414FDU, 0x542528U, 0x543DC3U, 0x544681U, 0x545E6AU, - 0x546FBFU, 0x547754U, 0x5481D0U, 0x54993BU, 0x54A8EEU, 0x54B005U, 0x54CB47U, 0x54D3ACU, 0x54E279U, 0x54FA92U, - 0x550F71U, 0x55179AU, 0x55264FU, 0x553EA4U, 0x5545E6U, 0x555D0DU, 0x556CD8U, 0x557433U, 0x5582B7U, 0x559A5CU, - 0x55AB89U, 0x55B362U, 0x55C820U, 0x55D0CBU, 0x55E11EU, 0x55F9F5U, 0x560ADBU, 0x561230U, 0x5623E5U, 0x563B0EU, - 0x56404CU, 0x5658A7U, 0x566972U, 0x567199U, 0x56871DU, 0x569FF6U, 0x56AE23U, 0x56B6C8U, 0x56CD8AU, 0x56D561U, - 0x56E4B4U, 0x56FC5FU, 0x5709BCU, 0x571157U, 0x572082U, 0x573869U, 0x57432BU, 0x575BC0U, 0x576A15U, 0x5772FEU, - 0x57847AU, 0x579C91U, 0x57AD44U, 0x57B5AFU, 0x57CEEDU, 0x57D606U, 0x57E7D3U, 0x57FF38U, 0x580255U, 0x581ABEU, - 0x582B6BU, 0x583380U, 0x5848C2U, 0x585029U, 0x5861FCU, 0x587917U, 0x588F93U, 0x589778U, 0x58A6ADU, 0x58BE46U, - 0x58C504U, 0x58DDEFU, 0x58EC3AU, 0x58F4D1U, 0x590132U, 0x5919D9U, 0x59280CU, 0x5930E7U, 0x594BA5U, 0x59534EU, - 0x59629BU, 0x597A70U, 0x598CF4U, 0x59941FU, 0x59A5CAU, 0x59BD21U, 0x59C663U, 0x59DE88U, 0x59EF5DU, 0x59F7B6U, - 0x5A0498U, 0x5A1C73U, 0x5A2DA6U, 0x5A354DU, 0x5A4E0FU, 0x5A56E4U, 0x5A6731U, 0x5A7FDAU, 0x5A895EU, 0x5A91B5U, - 0x5AA060U, 0x5AB88BU, 0x5AC3C9U, 0x5ADB22U, 0x5AEAF7U, 0x5AF21CU, 0x5B07FFU, 0x5B1F14U, 0x5B2EC1U, 0x5B362AU, - 0x5B4D68U, 0x5B5583U, 0x5B6456U, 0x5B7CBDU, 0x5B8A39U, 0x5B92D2U, 0x5BA307U, 0x5BBBECU, 0x5BC0AEU, 0x5BD845U, - 0x5BE990U, 0x5BF17BU, 0x5C0FCCU, 0x5C1727U, 0x5C26F2U, 0x5C3E19U, 0x5C455BU, 0x5C5DB0U, 0x5C6C65U, 0x5C748EU, - 0x5C820AU, 0x5C9AE1U, 0x5CAB34U, 0x5CB3DFU, 0x5CC89DU, 0x5CD076U, 0x5CE1A3U, 0x5CF948U, 0x5D0CABU, 0x5D1440U, - 0x5D2595U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED7U, 0x5D6F02U, 0x5D77E9U, 0x5D816DU, 0x5D9986U, 0x5DA853U, 0x5DB0B8U, - 0x5DCBFAU, 0x5DD311U, 0x5DE2C4U, 0x5DFA2FU, 0x5E0901U, 0x5E11EAU, 0x5E203FU, 0x5E38D4U, 0x5E4396U, 0x5E5B7DU, - 0x5E6AA8U, 0x5E7243U, 0x5E84C7U, 0x5E9C2CU, 0x5EADF9U, 0x5EB512U, 0x5ECE50U, 0x5ED6BBU, 0x5EE76EU, 0x5EFF85U, - 0x5F0A66U, 0x5F128DU, 0x5F2358U, 0x5F3BB3U, 0x5F40F1U, 0x5F581AU, 0x5F69CFU, 0x5F7124U, 0x5F87A0U, 0x5F9F4BU, - 0x5FAE9EU, 0x5FB675U, 0x5FCD37U, 0x5FD5DCU, 0x5FE409U, 0x5FFCE2U, 0x600953U, 0x6011B8U, 0x60206DU, 0x603886U, - 0x6043C4U, 0x605B2FU, 0x606AFAU, 0x607211U, 0x608495U, 0x609C7EU, 0x60ADABU, 0x60B540U, 0x60CE02U, 0x60D6E9U, - 0x60E73CU, 0x60FFD7U, 0x610A34U, 0x6112DFU, 0x61230AU, 0x613BE1U, 0x6140A3U, 0x615848U, 0x61699DU, 0x617176U, - 0x6187F2U, 0x619F19U, 0x61AECCU, 0x61B627U, 0x61CD65U, 0x61D58EU, 0x61E45BU, 0x61FCB0U, 0x620F9EU, 0x621775U, - 0x6226A0U, 0x623E4BU, 0x624509U, 0x625DE2U, 0x626C37U, 0x6274DCU, 0x628258U, 0x629AB3U, 0x62AB66U, 0x62B38DU, - 0x62C8CFU, 0x62D024U, 0x62E1F1U, 0x62F91AU, 0x630CF9U, 0x631412U, 0x6325C7U, 0x633D2CU, 0x63466EU, 0x635E85U, - 0x636F50U, 0x6377BBU, 0x63813FU, 0x6399D4U, 0x63A801U, 0x63B0EAU, 0x63CBA8U, 0x63D343U, 0x63E296U, 0x63FA7DU, - 0x6404CAU, 0x641C21U, 0x642DF4U, 0x64351FU, 0x644E5DU, 0x6456B6U, 0x646763U, 0x647F88U, 0x64890CU, 0x6491E7U, - 0x64A032U, 0x64B8D9U, 0x64C39BU, 0x64DB70U, 0x64EAA5U, 0x64F24EU, 0x6507ADU, 0x651F46U, 0x652E93U, 0x653678U, - 0x654D3AU, 0x6555D1U, 0x656404U, 0x657CEFU, 0x658A6BU, 0x659280U, 0x65A355U, 0x65BBBEU, 0x65C0FCU, 0x65D817U, - 0x65E9C2U, 0x65F129U, 0x660207U, 0x661AECU, 0x662B39U, 0x6633D2U, 0x664890U, 0x66507BU, 0x6661AEU, 0x667945U, - 0x668FC1U, 0x66972AU, 0x66A6FFU, 0x66BE14U, 0x66C556U, 0x66DDBDU, 0x66EC68U, 0x66F483U, 0x670160U, 0x67198BU, - 0x67285EU, 0x6730B5U, 0x674BF7U, 0x67531CU, 0x6762C9U, 0x677A22U, 0x678CA6U, 0x67944DU, 0x67A598U, 0x67BD73U, - 0x67C631U, 0x67DEDAU, 0x67EF0FU, 0x67F7E4U, 0x680A89U, 0x681262U, 0x6823B7U, 0x683B5CU, 0x68401EU, 0x6858F5U, - 0x686920U, 0x6871CBU, 0x68874FU, 0x689FA4U, 0x68AE71U, 0x68B69AU, 0x68CDD8U, 0x68D533U, 0x68E4E6U, 0x68FC0DU, - 0x6909EEU, 0x691105U, 0x6920D0U, 0x69383BU, 0x694379U, 0x695B92U, 0x696A47U, 0x6972ACU, 0x698428U, 0x699CC3U, - 0x69AD16U, 0x69B5FDU, 0x69CEBFU, 0x69D654U, 0x69E781U, 0x69FF6AU, 0x6A0C44U, 0x6A14AFU, 0x6A257AU, 0x6A3D91U, - 0x6A46D3U, 0x6A5E38U, 0x6A6FEDU, 0x6A7706U, 0x6A8182U, 0x6A9969U, 0x6AA8BCU, 0x6AB057U, 0x6ACB15U, 0x6AD3FEU, - 0x6AE22BU, 0x6AFAC0U, 0x6B0F23U, 0x6B17C8U, 0x6B261DU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5FU, 0x6B6C8AU, 0x6B7461U, - 0x6B82E5U, 0x6B9A0EU, 0x6BABDBU, 0x6BB330U, 0x6BC872U, 0x6BD099U, 0x6BE14CU, 0x6BF9A7U, 0x6C0710U, 0x6C1FFBU, - 0x6C2E2EU, 0x6C36C5U, 0x6C4D87U, 0x6C556CU, 0x6C64B9U, 0x6C7C52U, 0x6C8AD6U, 0x6C923DU, 0x6CA3E8U, 0x6CBB03U, - 0x6CC041U, 0x6CD8AAU, 0x6CE97FU, 0x6CF194U, 0x6D0477U, 0x6D1C9CU, 0x6D2D49U, 0x6D35A2U, 0x6D4EE0U, 0x6D560BU, - 0x6D67DEU, 0x6D7F35U, 0x6D89B1U, 0x6D915AU, 0x6DA08FU, 0x6DB864U, 0x6DC326U, 0x6DDBCDU, 0x6DEA18U, 0x6DF2F3U, - 0x6E01DDU, 0x6E1936U, 0x6E28E3U, 0x6E3008U, 0x6E4B4AU, 0x6E53A1U, 0x6E6274U, 0x6E7A9FU, 0x6E8C1BU, 0x6E94F0U, - 0x6EA525U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE67U, 0x6EEFB2U, 0x6EF759U, 0x6F02BAU, 0x6F1A51U, 0x6F2B84U, 0x6F336FU, - 0x6F482DU, 0x6F50C6U, 0x6F6113U, 0x6F79F8U, 0x6F8F7CU, 0x6F9797U, 0x6FA642U, 0x6FBEA9U, 0x6FC5EBU, 0x6FDD00U, - 0x6FECD5U, 0x6FF43EU, 0x700EE7U, 0x70160CU, 0x7027D9U, 0x703F32U, 0x704470U, 0x705C9BU, 0x706D4EU, 0x7075A5U, - 0x708321U, 0x709BCAU, 0x70AA1FU, 0x70B2F4U, 0x70C9B6U, 0x70D15DU, 0x70E088U, 0x70F863U, 0x710D80U, 0x71156BU, - 0x7124BEU, 0x713C55U, 0x714717U, 0x715FFCU, 0x716E29U, 0x7176C2U, 0x718046U, 0x7198ADU, 0x71A978U, 0x71B193U, - 0x71CAD1U, 0x71D23AU, 0x71E3EFU, 0x71FB04U, 0x72082AU, 0x7210C1U, 0x722114U, 0x7239FFU, 0x7242BDU, 0x725A56U, - 0x726B83U, 0x727368U, 0x7285ECU, 0x729D07U, 0x72ACD2U, 0x72B439U, 0x72CF7BU, 0x72D790U, 0x72E645U, 0x72FEAEU, - 0x730B4DU, 0x7313A6U, 0x732273U, 0x733A98U, 0x7341DAU, 0x735931U, 0x7368E4U, 0x73700FU, 0x73868BU, 0x739E60U, - 0x73AFB5U, 0x73B75EU, 0x73CC1CU, 0x73D4F7U, 0x73E522U, 0x73FDC9U, 0x74037EU, 0x741B95U, 0x742A40U, 0x7432ABU, - 0x7449E9U, 0x745102U, 0x7460D7U, 0x74783CU, 0x748EB8U, 0x749653U, 0x74A786U, 0x74BF6DU, 0x74C42FU, 0x74DCC4U, - 0x74ED11U, 0x74F5FAU, 0x750019U, 0x7518F2U, 0x752927U, 0x7531CCU, 0x754A8EU, 0x755265U, 0x7563B0U, 0x757B5BU, - 0x758DDFU, 0x759534U, 0x75A4E1U, 0x75BC0AU, 0x75C748U, 0x75DFA3U, 0x75EE76U, 0x75F69DU, 0x7605B3U, 0x761D58U, - 0x762C8DU, 0x763466U, 0x764F24U, 0x7657CFU, 0x76661AU, 0x767EF1U, 0x768875U, 0x76909EU, 0x76A14BU, 0x76B9A0U, - 0x76C2E2U, 0x76DA09U, 0x76EBDCU, 0x76F337U, 0x7706D4U, 0x771E3FU, 0x772FEAU, 0x773701U, 0x774C43U, 0x7754A8U, - 0x77657DU, 0x777D96U, 0x778B12U, 0x7793F9U, 0x77A22CU, 0x77BAC7U, 0x77C185U, 0x77D96EU, 0x77E8BBU, 0x77F050U, - 0x780D3DU, 0x7815D6U, 0x782403U, 0x783CE8U, 0x7847AAU, 0x785F41U, 0x786E94U, 0x78767FU, 0x7880FBU, 0x789810U, - 0x78A9C5U, 0x78B12EU, 0x78CA6CU, 0x78D287U, 0x78E352U, 0x78FBB9U, 0x790E5AU, 0x7916B1U, 0x792764U, 0x793F8FU, - 0x7944CDU, 0x795C26U, 0x796DF3U, 0x797518U, 0x79839CU, 0x799B77U, 0x79AAA2U, 0x79B249U, 0x79C90BU, 0x79D1E0U, - 0x79E035U, 0x79F8DEU, 0x7A0BF0U, 0x7A131BU, 0x7A22CEU, 0x7A3A25U, 0x7A4167U, 0x7A598CU, 0x7A6859U, 0x7A70B2U, - 0x7A8636U, 0x7A9EDDU, 0x7AAF08U, 0x7AB7E3U, 0x7ACCA1U, 0x7AD44AU, 0x7AE59FU, 0x7AFD74U, 0x7B0897U, 0x7B107CU, - 0x7B21A9U, 0x7B3942U, 0x7B4200U, 0x7B5AEBU, 0x7B6B3EU, 0x7B73D5U, 0x7B8551U, 0x7B9DBAU, 0x7BAC6FU, 0x7BB484U, - 0x7BCFC6U, 0x7BD72DU, 0x7BE6F8U, 0x7BFE13U, 0x7C00A4U, 0x7C184FU, 0x7C299AU, 0x7C3171U, 0x7C4A33U, 0x7C52D8U, - 0x7C630DU, 0x7C7BE6U, 0x7C8D62U, 0x7C9589U, 0x7CA45CU, 0x7CBCB7U, 0x7CC7F5U, 0x7CDF1EU, 0x7CEECBU, 0x7CF620U, - 0x7D03C3U, 0x7D1B28U, 0x7D2AFDU, 0x7D3216U, 0x7D4954U, 0x7D51BFU, 0x7D606AU, 0x7D7881U, 0x7D8E05U, 0x7D96EEU, - 0x7DA73BU, 0x7DBFD0U, 0x7DC492U, 0x7DDC79U, 0x7DEDACU, 0x7DF547U, 0x7E0669U, 0x7E1E82U, 0x7E2F57U, 0x7E37BCU, - 0x7E4CFEU, 0x7E5415U, 0x7E65C0U, 0x7E7D2BU, 0x7E8BAFU, 0x7E9344U, 0x7EA291U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D3U, - 0x7EE806U, 0x7EF0EDU, 0x7F050EU, 0x7F1DE5U, 0x7F2C30U, 0x7F34DBU, 0x7F4F99U, 0x7F5772U, 0x7F66A7U, 0x7F7E4CU, - 0x7F88C8U, 0x7F9023U, 0x7FA1F6U, 0x7FB91DU, 0x7FC25FU, 0x7FDAB4U, 0x7FEB61U, 0x7FF38AU, 0x800C75U, 0x80149EU, - 0x80254BU, 0x803DA0U, 0x8046E2U, 0x805E09U, 0x806FDCU, 0x807737U, 0x8081B3U, 0x809958U, 0x80A88DU, 0x80B066U, - 0x80CB24U, 0x80D3CFU, 0x80E21AU, 0x80FAF1U, 0x810F12U, 0x8117F9U, 0x81262CU, 0x813EC7U, 0x814585U, 0x815D6EU, - 0x816CBBU, 0x817450U, 0x8182D4U, 0x819A3FU, 0x81ABEAU, 0x81B301U, 0x81C843U, 0x81D0A8U, 0x81E17DU, 0x81F996U, - 0x820AB8U, 0x821253U, 0x822386U, 0x823B6DU, 0x82402FU, 0x8258C4U, 0x826911U, 0x8271FAU, 0x82877EU, 0x829F95U, - 0x82AE40U, 0x82B6ABU, 0x82CDE9U, 0x82D502U, 0x82E4D7U, 0x82FC3CU, 0x8309DFU, 0x831134U, 0x8320E1U, 0x83380AU, - 0x834348U, 0x835BA3U, 0x836A76U, 0x83729DU, 0x838419U, 0x839CF2U, 0x83AD27U, 0x83B5CCU, 0x83CE8EU, 0x83D665U, - 0x83E7B0U, 0x83FF5BU, 0x8401ECU, 0x841907U, 0x8428D2U, 0x843039U, 0x844B7BU, 0x845390U, 0x846245U, 0x847AAEU, - 0x848C2AU, 0x8494C1U, 0x84A514U, 0x84BDFFU, 0x84C6BDU, 0x84DE56U, 0x84EF83U, 0x84F768U, 0x85028BU, 0x851A60U, - 0x852BB5U, 0x85335EU, 0x85481CU, 0x8550F7U, 0x856122U, 0x8579C9U, 0x858F4DU, 0x8597A6U, 0x85A673U, 0x85BE98U, - 0x85C5DAU, 0x85DD31U, 0x85ECE4U, 0x85F40FU, 0x860721U, 0x861FCAU, 0x862E1FU, 0x8636F4U, 0x864DB6U, 0x86555DU, - 0x866488U, 0x867C63U, 0x868AE7U, 0x86920CU, 0x86A3D9U, 0x86BB32U, 0x86C070U, 0x86D89BU, 0x86E94EU, 0x86F1A5U, - 0x870446U, 0x871CADU, 0x872D78U, 0x873593U, 0x874ED1U, 0x87563AU, 0x8767EFU, 0x877F04U, 0x878980U, 0x87916BU, - 0x87A0BEU, 0x87B855U, 0x87C317U, 0x87DBFCU, 0x87EA29U, 0x87F2C2U, 0x880FAFU, 0x881744U, 0x882691U, 0x883E7AU, - 0x884538U, 0x885DD3U, 0x886C06U, 0x8874EDU, 0x888269U, 0x889A82U, 0x88AB57U, 0x88B3BCU, 0x88C8FEU, 0x88D015U, - 0x88E1C0U, 0x88F92BU, 0x890CC8U, 0x891423U, 0x8925F6U, 0x893D1DU, 0x89465FU, 0x895EB4U, 0x896F61U, 0x89778AU, - 0x89810EU, 0x8999E5U, 0x89A830U, 0x89B0DBU, 0x89CB99U, 0x89D372U, 0x89E2A7U, 0x89FA4CU, 0x8A0962U, 0x8A1189U, - 0x8A205CU, 0x8A38B7U, 0x8A43F5U, 0x8A5B1EU, 0x8A6ACBU, 0x8A7220U, 0x8A84A4U, 0x8A9C4FU, 0x8AAD9AU, 0x8AB571U, - 0x8ACE33U, 0x8AD6D8U, 0x8AE70DU, 0x8AFFE6U, 0x8B0A05U, 0x8B12EEU, 0x8B233BU, 0x8B3BD0U, 0x8B4092U, 0x8B5879U, - 0x8B69ACU, 0x8B7147U, 0x8B87C3U, 0x8B9F28U, 0x8BAEFDU, 0x8BB616U, 0x8BCD54U, 0x8BD5BFU, 0x8BE46AU, 0x8BFC81U, - 0x8C0236U, 0x8C1ADDU, 0x8C2B08U, 0x8C33E3U, 0x8C48A1U, 0x8C504AU, 0x8C619FU, 0x8C7974U, 0x8C8FF0U, 0x8C971BU, - 0x8CA6CEU, 0x8CBE25U, 0x8CC567U, 0x8CDD8CU, 0x8CEC59U, 0x8CF4B2U, 0x8D0151U, 0x8D19BAU, 0x8D286FU, 0x8D3084U, - 0x8D4BC6U, 0x8D532DU, 0x8D62F8U, 0x8D7A13U, 0x8D8C97U, 0x8D947CU, 0x8DA5A9U, 0x8DBD42U, 0x8DC600U, 0x8DDEEBU, - 0x8DEF3EU, 0x8DF7D5U, 0x8E04FBU, 0x8E1C10U, 0x8E2DC5U, 0x8E352EU, 0x8E4E6CU, 0x8E5687U, 0x8E6752U, 0x8E7FB9U, - 0x8E893DU, 0x8E91D6U, 0x8EA003U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB41U, 0x8EEA94U, 0x8EF27FU, 0x8F079CU, 0x8F1F77U, - 0x8F2EA2U, 0x8F3649U, 0x8F4D0BU, 0x8F55E0U, 0x8F6435U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B1U, 0x8FA364U, 0x8FBB8FU, - 0x8FC0CDU, 0x8FD826U, 0x8FE9F3U, 0x8FF118U, 0x900BC1U, 0x90132AU, 0x9022FFU, 0x903A14U, 0x904156U, 0x9059BDU, - 0x906868U, 0x907083U, 0x908607U, 0x909EECU, 0x90AF39U, 0x90B7D2U, 0x90CC90U, 0x90D47BU, 0x90E5AEU, 0x90FD45U, - 0x9108A6U, 0x91104DU, 0x912198U, 0x913973U, 0x914231U, 0x915ADAU, 0x916B0FU, 0x9173E4U, 0x918560U, 0x919D8BU, - 0x91AC5EU, 0x91B4B5U, 0x91CFF7U, 0x91D71CU, 0x91E6C9U, 0x91FE22U, 0x920D0CU, 0x9215E7U, 0x922432U, 0x923CD9U, - 0x92479BU, 0x925F70U, 0x926EA5U, 0x92764EU, 0x9280CAU, 0x929821U, 0x92A9F4U, 0x92B11FU, 0x92CA5DU, 0x92D2B6U, - 0x92E363U, 0x92FB88U, 0x930E6BU, 0x931680U, 0x932755U, 0x933FBEU, 0x9344FCU, 0x935C17U, 0x936DC2U, 0x937529U, - 0x9383ADU, 0x939B46U, 0x93AA93U, 0x93B278U, 0x93C93AU, 0x93D1D1U, 0x93E004U, 0x93F8EFU, 0x940658U, 0x941EB3U, - 0x942F66U, 0x94378DU, 0x944CCFU, 0x945424U, 0x9465F1U, 0x947D1AU, 0x948B9EU, 0x949375U, 0x94A2A0U, 0x94BA4BU, - 0x94C109U, 0x94D9E2U, 0x94E837U, 0x94F0DCU, 0x95053FU, 0x951DD4U, 0x952C01U, 0x9534EAU, 0x954FA8U, 0x955743U, - 0x956696U, 0x957E7DU, 0x9588F9U, 0x959012U, 0x95A1C7U, 0x95B92CU, 0x95C26EU, 0x95DA85U, 0x95EB50U, 0x95F3BBU, - 0x960095U, 0x96187EU, 0x9629ABU, 0x963140U, 0x964A02U, 0x9652E9U, 0x96633CU, 0x967BD7U, 0x968D53U, 0x9695B8U, - 0x96A46DU, 0x96BC86U, 0x96C7C4U, 0x96DF2FU, 0x96EEFAU, 0x96F611U, 0x9703F2U, 0x971B19U, 0x972ACCU, 0x973227U, - 0x974965U, 0x97518EU, 0x97605BU, 0x9778B0U, 0x978E34U, 0x9796DFU, 0x97A70AU, 0x97BFE1U, 0x97C4A3U, 0x97DC48U, - 0x97ED9DU, 0x97F576U, 0x98081BU, 0x9810F0U, 0x982125U, 0x9839CEU, 0x98428CU, 0x985A67U, 0x986BB2U, 0x987359U, - 0x9885DDU, 0x989D36U, 0x98ACE3U, 0x98B408U, 0x98CF4AU, 0x98D7A1U, 0x98E674U, 0x98FE9FU, 0x990B7CU, 0x991397U, - 0x992242U, 0x993AA9U, 0x9941EBU, 0x995900U, 0x9968D5U, 0x99703EU, 0x9986BAU, 0x999E51U, 0x99AF84U, 0x99B76FU, - 0x99CC2DU, 0x99D4C6U, 0x99E513U, 0x99FDF8U, 0x9A0ED6U, 0x9A163DU, 0x9A27E8U, 0x9A3F03U, 0x9A4441U, 0x9A5CAAU, - 0x9A6D7FU, 0x9A7594U, 0x9A8310U, 0x9A9BFBU, 0x9AAA2EU, 0x9AB2C5U, 0x9AC987U, 0x9AD16CU, 0x9AE0B9U, 0x9AF852U, - 0x9B0DB1U, 0x9B155AU, 0x9B248FU, 0x9B3C64U, 0x9B4726U, 0x9B5FCDU, 0x9B6E18U, 0x9B76F3U, 0x9B8077U, 0x9B989CU, - 0x9BA949U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20BU, 0x9BE3DEU, 0x9BFB35U, 0x9C0582U, 0x9C1D69U, 0x9C2CBCU, 0x9C3457U, - 0x9C4F15U, 0x9C57FEU, 0x9C662BU, 0x9C7EC0U, 0x9C8844U, 0x9C90AFU, 0x9CA17AU, 0x9CB991U, 0x9CC2D3U, 0x9CDA38U, - 0x9CEBEDU, 0x9CF306U, 0x9D06E5U, 0x9D1E0EU, 0x9D2FDBU, 0x9D3730U, 0x9D4C72U, 0x9D5499U, 0x9D654CU, 0x9D7DA7U, - 0x9D8B23U, 0x9D93C8U, 0x9DA21DU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95FU, 0x9DE88AU, 0x9DF061U, 0x9E034FU, 0x9E1BA4U, - 0x9E2A71U, 0x9E329AU, 0x9E49D8U, 0x9E5133U, 0x9E60E6U, 0x9E780DU, 0x9E8E89U, 0x9E9662U, 0x9EA7B7U, 0x9EBF5CU, - 0x9EC41EU, 0x9EDCF5U, 0x9EED20U, 0x9EF5CBU, 0x9F0028U, 0x9F18C3U, 0x9F2916U, 0x9F31FDU, 0x9F4ABFU, 0x9F5254U, - 0x9F6381U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9505U, 0x9FA4D0U, 0x9FBC3BU, 0x9FC779U, 0x9FDF92U, 0x9FEE47U, 0x9FF6ACU, - 0xA0031DU, 0xA01BF6U, 0xA02A23U, 0xA032C8U, 0xA0498AU, 0xA05161U, 0xA060B4U, 0xA0785FU, 0xA08EDBU, 0xA09630U, - 0xA0A7E5U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA7U, 0xA0ED72U, 0xA0F599U, 0xA1007AU, 0xA11891U, 0xA12944U, 0xA131AFU, - 0xA14AEDU, 0xA15206U, 0xA163D3U, 0xA17B38U, 0xA18DBCU, 0xA19557U, 0xA1A482U, 0xA1BC69U, 0xA1C72BU, 0xA1DFC0U, - 0xA1EE15U, 0xA1F6FEU, 0xA205D0U, 0xA21D3BU, 0xA22CEEU, 0xA23405U, 0xA24F47U, 0xA257ACU, 0xA26679U, 0xA27E92U, - 0xA28816U, 0xA290FDU, 0xA2A128U, 0xA2B9C3U, 0xA2C281U, 0xA2DA6AU, 0xA2EBBFU, 0xA2F354U, 0xA306B7U, 0xA31E5CU, - 0xA32F89U, 0xA33762U, 0xA34C20U, 0xA354CBU, 0xA3651EU, 0xA37DF5U, 0xA38B71U, 0xA3939AU, 0xA3A24FU, 0xA3BAA4U, - 0xA3C1E6U, 0xA3D90DU, 0xA3E8D8U, 0xA3F033U, 0xA40E84U, 0xA4166FU, 0xA427BAU, 0xA43F51U, 0xA44413U, 0xA45CF8U, - 0xA46D2DU, 0xA475C6U, 0xA48342U, 0xA49BA9U, 0xA4AA7CU, 0xA4B297U, 0xA4C9D5U, 0xA4D13EU, 0xA4E0EBU, 0xA4F800U, - 0xA50DE3U, 0xA51508U, 0xA524DDU, 0xA53C36U, 0xA54774U, 0xA55F9FU, 0xA56E4AU, 0xA576A1U, 0xA58025U, 0xA598CEU, - 0xA5A91BU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D259U, 0xA5E38CU, 0xA5FB67U, 0xA60849U, 0xA610A2U, 0xA62177U, 0xA6399CU, - 0xA642DEU, 0xA65A35U, 0xA66BE0U, 0xA6730BU, 0xA6858FU, 0xA69D64U, 0xA6ACB1U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F3U, - 0xA6E626U, 0xA6FECDU, 0xA70B2EU, 0xA713C5U, 0xA72210U, 0xA73AFBU, 0xA741B9U, 0xA75952U, 0xA76887U, 0xA7706CU, - 0xA786E8U, 0xA79E03U, 0xA7AFD6U, 0xA7B73DU, 0xA7CC7FU, 0xA7D494U, 0xA7E541U, 0xA7FDAAU, 0xA800C7U, 0xA8182CU, - 0xA829F9U, 0xA83112U, 0xA84A50U, 0xA852BBU, 0xA8636EU, 0xA87B85U, 0xA88D01U, 0xA895EAU, 0xA8A43FU, 0xA8BCD4U, - 0xA8C796U, 0xA8DF7DU, 0xA8EEA8U, 0xA8F643U, 0xA903A0U, 0xA91B4BU, 0xA92A9EU, 0xA93275U, 0xA94937U, 0xA951DCU, - 0xA96009U, 0xA978E2U, 0xA98E66U, 0xA9968DU, 0xA9A758U, 0xA9BFB3U, 0xA9C4F1U, 0xA9DC1AU, 0xA9EDCFU, 0xA9F524U, - 0xAA060AU, 0xAA1EE1U, 0xAA2F34U, 0xAA37DFU, 0xAA4C9DU, 0xAA5476U, 0xAA65A3U, 0xAA7D48U, 0xAA8BCCU, 0xAA9327U, - 0xAAA2F2U, 0xAABA19U, 0xAAC15BU, 0xAAD9B0U, 0xAAE865U, 0xAAF08EU, 0xAB056DU, 0xAB1D86U, 0xAB2C53U, 0xAB34B8U, - 0xAB4FFAU, 0xAB5711U, 0xAB66C4U, 0xAB7E2FU, 0xAB88ABU, 0xAB9040U, 0xABA195U, 0xABB97EU, 0xABC23CU, 0xABDAD7U, - 0xABEB02U, 0xABF3E9U, 0xAC0D5EU, 0xAC15B5U, 0xAC2460U, 0xAC3C8BU, 0xAC47C9U, 0xAC5F22U, 0xAC6EF7U, 0xAC761CU, - 0xAC8098U, 0xAC9873U, 0xACA9A6U, 0xACB14DU, 0xACCA0FU, 0xACD2E4U, 0xACE331U, 0xACFBDAU, 0xAD0E39U, 0xAD16D2U, - 0xAD2707U, 0xAD3FECU, 0xAD44AEU, 0xAD5C45U, 0xAD6D90U, 0xAD757BU, 0xAD83FFU, 0xAD9B14U, 0xADAAC1U, 0xADB22AU, - 0xADC968U, 0xADD183U, 0xADE056U, 0xADF8BDU, 0xAE0B93U, 0xAE1378U, 0xAE22ADU, 0xAE3A46U, 0xAE4104U, 0xAE59EFU, - 0xAE683AU, 0xAE70D1U, 0xAE8655U, 0xAE9EBEU, 0xAEAF6BU, 0xAEB780U, 0xAECCC2U, 0xAED429U, 0xAEE5FCU, 0xAEFD17U, - 0xAF08F4U, 0xAF101FU, 0xAF21CAU, 0xAF3921U, 0xAF4263U, 0xAF5A88U, 0xAF6B5DU, 0xAF73B6U, 0xAF8532U, 0xAF9DD9U, - 0xAFAC0CU, 0xAFB4E7U, 0xAFCFA5U, 0xAFD74EU, 0xAFE69BU, 0xAFFE70U, 0xB004A9U, 0xB01C42U, 0xB02D97U, 0xB0357CU, - 0xB04E3EU, 0xB056D5U, 0xB06700U, 0xB07FEBU, 0xB0896FU, 0xB09184U, 0xB0A051U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB13U, - 0xB0EAC6U, 0xB0F22DU, 0xB107CEU, 0xB11F25U, 0xB12EF0U, 0xB1361BU, 0xB14D59U, 0xB155B2U, 0xB16467U, 0xB17C8CU, - 0xB18A08U, 0xB192E3U, 0xB1A336U, 0xB1BBDDU, 0xB1C09FU, 0xB1D874U, 0xB1E9A1U, 0xB1F14AU, 0xB20264U, 0xB21A8FU, - 0xB22B5AU, 0xB233B1U, 0xB248F3U, 0xB25018U, 0xB261CDU, 0xB27926U, 0xB28FA2U, 0xB29749U, 0xB2A69CU, 0xB2BE77U, - 0xB2C535U, 0xB2DDDEU, 0xB2EC0BU, 0xB2F4E0U, 0xB30103U, 0xB319E8U, 0xB3283DU, 0xB330D6U, 0xB34B94U, 0xB3537FU, - 0xB362AAU, 0xB37A41U, 0xB38CC5U, 0xB3942EU, 0xB3A5FBU, 0xB3BD10U, 0xB3C652U, 0xB3DEB9U, 0xB3EF6CU, 0xB3F787U, - 0xB40930U, 0xB411DBU, 0xB4200EU, 0xB438E5U, 0xB443A7U, 0xB45B4CU, 0xB46A99U, 0xB47272U, 0xB484F6U, 0xB49C1DU, - 0xB4ADC8U, 0xB4B523U, 0xB4CE61U, 0xB4D68AU, 0xB4E75FU, 0xB4FFB4U, 0xB50A57U, 0xB512BCU, 0xB52369U, 0xB53B82U, - 0xB540C0U, 0xB5582BU, 0xB569FEU, 0xB57115U, 0xB58791U, 0xB59F7AU, 0xB5AEAFU, 0xB5B644U, 0xB5CD06U, 0xB5D5EDU, - 0xB5E438U, 0xB5FCD3U, 0xB60FFDU, 0xB61716U, 0xB626C3U, 0xB63E28U, 0xB6456AU, 0xB65D81U, 0xB66C54U, 0xB674BFU, - 0xB6823BU, 0xB69AD0U, 0xB6AB05U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D047U, 0xB6E192U, 0xB6F979U, 0xB70C9AU, 0xB71471U, - 0xB725A4U, 0xB73D4FU, 0xB7460DU, 0xB75EE6U, 0xB76F33U, 0xB777D8U, 0xB7815CU, 0xB799B7U, 0xB7A862U, 0xB7B089U, - 0xB7CBCBU, 0xB7D320U, 0xB7E2F5U, 0xB7FA1EU, 0xB80773U, 0xB81F98U, 0xB82E4DU, 0xB836A6U, 0xB84DE4U, 0xB8550FU, - 0xB864DAU, 0xB87C31U, 0xB88AB5U, 0xB8925EU, 0xB8A38BU, 0xB8BB60U, 0xB8C022U, 0xB8D8C9U, 0xB8E91CU, 0xB8F1F7U, - 0xB90414U, 0xB91CFFU, 0xB92D2AU, 0xB935C1U, 0xB94E83U, 0xB95668U, 0xB967BDU, 0xB97F56U, 0xB989D2U, 0xB99139U, - 0xB9A0ECU, 0xB9B807U, 0xB9C345U, 0xB9DBAEU, 0xB9EA7BU, 0xB9F290U, 0xBA01BEU, 0xBA1955U, 0xBA2880U, 0xBA306BU, - 0xBA4B29U, 0xBA53C2U, 0xBA6217U, 0xBA7AFCU, 0xBA8C78U, 0xBA9493U, 0xBAA546U, 0xBABDADU, 0xBAC6EFU, 0xBADE04U, - 0xBAEFD1U, 0xBAF73AU, 0xBB02D9U, 0xBB1A32U, 0xBB2BE7U, 0xBB330CU, 0xBB484EU, 0xBB50A5U, 0xBB6170U, 0xBB799BU, - 0xBB8F1FU, 0xBB97F4U, 0xBBA621U, 0xBBBECAU, 0xBBC588U, 0xBBDD63U, 0xBBECB6U, 0xBBF45DU, 0xBC0AEAU, 0xBC1201U, - 0xBC23D4U, 0xBC3B3FU, 0xBC407DU, 0xBC5896U, 0xBC6943U, 0xBC71A8U, 0xBC872CU, 0xBC9FC7U, 0xBCAE12U, 0xBCB6F9U, - 0xBCCDBBU, 0xBCD550U, 0xBCE485U, 0xBCFC6EU, 0xBD098DU, 0xBD1166U, 0xBD20B3U, 0xBD3858U, 0xBD431AU, 0xBD5BF1U, - 0xBD6A24U, 0xBD72CFU, 0xBD844BU, 0xBD9CA0U, 0xBDAD75U, 0xBDB59EU, 0xBDCEDCU, 0xBDD637U, 0xBDE7E2U, 0xBDFF09U, - 0xBE0C27U, 0xBE14CCU, 0xBE2519U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5BU, 0xBE6F8EU, 0xBE7765U, 0xBE81E1U, 0xBE990AU, - 0xBEA8DFU, 0xBEB034U, 0xBECB76U, 0xBED39DU, 0xBEE248U, 0xBEFAA3U, 0xBF0F40U, 0xBF17ABU, 0xBF267EU, 0xBF3E95U, - 0xBF45D7U, 0xBF5D3CU, 0xBF6CE9U, 0xBF7402U, 0xBF8286U, 0xBF9A6DU, 0xBFABB8U, 0xBFB353U, 0xBFC811U, 0xBFD0FAU, - 0xBFE12FU, 0xBFF9C4U, 0xC00A4EU, 0xC012A5U, 0xC02370U, 0xC03B9BU, 0xC040D9U, 0xC05832U, 0xC069E7U, 0xC0710CU, - 0xC08788U, 0xC09F63U, 0xC0AEB6U, 0xC0B65DU, 0xC0CD1FU, 0xC0D5F4U, 0xC0E421U, 0xC0FCCAU, 0xC10929U, 0xC111C2U, - 0xC12017U, 0xC138FCU, 0xC143BEU, 0xC15B55U, 0xC16A80U, 0xC1726BU, 0xC184EFU, 0xC19C04U, 0xC1ADD1U, 0xC1B53AU, - 0xC1CE78U, 0xC1D693U, 0xC1E746U, 0xC1FFADU, 0xC20C83U, 0xC21468U, 0xC225BDU, 0xC23D56U, 0xC24614U, 0xC25EFFU, - 0xC26F2AU, 0xC277C1U, 0xC28145U, 0xC299AEU, 0xC2A87BU, 0xC2B090U, 0xC2CBD2U, 0xC2D339U, 0xC2E2ECU, 0xC2FA07U, - 0xC30FE4U, 0xC3170FU, 0xC326DAU, 0xC33E31U, 0xC34573U, 0xC35D98U, 0xC36C4DU, 0xC374A6U, 0xC38222U, 0xC39AC9U, - 0xC3AB1CU, 0xC3B3F7U, 0xC3C8B5U, 0xC3D05EU, 0xC3E18BU, 0xC3F960U, 0xC407D7U, 0xC41F3CU, 0xC42EE9U, 0xC43602U, - 0xC44D40U, 0xC455ABU, 0xC4647EU, 0xC47C95U, 0xC48A11U, 0xC492FAU, 0xC4A32FU, 0xC4BBC4U, 0xC4C086U, 0xC4D86DU, - 0xC4E9B8U, 0xC4F153U, 0xC504B0U, 0xC51C5BU, 0xC52D8EU, 0xC53565U, 0xC54E27U, 0xC556CCU, 0xC56719U, 0xC57FF2U, - 0xC58976U, 0xC5919DU, 0xC5A048U, 0xC5B8A3U, 0xC5C3E1U, 0xC5DB0AU, 0xC5EADFU, 0xC5F234U, 0xC6011AU, 0xC619F1U, - 0xC62824U, 0xC630CFU, 0xC64B8DU, 0xC65366U, 0xC662B3U, 0xC67A58U, 0xC68CDCU, 0xC69437U, 0xC6A5E2U, 0xC6BD09U, - 0xC6C64BU, 0xC6DEA0U, 0xC6EF75U, 0xC6F79EU, 0xC7027DU, 0xC71A96U, 0xC72B43U, 0xC733A8U, 0xC748EAU, 0xC75001U, - 0xC761D4U, 0xC7793FU, 0xC78FBBU, 0xC79750U, 0xC7A685U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC7U, 0xC7EC12U, 0xC7F4F9U, - 0xC80994U, 0xC8117FU, 0xC820AAU, 0xC83841U, 0xC84303U, 0xC85BE8U, 0xC86A3DU, 0xC872D6U, 0xC88452U, 0xC89CB9U, - 0xC8AD6CU, 0xC8B587U, 0xC8CEC5U, 0xC8D62EU, 0xC8E7FBU, 0xC8FF10U, 0xC90AF3U, 0xC91218U, 0xC923CDU, 0xC93B26U, - 0xC94064U, 0xC9588FU, 0xC9695AU, 0xC971B1U, 0xC98735U, 0xC99FDEU, 0xC9AE0BU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D549U, - 0xC9E49CU, 0xC9FC77U, 0xCA0F59U, 0xCA17B2U, 0xCA2667U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D25U, 0xCA6CF0U, 0xCA741BU, - 0xCA829FU, 0xCA9A74U, 0xCAABA1U, 0xCAB34AU, 0xCAC808U, 0xCAD0E3U, 0xCAE136U, 0xCAF9DDU, 0xCB0C3EU, 0xCB14D5U, - 0xCB2500U, 0xCB3DEBU, 0xCB46A9U, 0xCB5E42U, 0xCB6F97U, 0xCB777CU, 0xCB81F8U, 0xCB9913U, 0xCBA8C6U, 0xCBB02DU, - 0xCBCB6FU, 0xCBD384U, 0xCBE251U, 0xCBFABAU, 0xCC040DU, 0xCC1CE6U, 0xCC2D33U, 0xCC35D8U, 0xCC4E9AU, 0xCC5671U, - 0xCC67A4U, 0xCC7F4FU, 0xCC89CBU, 0xCC9120U, 0xCCA0F5U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB7U, 0xCCEA62U, 0xCCF289U, - 0xCD076AU, 0xCD1F81U, 0xCD2E54U, 0xCD36BFU, 0xCD4DFDU, 0xCD5516U, 0xCD64C3U, 0xCD7C28U, 0xCD8AACU, 0xCD9247U, - 0xCDA392U, 0xCDBB79U, 0xCDC03BU, 0xCDD8D0U, 0xCDE905U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2BU, 0xCE2BFEU, 0xCE3315U, - 0xCE4857U, 0xCE50BCU, 0xCE6169U, 0xCE7982U, 0xCE8F06U, 0xCE97EDU, 0xCEA638U, 0xCEBED3U, 0xCEC591U, 0xCEDD7AU, - 0xCEECAFU, 0xCEF444U, 0xCF01A7U, 0xCF194CU, 0xCF2899U, 0xCF3072U, 0xCF4B30U, 0xCF53DBU, 0xCF620EU, 0xCF7AE5U, - 0xCF8C61U, 0xCF948AU, 0xCFA55FU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1DU, 0xCFEFC8U, 0xCFF723U, 0xD00DFAU, 0xD01511U, - 0xD024C4U, 0xD03C2FU, 0xD0476DU, 0xD05F86U, 0xD06E53U, 0xD076B8U, 0xD0803CU, 0xD098D7U, 0xD0A902U, 0xD0B1E9U, - 0xD0CAABU, 0xD0D240U, 0xD0E395U, 0xD0FB7EU, 0xD10E9DU, 0xD11676U, 0xD127A3U, 0xD13F48U, 0xD1440AU, 0xD15CE1U, - 0xD16D34U, 0xD175DFU, 0xD1835BU, 0xD19BB0U, 0xD1AA65U, 0xD1B28EU, 0xD1C9CCU, 0xD1D127U, 0xD1E0F2U, 0xD1F819U, - 0xD20B37U, 0xD213DCU, 0xD22209U, 0xD23AE2U, 0xD241A0U, 0xD2594BU, 0xD2689EU, 0xD27075U, 0xD286F1U, 0xD29E1AU, - 0xD2AFCFU, 0xD2B724U, 0xD2CC66U, 0xD2D48DU, 0xD2E558U, 0xD2FDB3U, 0xD30850U, 0xD310BBU, 0xD3216EU, 0xD33985U, - 0xD342C7U, 0xD35A2CU, 0xD36BF9U, 0xD37312U, 0xD38596U, 0xD39D7DU, 0xD3ACA8U, 0xD3B443U, 0xD3CF01U, 0xD3D7EAU, - 0xD3E63FU, 0xD3FED4U, 0xD40063U, 0xD41888U, 0xD4295DU, 0xD431B6U, 0xD44AF4U, 0xD4521FU, 0xD463CAU, 0xD47B21U, - 0xD48DA5U, 0xD4954EU, 0xD4A49BU, 0xD4BC70U, 0xD4C732U, 0xD4DFD9U, 0xD4EE0CU, 0xD4F6E7U, 0xD50304U, 0xD51BEFU, - 0xD52A3AU, 0xD532D1U, 0xD54993U, 0xD55178U, 0xD560ADU, 0xD57846U, 0xD58EC2U, 0xD59629U, 0xD5A7FCU, 0xD5BF17U, - 0xD5C455U, 0xD5DCBEU, 0xD5ED6BU, 0xD5F580U, 0xD606AEU, 0xD61E45U, 0xD62F90U, 0xD6377BU, 0xD64C39U, 0xD654D2U, - 0xD66507U, 0xD67DECU, 0xD68B68U, 0xD69383U, 0xD6A256U, 0xD6BABDU, 0xD6C1FFU, 0xD6D914U, 0xD6E8C1U, 0xD6F02AU, - 0xD705C9U, 0xD71D22U, 0xD72CF7U, 0xD7341CU, 0xD74F5EU, 0xD757B5U, 0xD76660U, 0xD77E8BU, 0xD7880FU, 0xD790E4U, - 0xD7A131U, 0xD7B9DAU, 0xD7C298U, 0xD7DA73U, 0xD7EBA6U, 0xD7F34DU, 0xD80E20U, 0xD816CBU, 0xD8271EU, 0xD83FF5U, - 0xD844B7U, 0xD85C5CU, 0xD86D89U, 0xD87562U, 0xD883E6U, 0xD89B0DU, 0xD8AAD8U, 0xD8B233U, 0xD8C971U, 0xD8D19AU, - 0xD8E04FU, 0xD8F8A4U, 0xD90D47U, 0xD915ACU, 0xD92479U, 0xD93C92U, 0xD947D0U, 0xD95F3BU, 0xD96EEEU, 0xD97605U, - 0xD98081U, 0xD9986AU, 0xD9A9BFU, 0xD9B154U, 0xD9CA16U, 0xD9D2FDU, 0xD9E328U, 0xD9FBC3U, 0xDA08EDU, 0xDA1006U, - 0xDA21D3U, 0xDA3938U, 0xDA427AU, 0xDA5A91U, 0xDA6B44U, 0xDA73AFU, 0xDA852BU, 0xDA9DC0U, 0xDAAC15U, 0xDAB4FEU, - 0xDACFBCU, 0xDAD757U, 0xDAE682U, 0xDAFE69U, 0xDB0B8AU, 0xDB1361U, 0xDB22B4U, 0xDB3A5FU, 0xDB411DU, 0xDB59F6U, - 0xDB6823U, 0xDB70C8U, 0xDB864CU, 0xDB9EA7U, 0xDBAF72U, 0xDBB799U, 0xDBCCDBU, 0xDBD430U, 0xDBE5E5U, 0xDBFD0EU, - 0xDC03B9U, 0xDC1B52U, 0xDC2A87U, 0xDC326CU, 0xDC492EU, 0xDC51C5U, 0xDC6010U, 0xDC78FBU, 0xDC8E7FU, 0xDC9694U, - 0xDCA741U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC03U, 0xDCEDD6U, 0xDCF53DU, 0xDD00DEU, 0xDD1835U, 0xDD29E0U, 0xDD310BU, - 0xDD4A49U, 0xDD52A2U, 0xDD6377U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F3U, 0xDDA426U, 0xDDBCCDU, 0xDDC78FU, 0xDDDF64U, - 0xDDEEB1U, 0xDDF65AU, 0xDE0574U, 0xDE1D9FU, 0xDE2C4AU, 0xDE34A1U, 0xDE4FE3U, 0xDE5708U, 0xDE66DDU, 0xDE7E36U, - 0xDE88B2U, 0xDE9059U, 0xDEA18CU, 0xDEB967U, 0xDEC225U, 0xDEDACEU, 0xDEEB1BU, 0xDEF3F0U, 0xDF0613U, 0xDF1EF8U, - 0xDF2F2DU, 0xDF37C6U, 0xDF4C84U, 0xDF546FU, 0xDF65BAU, 0xDF7D51U, 0xDF8BD5U, 0xDF933EU, 0xDFA2EBU, 0xDFBA00U, - 0xDFC142U, 0xDFD9A9U, 0xDFE87CU, 0xDFF097U, 0xE00526U, 0xE01DCDU, 0xE02C18U, 0xE034F3U, 0xE04FB1U, 0xE0575AU, - 0xE0668FU, 0xE07E64U, 0xE088E0U, 0xE0900BU, 0xE0A1DEU, 0xE0B935U, 0xE0C277U, 0xE0DA9CU, 0xE0EB49U, 0xE0F3A2U, - 0xE10641U, 0xE11EAAU, 0xE12F7FU, 0xE13794U, 0xE14CD6U, 0xE1543DU, 0xE165E8U, 0xE17D03U, 0xE18B87U, 0xE1936CU, - 0xE1A2B9U, 0xE1BA52U, 0xE1C110U, 0xE1D9FBU, 0xE1E82EU, 0xE1F0C5U, 0xE203EBU, 0xE21B00U, 0xE22AD5U, 0xE2323EU, - 0xE2497CU, 0xE25197U, 0xE26042U, 0xE278A9U, 0xE28E2DU, 0xE296C6U, 0xE2A713U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC51U, - 0xE2ED84U, 0xE2F56FU, 0xE3008CU, 0xE31867U, 0xE329B2U, 0xE33159U, 0xE34A1BU, 0xE352F0U, 0xE36325U, 0xE37BCEU, - 0xE38D4AU, 0xE395A1U, 0xE3A474U, 0xE3BC9FU, 0xE3C7DDU, 0xE3DF36U, 0xE3EEE3U, 0xE3F608U, 0xE408BFU, 0xE41054U, - 0xE42181U, 0xE4396AU, 0xE44228U, 0xE45AC3U, 0xE46B16U, 0xE473FDU, 0xE48579U, 0xE49D92U, 0xE4AC47U, 0xE4B4ACU, - 0xE4CFEEU, 0xE4D705U, 0xE4E6D0U, 0xE4FE3BU, 0xE50BD8U, 0xE51333U, 0xE522E6U, 0xE53A0DU, 0xE5414FU, 0xE559A4U, - 0xE56871U, 0xE5709AU, 0xE5861EU, 0xE59EF5U, 0xE5AF20U, 0xE5B7CBU, 0xE5CC89U, 0xE5D462U, 0xE5E5B7U, 0xE5FD5CU, - 0xE60E72U, 0xE61699U, 0xE6274CU, 0xE63FA7U, 0xE644E5U, 0xE65C0EU, 0xE66DDBU, 0xE67530U, 0xE683B4U, 0xE69B5FU, - 0xE6AA8AU, 0xE6B261U, 0xE6C923U, 0xE6D1C8U, 0xE6E01DU, 0xE6F8F6U, 0xE70D15U, 0xE715FEU, 0xE7242BU, 0xE73CC0U, - 0xE74782U, 0xE75F69U, 0xE76EBCU, 0xE77657U, 0xE780D3U, 0xE79838U, 0xE7A9EDU, 0xE7B106U, 0xE7CA44U, 0xE7D2AFU, - 0xE7E37AU, 0xE7FB91U, 0xE806FCU, 0xE81E17U, 0xE82FC2U, 0xE83729U, 0xE84C6BU, 0xE85480U, 0xE86555U, 0xE87DBEU, - 0xE88B3AU, 0xE893D1U, 0xE8A204U, 0xE8BAEFU, 0xE8C1ADU, 0xE8D946U, 0xE8E893U, 0xE8F078U, 0xE9059BU, 0xE91D70U, - 0xE92CA5U, 0xE9344EU, 0xE94F0CU, 0xE957E7U, 0xE96632U, 0xE97ED9U, 0xE9885DU, 0xE990B6U, 0xE9A163U, 0xE9B988U, - 0xE9C2CAU, 0xE9DA21U, 0xE9EBF4U, 0xE9F31FU, 0xEA0031U, 0xEA18DAU, 0xEA290FU, 0xEA31E4U, 0xEA4AA6U, 0xEA524DU, - 0xEA6398U, 0xEA7B73U, 0xEA8DF7U, 0xEA951CU, 0xEAA4C9U, 0xEABC22U, 0xEAC760U, 0xEADF8BU, 0xEAEE5EU, 0xEAF6B5U, - 0xEB0356U, 0xEB1BBDU, 0xEB2A68U, 0xEB3283U, 0xEB49C1U, 0xEB512AU, 0xEB60FFU, 0xEB7814U, 0xEB8E90U, 0xEB967BU, - 0xEBA7AEU, 0xEBBF45U, 0xEBC407U, 0xEBDCECU, 0xEBED39U, 0xEBF5D2U, 0xEC0B65U, 0xEC138EU, 0xEC225BU, 0xEC3AB0U, - 0xEC41F2U, 0xEC5919U, 0xEC68CCU, 0xEC7027U, 0xEC86A3U, 0xEC9E48U, 0xECAF9DU, 0xECB776U, 0xECCC34U, 0xECD4DFU, - 0xECE50AU, 0xECFDE1U, 0xED0802U, 0xED10E9U, 0xED213CU, 0xED39D7U, 0xED4295U, 0xED5A7EU, 0xED6BABU, 0xED7340U, - 0xED85C4U, 0xED9D2FU, 0xEDACFAU, 0xEDB411U, 0xEDCF53U, 0xEDD7B8U, 0xEDE66DU, 0xEDFE86U, 0xEE0DA8U, 0xEE1543U, - 0xEE2496U, 0xEE3C7DU, 0xEE473FU, 0xEE5FD4U, 0xEE6E01U, 0xEE76EAU, 0xEE806EU, 0xEE9885U, 0xEEA950U, 0xEEB1BBU, - 0xEECAF9U, 0xEED212U, 0xEEE3C7U, 0xEEFB2CU, 0xEF0ECFU, 0xEF1624U, 0xEF27F1U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB3U, - 0xEF6D66U, 0xEF758DU, 0xEF8309U, 0xEF9BE2U, 0xEFAA37U, 0xEFB2DCU, 0xEFC99EU, 0xEFD175U, 0xEFE0A0U, 0xEFF84BU, - 0xF00292U, 0xF01A79U, 0xF02BACU, 0xF03347U, 0xF04805U, 0xF050EEU, 0xF0613BU, 0xF079D0U, 0xF08F54U, 0xF097BFU, - 0xF0A66AU, 0xF0BE81U, 0xF0C5C3U, 0xF0DD28U, 0xF0ECFDU, 0xF0F416U, 0xF101F5U, 0xF1191EU, 0xF128CBU, 0xF13020U, - 0xF14B62U, 0xF15389U, 0xF1625CU, 0xF17AB7U, 0xF18C33U, 0xF194D8U, 0xF1A50DU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4FU, - 0xF1EF9AU, 0xF1F771U, 0xF2045FU, 0xF21CB4U, 0xF22D61U, 0xF2358AU, 0xF24EC8U, 0xF25623U, 0xF267F6U, 0xF27F1DU, - 0xF28999U, 0xF29172U, 0xF2A0A7U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE5U, 0xF2EA30U, 0xF2F2DBU, 0xF30738U, 0xF31FD3U, - 0xF32E06U, 0xF336EDU, 0xF34DAFU, 0xF35544U, 0xF36491U, 0xF37C7AU, 0xF38AFEU, 0xF39215U, 0xF3A3C0U, 0xF3BB2BU, - 0xF3C069U, 0xF3D882U, 0xF3E957U, 0xF3F1BCU, 0xF40F0BU, 0xF417E0U, 0xF42635U, 0xF43EDEU, 0xF4459CU, 0xF45D77U, - 0xF46CA2U, 0xF47449U, 0xF482CDU, 0xF49A26U, 0xF4ABF3U, 0xF4B318U, 0xF4C85AU, 0xF4D0B1U, 0xF4E164U, 0xF4F98FU, - 0xF50C6CU, 0xF51487U, 0xF52552U, 0xF53DB9U, 0xF546FBU, 0xF55E10U, 0xF56FC5U, 0xF5772EU, 0xF581AAU, 0xF59941U, - 0xF5A894U, 0xF5B07FU, 0xF5CB3DU, 0xF5D3D6U, 0xF5E203U, 0xF5FAE8U, 0xF609C6U, 0xF6112DU, 0xF620F8U, 0xF63813U, - 0xF64351U, 0xF65BBAU, 0xF66A6FU, 0xF67284U, 0xF68400U, 0xF69CEBU, 0xF6AD3EU, 0xF6B5D5U, 0xF6CE97U, 0xF6D67CU, - 0xF6E7A9U, 0xF6FF42U, 0xF70AA1U, 0xF7124AU, 0xF7239FU, 0xF73B74U, 0xF74036U, 0xF758DDU, 0xF76908U, 0xF771E3U, - 0xF78767U, 0xF79F8CU, 0xF7AE59U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51BU, 0xF7E4CEU, 0xF7FC25U, 0xF80148U, 0xF819A3U, - 0xF82876U, 0xF8309DU, 0xF84BDFU, 0xF85334U, 0xF862E1U, 0xF87A0AU, 0xF88C8EU, 0xF89465U, 0xF8A5B0U, 0xF8BD5BU, - 0xF8C619U, 0xF8DEF2U, 0xF8EF27U, 0xF8F7CCU, 0xF9022FU, 0xF91AC4U, 0xF92B11U, 0xF933FAU, 0xF948B8U, 0xF95053U, - 0xF96186U, 0xF9796DU, 0xF98FE9U, 0xF99702U, 0xF9A6D7U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD95U, 0xF9EC40U, 0xF9F4ABU, - 0xFA0785U, 0xFA1F6EU, 0xFA2EBBU, 0xFA3650U, 0xFA4D12U, 0xFA55F9U, 0xFA642CU, 0xFA7CC7U, 0xFA8A43U, 0xFA92A8U, - 0xFAA37DU, 0xFABB96U, 0xFAC0D4U, 0xFAD83FU, 0xFAE9EAU, 0xFAF101U, 0xFB04E2U, 0xFB1C09U, 0xFB2DDCU, 0xFB3537U, - 0xFB4E75U, 0xFB569EU, 0xFB674BU, 0xFB7FA0U, 0xFB8924U, 0xFB91CFU, 0xFBA01AU, 0xFBB8F1U, 0xFBC3B3U, 0xFBDB58U, - 0xFBEA8DU, 0xFBF266U, 0xFC0CD1U, 0xFC143AU, 0xFC25EFU, 0xFC3D04U, 0xFC4646U, 0xFC5EADU, 0xFC6F78U, 0xFC7793U, - 0xFC8117U, 0xFC99FCU, 0xFCA829U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36BU, 0xFCE2BEU, 0xFCFA55U, 0xFD0FB6U, 0xFD175DU, - 0xFD2688U, 0xFD3E63U, 0xFD4521U, 0xFD5DCAU, 0xFD6C1FU, 0xFD74F4U, 0xFD8270U, 0xFD9A9BU, 0xFDAB4EU, 0xFDB3A5U, - 0xFDC8E7U, 0xFDD00CU, 0xFDE1D9U, 0xFDF932U, 0xFE0A1CU, 0xFE12F7U, 0xFE2322U, 0xFE3BC9U, 0xFE408BU, 0xFE5860U, - 0xFE69B5U, 0xFE715EU, 0xFE87DAU, 0xFE9F31U, 0xFEAEE4U, 0xFEB60FU, 0xFECD4DU, 0xFED5A6U, 0xFEE473U, 0xFEFC98U, - 0xFF097BU, 0xFF1190U, 0xFF2045U, 0xFF38AEU, 0xFF43ECU, 0xFF5B07U, 0xFF6AD2U, 0xFF7239U, 0xFF84BDU, 0xFF9C56U, - 0xFFAD83U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C1U, 0xFFE714U, 0xFFFFFFU + 0x000000U, 0x0018EBU, 0x00293EU, 0x0031D5U, 0x004A97U, 0x00527CU, 0x0063A9U, 0x007B42U, 0x008DC6U, 0x00952DU, + 0x00A4F8U, 0x00BC13U, 0x00C751U, 0x00DFBAU, 0x00EE6FU, 0x00F684U, 0x010367U, 0x011B8CU, 0x012A59U, 0x0132B2U, + 0x0149F0U, 0x01511BU, 0x0160CEU, 0x017825U, 0x018EA1U, 0x01964AU, 0x01A79FU, 0x01BF74U, 0x01C436U, 0x01DCDDU, + 0x01ED08U, 0x01F5E3U, 0x0206CDU, 0x021E26U, 0x022FF3U, 0x023718U, 0x024C5AU, 0x0254B1U, 0x026564U, 0x027D8FU, + 0x028B0BU, 0x0293E0U, 0x02A235U, 0x02BADEU, 0x02C19CU, 0x02D977U, 0x02E8A2U, 0x02F049U, 0x0305AAU, 0x031D41U, + 0x032C94U, 0x03347FU, 0x034F3DU, 0x0357D6U, 0x036603U, 0x037EE8U, 0x03886CU, 0x039087U, 0x03A152U, 0x03B9B9U, + 0x03C2FBU, 0x03DA10U, 0x03EBC5U, 0x03F32EU, 0x040D99U, 0x041572U, 0x0424A7U, 0x043C4CU, 0x04470EU, 0x045FE5U, + 0x046E30U, 0x0476DBU, 0x04805FU, 0x0498B4U, 0x04A961U, 0x04B18AU, 0x04CAC8U, 0x04D223U, 0x04E3F6U, 0x04FB1DU, + 0x050EFEU, 0x051615U, 0x0527C0U, 0x053F2BU, 0x054469U, 0x055C82U, 0x056D57U, 0x0575BCU, 0x058338U, 0x059BD3U, + 0x05AA06U, 0x05B2EDU, 0x05C9AFU, 0x05D144U, 0x05E091U, 0x05F87AU, 0x060B54U, 0x0613BFU, 0x06226AU, 0x063A81U, + 0x0641C3U, 0x065928U, 0x0668FDU, 0x067016U, 0x068692U, 0x069E79U, 0x06AFACU, 0x06B747U, 0x06CC05U, 0x06D4EEU, + 0x06E53BU, 0x06FDD0U, 0x070833U, 0x0710D8U, 0x07210DU, 0x0739E6U, 0x0742A4U, 0x075A4FU, 0x076B9AU, 0x077371U, + 0x0785F5U, 0x079D1EU, 0x07ACCBU, 0x07B420U, 0x07CF62U, 0x07D789U, 0x07E65CU, 0x07FEB7U, 0x0803DAU, 0x081B31U, + 0x082AE4U, 0x08320FU, 0x08494DU, 0x0851A6U, 0x086073U, 0x087898U, 0x088E1CU, 0x0896F7U, 0x08A722U, 0x08BFC9U, + 0x08C48BU, 0x08DC60U, 0x08EDB5U, 0x08F55EU, 0x0900BDU, 0x091856U, 0x092983U, 0x093168U, 0x094A2AU, 0x0952C1U, + 0x096314U, 0x097BFFU, 0x098D7BU, 0x099590U, 0x09A445U, 0x09BCAEU, 0x09C7ECU, 0x09DF07U, 0x09EED2U, 0x09F639U, + 0x0A0517U, 0x0A1DFCU, 0x0A2C29U, 0x0A34C2U, 0x0A4F80U, 0x0A576BU, 0x0A66BEU, 0x0A7E55U, 0x0A88D1U, 0x0A903AU, + 0x0AA1EFU, 0x0AB904U, 0x0AC246U, 0x0ADAADU, 0x0AEB78U, 0x0AF393U, 0x0B0670U, 0x0B1E9BU, 0x0B2F4EU, 0x0B37A5U, + 0x0B4CE7U, 0x0B540CU, 0x0B65D9U, 0x0B7D32U, 0x0B8BB6U, 0x0B935DU, 0x0BA288U, 0x0BBA63U, 0x0BC121U, 0x0BD9CAU, + 0x0BE81FU, 0x0BF0F4U, 0x0C0E43U, 0x0C16A8U, 0x0C277DU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3FU, 0x0C6DEAU, 0x0C7501U, + 0x0C8385U, 0x0C9B6EU, 0x0CAABBU, 0x0CB250U, 0x0CC912U, 0x0CD1F9U, 0x0CE02CU, 0x0CF8C7U, 0x0D0D24U, 0x0D15CFU, + 0x0D241AU, 0x0D3CF1U, 0x0D47B3U, 0x0D5F58U, 0x0D6E8DU, 0x0D7666U, 0x0D80E2U, 0x0D9809U, 0x0DA9DCU, 0x0DB137U, + 0x0DCA75U, 0x0DD29EU, 0x0DE34BU, 0x0DFBA0U, 0x0E088EU, 0x0E1065U, 0x0E21B0U, 0x0E395BU, 0x0E4219U, 0x0E5AF2U, + 0x0E6B27U, 0x0E73CCU, 0x0E8548U, 0x0E9DA3U, 0x0EAC76U, 0x0EB49DU, 0x0ECFDFU, 0x0ED734U, 0x0EE6E1U, 0x0EFE0AU, + 0x0F0BE9U, 0x0F1302U, 0x0F22D7U, 0x0F3A3CU, 0x0F417EU, 0x0F5995U, 0x0F6840U, 0x0F70ABU, 0x0F862FU, 0x0F9EC4U, + 0x0FAF11U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD453U, 0x0FE586U, 0x0FFD6DU, 0x1007B4U, 0x101F5FU, 0x102E8AU, 0x103661U, + 0x104D23U, 0x1055C8U, 0x10641DU, 0x107CF6U, 0x108A72U, 0x109299U, 0x10A34CU, 0x10BBA7U, 0x10C0E5U, 0x10D80EU, + 0x10E9DBU, 0x10F130U, 0x1104D3U, 0x111C38U, 0x112DEDU, 0x113506U, 0x114E44U, 0x1156AFU, 0x11677AU, 0x117F91U, + 0x118915U, 0x1191FEU, 0x11A02BU, 0x11B8C0U, 0x11C382U, 0x11DB69U, 0x11EABCU, 0x11F257U, 0x120179U, 0x121992U, + 0x122847U, 0x1230ACU, 0x124BEEU, 0x125305U, 0x1262D0U, 0x127A3BU, 0x128CBFU, 0x129454U, 0x12A581U, 0x12BD6AU, + 0x12C628U, 0x12DEC3U, 0x12EF16U, 0x12F7FDU, 0x13021EU, 0x131AF5U, 0x132B20U, 0x1333CBU, 0x134889U, 0x135062U, + 0x1361B7U, 0x13795CU, 0x138FD8U, 0x139733U, 0x13A6E6U, 0x13BE0DU, 0x13C54FU, 0x13DDA4U, 0x13EC71U, 0x13F49AU, + 0x140A2DU, 0x1412C6U, 0x142313U, 0x143BF8U, 0x1440BAU, 0x145851U, 0x146984U, 0x14716FU, 0x1487EBU, 0x149F00U, + 0x14AED5U, 0x14B63EU, 0x14CD7CU, 0x14D597U, 0x14E442U, 0x14FCA9U, 0x15094AU, 0x1511A1U, 0x152074U, 0x15389FU, + 0x1543DDU, 0x155B36U, 0x156AE3U, 0x157208U, 0x15848CU, 0x159C67U, 0x15ADB2U, 0x15B559U, 0x15CE1BU, 0x15D6F0U, + 0x15E725U, 0x15FFCEU, 0x160CE0U, 0x16140BU, 0x1625DEU, 0x163D35U, 0x164677U, 0x165E9CU, 0x166F49U, 0x1677A2U, + 0x168126U, 0x1699CDU, 0x16A818U, 0x16B0F3U, 0x16CBB1U, 0x16D35AU, 0x16E28FU, 0x16FA64U, 0x170F87U, 0x17176CU, + 0x1726B9U, 0x173E52U, 0x174510U, 0x175DFBU, 0x176C2EU, 0x1774C5U, 0x178241U, 0x179AAAU, 0x17AB7FU, 0x17B394U, + 0x17C8D6U, 0x17D03DU, 0x17E1E8U, 0x17F903U, 0x18046EU, 0x181C85U, 0x182D50U, 0x1835BBU, 0x184EF9U, 0x185612U, + 0x1867C7U, 0x187F2CU, 0x1889A8U, 0x189143U, 0x18A096U, 0x18B87DU, 0x18C33FU, 0x18DBD4U, 0x18EA01U, 0x18F2EAU, + 0x190709U, 0x191FE2U, 0x192E37U, 0x1936DCU, 0x194D9EU, 0x195575U, 0x1964A0U, 0x197C4BU, 0x198ACFU, 0x199224U, + 0x19A3F1U, 0x19BB1AU, 0x19C058U, 0x19D8B3U, 0x19E966U, 0x19F18DU, 0x1A02A3U, 0x1A1A48U, 0x1A2B9DU, 0x1A3376U, + 0x1A4834U, 0x1A50DFU, 0x1A610AU, 0x1A79E1U, 0x1A8F65U, 0x1A978EU, 0x1AA65BU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD19U, + 0x1AECCCU, 0x1AF427U, 0x1B01C4U, 0x1B192FU, 0x1B28FAU, 0x1B3011U, 0x1B4B53U, 0x1B53B8U, 0x1B626DU, 0x1B7A86U, + 0x1B8C02U, 0x1B94E9U, 0x1BA53CU, 0x1BBDD7U, 0x1BC695U, 0x1BDE7EU, 0x1BEFABU, 0x1BF740U, 0x1C09F7U, 0x1C111CU, + 0x1C20C9U, 0x1C3822U, 0x1C4360U, 0x1C5B8BU, 0x1C6A5EU, 0x1C72B5U, 0x1C8431U, 0x1C9CDAU, 0x1CAD0FU, 0x1CB5E4U, + 0x1CCEA6U, 0x1CD64DU, 0x1CE798U, 0x1CFF73U, 0x1D0A90U, 0x1D127BU, 0x1D23AEU, 0x1D3B45U, 0x1D4007U, 0x1D58ECU, + 0x1D6939U, 0x1D71D2U, 0x1D8756U, 0x1D9FBDU, 0x1DAE68U, 0x1DB683U, 0x1DCDC1U, 0x1DD52AU, 0x1DE4FFU, 0x1DFC14U, + 0x1E0F3AU, 0x1E17D1U, 0x1E2604U, 0x1E3EEFU, 0x1E45ADU, 0x1E5D46U, 0x1E6C93U, 0x1E7478U, 0x1E82FCU, 0x1E9A17U, + 0x1EABC2U, 0x1EB329U, 0x1EC86BU, 0x1ED080U, 0x1EE155U, 0x1EF9BEU, 0x1F0C5DU, 0x1F14B6U, 0x1F2563U, 0x1F3D88U, + 0x1F46CAU, 0x1F5E21U, 0x1F6FF4U, 0x1F771FU, 0x1F819BU, 0x1F9970U, 0x1FA8A5U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E7U, + 0x1FE232U, 0x1FFAD9U, 0x200F68U, 0x201783U, 0x202656U, 0x203EBDU, 0x2045FFU, 0x205D14U, 0x206CC1U, 0x20742AU, + 0x2082AEU, 0x209A45U, 0x20AB90U, 0x20B37BU, 0x20C839U, 0x20D0D2U, 0x20E107U, 0x20F9ECU, 0x210C0FU, 0x2114E4U, + 0x212531U, 0x213DDAU, 0x214698U, 0x215E73U, 0x216FA6U, 0x21774DU, 0x2181C9U, 0x219922U, 0x21A8F7U, 0x21B01CU, + 0x21CB5EU, 0x21D3B5U, 0x21E260U, 0x21FA8BU, 0x2209A5U, 0x22114EU, 0x22209BU, 0x223870U, 0x224332U, 0x225BD9U, + 0x226A0CU, 0x2272E7U, 0x228463U, 0x229C88U, 0x22AD5DU, 0x22B5B6U, 0x22CEF4U, 0x22D61FU, 0x22E7CAU, 0x22FF21U, + 0x230AC2U, 0x231229U, 0x2323FCU, 0x233B17U, 0x234055U, 0x2358BEU, 0x23696BU, 0x237180U, 0x238704U, 0x239FEFU, + 0x23AE3AU, 0x23B6D1U, 0x23CD93U, 0x23D578U, 0x23E4ADU, 0x23FC46U, 0x2402F1U, 0x241A1AU, 0x242BCFU, 0x243324U, + 0x244866U, 0x24508DU, 0x246158U, 0x2479B3U, 0x248F37U, 0x2497DCU, 0x24A609U, 0x24BEE2U, 0x24C5A0U, 0x24DD4BU, + 0x24EC9EU, 0x24F475U, 0x250196U, 0x25197DU, 0x2528A8U, 0x253043U, 0x254B01U, 0x2553EAU, 0x25623FU, 0x257AD4U, + 0x258C50U, 0x2594BBU, 0x25A56EU, 0x25BD85U, 0x25C6C7U, 0x25DE2CU, 0x25EFF9U, 0x25F712U, 0x26043CU, 0x261CD7U, + 0x262D02U, 0x2635E9U, 0x264EABU, 0x265640U, 0x266795U, 0x267F7EU, 0x2689FAU, 0x269111U, 0x26A0C4U, 0x26B82FU, + 0x26C36DU, 0x26DB86U, 0x26EA53U, 0x26F2B8U, 0x27075BU, 0x271FB0U, 0x272E65U, 0x27368EU, 0x274DCCU, 0x275527U, + 0x2764F2U, 0x277C19U, 0x278A9DU, 0x279276U, 0x27A3A3U, 0x27BB48U, 0x27C00AU, 0x27D8E1U, 0x27E934U, 0x27F1DFU, + 0x280CB2U, 0x281459U, 0x28258CU, 0x283D67U, 0x284625U, 0x285ECEU, 0x286F1BU, 0x2877F0U, 0x288174U, 0x28999FU, + 0x28A84AU, 0x28B0A1U, 0x28CBE3U, 0x28D308U, 0x28E2DDU, 0x28FA36U, 0x290FD5U, 0x29173EU, 0x2926EBU, 0x293E00U, + 0x294542U, 0x295DA9U, 0x296C7CU, 0x297497U, 0x298213U, 0x299AF8U, 0x29AB2DU, 0x29B3C6U, 0x29C884U, 0x29D06FU, + 0x29E1BAU, 0x29F951U, 0x2A0A7FU, 0x2A1294U, 0x2A2341U, 0x2A3BAAU, 0x2A40E8U, 0x2A5803U, 0x2A69D6U, 0x2A713DU, + 0x2A87B9U, 0x2A9F52U, 0x2AAE87U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C5U, 0x2AE410U, 0x2AFCFBU, 0x2B0918U, 0x2B11F3U, + 0x2B2026U, 0x2B38CDU, 0x2B438FU, 0x2B5B64U, 0x2B6AB1U, 0x2B725AU, 0x2B84DEU, 0x2B9C35U, 0x2BADE0U, 0x2BB50BU, + 0x2BCE49U, 0x2BD6A2U, 0x2BE777U, 0x2BFF9CU, 0x2C012BU, 0x2C19C0U, 0x2C2815U, 0x2C30FEU, 0x2C4BBCU, 0x2C5357U, + 0x2C6282U, 0x2C7A69U, 0x2C8CEDU, 0x2C9406U, 0x2CA5D3U, 0x2CBD38U, 0x2CC67AU, 0x2CDE91U, 0x2CEF44U, 0x2CF7AFU, + 0x2D024CU, 0x2D1AA7U, 0x2D2B72U, 0x2D3399U, 0x2D48DBU, 0x2D5030U, 0x2D61E5U, 0x2D790EU, 0x2D8F8AU, 0x2D9761U, + 0x2DA6B4U, 0x2DBE5FU, 0x2DC51DU, 0x2DDDF6U, 0x2DEC23U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0DU, 0x2E2ED8U, 0x2E3633U, + 0x2E4D71U, 0x2E559AU, 0x2E644FU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CBU, 0x2EA31EU, 0x2EBBF5U, 0x2EC0B7U, 0x2ED85CU, + 0x2EE989U, 0x2EF162U, 0x2F0481U, 0x2F1C6AU, 0x2F2DBFU, 0x2F3554U, 0x2F4E16U, 0x2F56FDU, 0x2F6728U, 0x2F7FC3U, + 0x2F8947U, 0x2F91ACU, 0x2FA079U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3BU, 0x2FEAEEU, 0x2FF205U, 0x3008DCU, 0x301037U, + 0x3021E2U, 0x303909U, 0x30424BU, 0x305AA0U, 0x306B75U, 0x30739EU, 0x30851AU, 0x309DF1U, 0x30AC24U, 0x30B4CFU, + 0x30CF8DU, 0x30D766U, 0x30E6B3U, 0x30FE58U, 0x310BBBU, 0x311350U, 0x312285U, 0x313A6EU, 0x31412CU, 0x3159C7U, + 0x316812U, 0x3170F9U, 0x31867DU, 0x319E96U, 0x31AF43U, 0x31B7A8U, 0x31CCEAU, 0x31D401U, 0x31E5D4U, 0x31FD3FU, + 0x320E11U, 0x3216FAU, 0x32272FU, 0x323FC4U, 0x324486U, 0x325C6DU, 0x326DB8U, 0x327553U, 0x3283D7U, 0x329B3CU, + 0x32AAE9U, 0x32B202U, 0x32C940U, 0x32D1ABU, 0x32E07EU, 0x32F895U, 0x330D76U, 0x33159DU, 0x332448U, 0x333CA3U, + 0x3347E1U, 0x335F0AU, 0x336EDFU, 0x337634U, 0x3380B0U, 0x33985BU, 0x33A98EU, 0x33B165U, 0x33CA27U, 0x33D2CCU, + 0x33E319U, 0x33FBF2U, 0x340545U, 0x341DAEU, 0x342C7BU, 0x343490U, 0x344FD2U, 0x345739U, 0x3466ECU, 0x347E07U, + 0x348883U, 0x349068U, 0x34A1BDU, 0x34B956U, 0x34C214U, 0x34DAFFU, 0x34EB2AU, 0x34F3C1U, 0x350622U, 0x351EC9U, + 0x352F1CU, 0x3537F7U, 0x354CB5U, 0x35545EU, 0x35658BU, 0x357D60U, 0x358BE4U, 0x35930FU, 0x35A2DAU, 0x35BA31U, + 0x35C173U, 0x35D998U, 0x35E84DU, 0x35F0A6U, 0x360388U, 0x361B63U, 0x362AB6U, 0x36325DU, 0x36491FU, 0x3651F4U, + 0x366021U, 0x3678CAU, 0x368E4EU, 0x3696A5U, 0x36A770U, 0x36BF9BU, 0x36C4D9U, 0x36DC32U, 0x36EDE7U, 0x36F50CU, + 0x3700EFU, 0x371804U, 0x3729D1U, 0x37313AU, 0x374A78U, 0x375293U, 0x376346U, 0x377BADU, 0x378D29U, 0x3795C2U, + 0x37A417U, 0x37BCFCU, 0x37C7BEU, 0x37DF55U, 0x37EE80U, 0x37F66BU, 0x380B06U, 0x3813EDU, 0x382238U, 0x383AD3U, + 0x384191U, 0x38597AU, 0x3868AFU, 0x387044U, 0x3886C0U, 0x389E2BU, 0x38AFFEU, 0x38B715U, 0x38CC57U, 0x38D4BCU, + 0x38E569U, 0x38FD82U, 0x390861U, 0x39108AU, 0x39215FU, 0x3939B4U, 0x3942F6U, 0x395A1DU, 0x396BC8U, 0x397323U, + 0x3985A7U, 0x399D4CU, 0x39AC99U, 0x39B472U, 0x39CF30U, 0x39D7DBU, 0x39E60EU, 0x39FEE5U, 0x3A0DCBU, 0x3A1520U, + 0x3A24F5U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB7U, 0x3A6E62U, 0x3A7689U, 0x3A800DU, 0x3A98E6U, 0x3AA933U, 0x3AB1D8U, + 0x3ACA9AU, 0x3AD271U, 0x3AE3A4U, 0x3AFB4FU, 0x3B0EACU, 0x3B1647U, 0x3B2792U, 0x3B3F79U, 0x3B443BU, 0x3B5CD0U, + 0x3B6D05U, 0x3B75EEU, 0x3B836AU, 0x3B9B81U, 0x3BAA54U, 0x3BB2BFU, 0x3BC9FDU, 0x3BD116U, 0x3BE0C3U, 0x3BF828U, + 0x3C069FU, 0x3C1E74U, 0x3C2FA1U, 0x3C374AU, 0x3C4C08U, 0x3C54E3U, 0x3C6536U, 0x3C7DDDU, 0x3C8B59U, 0x3C93B2U, + 0x3CA267U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD925U, 0x3CE8F0U, 0x3CF01BU, 0x3D05F8U, 0x3D1D13U, 0x3D2CC6U, 0x3D342DU, + 0x3D4F6FU, 0x3D5784U, 0x3D6651U, 0x3D7EBAU, 0x3D883EU, 0x3D90D5U, 0x3DA100U, 0x3DB9EBU, 0x3DC2A9U, 0x3DDA42U, + 0x3DEB97U, 0x3DF37CU, 0x3E0052U, 0x3E18B9U, 0x3E296CU, 0x3E3187U, 0x3E4AC5U, 0x3E522EU, 0x3E63FBU, 0x3E7B10U, + 0x3E8D94U, 0x3E957FU, 0x3EA4AAU, 0x3EBC41U, 0x3EC703U, 0x3EDFE8U, 0x3EEE3DU, 0x3EF6D6U, 0x3F0335U, 0x3F1BDEU, + 0x3F2A0BU, 0x3F32E0U, 0x3F49A2U, 0x3F5149U, 0x3F609CU, 0x3F7877U, 0x3F8EF3U, 0x3F9618U, 0x3FA7CDU, 0x3FBF26U, + 0x3FC464U, 0x3FDC8FU, 0x3FED5AU, 0x3FF5B1U, 0x40063BU, 0x401ED0U, 0x402F05U, 0x4037EEU, 0x404CACU, 0x405447U, + 0x406592U, 0x407D79U, 0x408BFDU, 0x409316U, 0x40A2C3U, 0x40BA28U, 0x40C16AU, 0x40D981U, 0x40E854U, 0x40F0BFU, + 0x41055CU, 0x411DB7U, 0x412C62U, 0x413489U, 0x414FCBU, 0x415720U, 0x4166F5U, 0x417E1EU, 0x41889AU, 0x419071U, + 0x41A1A4U, 0x41B94FU, 0x41C20DU, 0x41DAE6U, 0x41EB33U, 0x41F3D8U, 0x4200F6U, 0x42181DU, 0x4229C8U, 0x423123U, + 0x424A61U, 0x42528AU, 0x42635FU, 0x427BB4U, 0x428D30U, 0x4295DBU, 0x42A40EU, 0x42BCE5U, 0x42C7A7U, 0x42DF4CU, + 0x42EE99U, 0x42F672U, 0x430391U, 0x431B7AU, 0x432AAFU, 0x433244U, 0x434906U, 0x4351EDU, 0x436038U, 0x4378D3U, + 0x438E57U, 0x4396BCU, 0x43A769U, 0x43BF82U, 0x43C4C0U, 0x43DC2BU, 0x43EDFEU, 0x43F515U, 0x440BA2U, 0x441349U, + 0x44229CU, 0x443A77U, 0x444135U, 0x4459DEU, 0x44680BU, 0x4470E0U, 0x448664U, 0x449E8FU, 0x44AF5AU, 0x44B7B1U, + 0x44CCF3U, 0x44D418U, 0x44E5CDU, 0x44FD26U, 0x4508C5U, 0x45102EU, 0x4521FBU, 0x453910U, 0x454252U, 0x455AB9U, + 0x456B6CU, 0x457387U, 0x458503U, 0x459DE8U, 0x45AC3DU, 0x45B4D6U, 0x45CF94U, 0x45D77FU, 0x45E6AAU, 0x45FE41U, + 0x460D6FU, 0x461584U, 0x462451U, 0x463CBAU, 0x4647F8U, 0x465F13U, 0x466EC6U, 0x46762DU, 0x4680A9U, 0x469842U, + 0x46A997U, 0x46B17CU, 0x46CA3EU, 0x46D2D5U, 0x46E300U, 0x46FBEBU, 0x470E08U, 0x4716E3U, 0x472736U, 0x473FDDU, + 0x47449FU, 0x475C74U, 0x476DA1U, 0x47754AU, 0x4783CEU, 0x479B25U, 0x47AAF0U, 0x47B21BU, 0x47C959U, 0x47D1B2U, + 0x47E067U, 0x47F88CU, 0x4805E1U, 0x481D0AU, 0x482CDFU, 0x483434U, 0x484F76U, 0x48579DU, 0x486648U, 0x487EA3U, + 0x488827U, 0x4890CCU, 0x48A119U, 0x48B9F2U, 0x48C2B0U, 0x48DA5BU, 0x48EB8EU, 0x48F365U, 0x490686U, 0x491E6DU, + 0x492FB8U, 0x493753U, 0x494C11U, 0x4954FAU, 0x49652FU, 0x497DC4U, 0x498B40U, 0x4993ABU, 0x49A27EU, 0x49BA95U, + 0x49C1D7U, 0x49D93CU, 0x49E8E9U, 0x49F002U, 0x4A032CU, 0x4A1BC7U, 0x4A2A12U, 0x4A32F9U, 0x4A49BBU, 0x4A5150U, + 0x4A6085U, 0x4A786EU, 0x4A8EEAU, 0x4A9601U, 0x4AA7D4U, 0x4ABF3FU, 0x4AC47DU, 0x4ADC96U, 0x4AED43U, 0x4AF5A8U, + 0x4B004BU, 0x4B18A0U, 0x4B2975U, 0x4B319EU, 0x4B4ADCU, 0x4B5237U, 0x4B63E2U, 0x4B7B09U, 0x4B8D8DU, 0x4B9566U, + 0x4BA4B3U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF1U, 0x4BEE24U, 0x4BF6CFU, 0x4C0878U, 0x4C1093U, 0x4C2146U, 0x4C39ADU, + 0x4C42EFU, 0x4C5A04U, 0x4C6BD1U, 0x4C733AU, 0x4C85BEU, 0x4C9D55U, 0x4CAC80U, 0x4CB46BU, 0x4CCF29U, 0x4CD7C2U, + 0x4CE617U, 0x4CFEFCU, 0x4D0B1FU, 0x4D13F4U, 0x4D2221U, 0x4D3ACAU, 0x4D4188U, 0x4D5963U, 0x4D68B6U, 0x4D705DU, + 0x4D86D9U, 0x4D9E32U, 0x4DAFE7U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A5U, 0x4DE570U, 0x4DFD9BU, 0x4E0EB5U, 0x4E165EU, + 0x4E278BU, 0x4E3F60U, 0x4E4422U, 0x4E5CC9U, 0x4E6D1CU, 0x4E75F7U, 0x4E8373U, 0x4E9B98U, 0x4EAA4DU, 0x4EB2A6U, + 0x4EC9E4U, 0x4ED10FU, 0x4EE0DAU, 0x4EF831U, 0x4F0DD2U, 0x4F1539U, 0x4F24ECU, 0x4F3C07U, 0x4F4745U, 0x4F5FAEU, + 0x4F6E7BU, 0x4F7690U, 0x4F8014U, 0x4F98FFU, 0x4FA92AU, 0x4FB1C1U, 0x4FCA83U, 0x4FD268U, 0x4FE3BDU, 0x4FFB56U, + 0x50018FU, 0x501964U, 0x5028B1U, 0x50305AU, 0x504B18U, 0x5053F3U, 0x506226U, 0x507ACDU, 0x508C49U, 0x5094A2U, + 0x50A577U, 0x50BD9CU, 0x50C6DEU, 0x50DE35U, 0x50EFE0U, 0x50F70BU, 0x5102E8U, 0x511A03U, 0x512BD6U, 0x51333DU, + 0x51487FU, 0x515094U, 0x516141U, 0x5179AAU, 0x518F2EU, 0x5197C5U, 0x51A610U, 0x51BEFBU, 0x51C5B9U, 0x51DD52U, + 0x51EC87U, 0x51F46CU, 0x520742U, 0x521FA9U, 0x522E7CU, 0x523697U, 0x524DD5U, 0x52553EU, 0x5264EBU, 0x527C00U, + 0x528A84U, 0x52926FU, 0x52A3BAU, 0x52BB51U, 0x52C013U, 0x52D8F8U, 0x52E92DU, 0x52F1C6U, 0x530425U, 0x531CCEU, + 0x532D1BU, 0x5335F0U, 0x534EB2U, 0x535659U, 0x53678CU, 0x537F67U, 0x5389E3U, 0x539108U, 0x53A0DDU, 0x53B836U, + 0x53C374U, 0x53DB9FU, 0x53EA4AU, 0x53F2A1U, 0x540C16U, 0x5414FDU, 0x542528U, 0x543DC3U, 0x544681U, 0x545E6AU, + 0x546FBFU, 0x547754U, 0x5481D0U, 0x54993BU, 0x54A8EEU, 0x54B005U, 0x54CB47U, 0x54D3ACU, 0x54E279U, 0x54FA92U, + 0x550F71U, 0x55179AU, 0x55264FU, 0x553EA4U, 0x5545E6U, 0x555D0DU, 0x556CD8U, 0x557433U, 0x5582B7U, 0x559A5CU, + 0x55AB89U, 0x55B362U, 0x55C820U, 0x55D0CBU, 0x55E11EU, 0x55F9F5U, 0x560ADBU, 0x561230U, 0x5623E5U, 0x563B0EU, + 0x56404CU, 0x5658A7U, 0x566972U, 0x567199U, 0x56871DU, 0x569FF6U, 0x56AE23U, 0x56B6C8U, 0x56CD8AU, 0x56D561U, + 0x56E4B4U, 0x56FC5FU, 0x5709BCU, 0x571157U, 0x572082U, 0x573869U, 0x57432BU, 0x575BC0U, 0x576A15U, 0x5772FEU, + 0x57847AU, 0x579C91U, 0x57AD44U, 0x57B5AFU, 0x57CEEDU, 0x57D606U, 0x57E7D3U, 0x57FF38U, 0x580255U, 0x581ABEU, + 0x582B6BU, 0x583380U, 0x5848C2U, 0x585029U, 0x5861FCU, 0x587917U, 0x588F93U, 0x589778U, 0x58A6ADU, 0x58BE46U, + 0x58C504U, 0x58DDEFU, 0x58EC3AU, 0x58F4D1U, 0x590132U, 0x5919D9U, 0x59280CU, 0x5930E7U, 0x594BA5U, 0x59534EU, + 0x59629BU, 0x597A70U, 0x598CF4U, 0x59941FU, 0x59A5CAU, 0x59BD21U, 0x59C663U, 0x59DE88U, 0x59EF5DU, 0x59F7B6U, + 0x5A0498U, 0x5A1C73U, 0x5A2DA6U, 0x5A354DU, 0x5A4E0FU, 0x5A56E4U, 0x5A6731U, 0x5A7FDAU, 0x5A895EU, 0x5A91B5U, + 0x5AA060U, 0x5AB88BU, 0x5AC3C9U, 0x5ADB22U, 0x5AEAF7U, 0x5AF21CU, 0x5B07FFU, 0x5B1F14U, 0x5B2EC1U, 0x5B362AU, + 0x5B4D68U, 0x5B5583U, 0x5B6456U, 0x5B7CBDU, 0x5B8A39U, 0x5B92D2U, 0x5BA307U, 0x5BBBECU, 0x5BC0AEU, 0x5BD845U, + 0x5BE990U, 0x5BF17BU, 0x5C0FCCU, 0x5C1727U, 0x5C26F2U, 0x5C3E19U, 0x5C455BU, 0x5C5DB0U, 0x5C6C65U, 0x5C748EU, + 0x5C820AU, 0x5C9AE1U, 0x5CAB34U, 0x5CB3DFU, 0x5CC89DU, 0x5CD076U, 0x5CE1A3U, 0x5CF948U, 0x5D0CABU, 0x5D1440U, + 0x5D2595U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED7U, 0x5D6F02U, 0x5D77E9U, 0x5D816DU, 0x5D9986U, 0x5DA853U, 0x5DB0B8U, + 0x5DCBFAU, 0x5DD311U, 0x5DE2C4U, 0x5DFA2FU, 0x5E0901U, 0x5E11EAU, 0x5E203FU, 0x5E38D4U, 0x5E4396U, 0x5E5B7DU, + 0x5E6AA8U, 0x5E7243U, 0x5E84C7U, 0x5E9C2CU, 0x5EADF9U, 0x5EB512U, 0x5ECE50U, 0x5ED6BBU, 0x5EE76EU, 0x5EFF85U, + 0x5F0A66U, 0x5F128DU, 0x5F2358U, 0x5F3BB3U, 0x5F40F1U, 0x5F581AU, 0x5F69CFU, 0x5F7124U, 0x5F87A0U, 0x5F9F4BU, + 0x5FAE9EU, 0x5FB675U, 0x5FCD37U, 0x5FD5DCU, 0x5FE409U, 0x5FFCE2U, 0x600953U, 0x6011B8U, 0x60206DU, 0x603886U, + 0x6043C4U, 0x605B2FU, 0x606AFAU, 0x607211U, 0x608495U, 0x609C7EU, 0x60ADABU, 0x60B540U, 0x60CE02U, 0x60D6E9U, + 0x60E73CU, 0x60FFD7U, 0x610A34U, 0x6112DFU, 0x61230AU, 0x613BE1U, 0x6140A3U, 0x615848U, 0x61699DU, 0x617176U, + 0x6187F2U, 0x619F19U, 0x61AECCU, 0x61B627U, 0x61CD65U, 0x61D58EU, 0x61E45BU, 0x61FCB0U, 0x620F9EU, 0x621775U, + 0x6226A0U, 0x623E4BU, 0x624509U, 0x625DE2U, 0x626C37U, 0x6274DCU, 0x628258U, 0x629AB3U, 0x62AB66U, 0x62B38DU, + 0x62C8CFU, 0x62D024U, 0x62E1F1U, 0x62F91AU, 0x630CF9U, 0x631412U, 0x6325C7U, 0x633D2CU, 0x63466EU, 0x635E85U, + 0x636F50U, 0x6377BBU, 0x63813FU, 0x6399D4U, 0x63A801U, 0x63B0EAU, 0x63CBA8U, 0x63D343U, 0x63E296U, 0x63FA7DU, + 0x6404CAU, 0x641C21U, 0x642DF4U, 0x64351FU, 0x644E5DU, 0x6456B6U, 0x646763U, 0x647F88U, 0x64890CU, 0x6491E7U, + 0x64A032U, 0x64B8D9U, 0x64C39BU, 0x64DB70U, 0x64EAA5U, 0x64F24EU, 0x6507ADU, 0x651F46U, 0x652E93U, 0x653678U, + 0x654D3AU, 0x6555D1U, 0x656404U, 0x657CEFU, 0x658A6BU, 0x659280U, 0x65A355U, 0x65BBBEU, 0x65C0FCU, 0x65D817U, + 0x65E9C2U, 0x65F129U, 0x660207U, 0x661AECU, 0x662B39U, 0x6633D2U, 0x664890U, 0x66507BU, 0x6661AEU, 0x667945U, + 0x668FC1U, 0x66972AU, 0x66A6FFU, 0x66BE14U, 0x66C556U, 0x66DDBDU, 0x66EC68U, 0x66F483U, 0x670160U, 0x67198BU, + 0x67285EU, 0x6730B5U, 0x674BF7U, 0x67531CU, 0x6762C9U, 0x677A22U, 0x678CA6U, 0x67944DU, 0x67A598U, 0x67BD73U, + 0x67C631U, 0x67DEDAU, 0x67EF0FU, 0x67F7E4U, 0x680A89U, 0x681262U, 0x6823B7U, 0x683B5CU, 0x68401EU, 0x6858F5U, + 0x686920U, 0x6871CBU, 0x68874FU, 0x689FA4U, 0x68AE71U, 0x68B69AU, 0x68CDD8U, 0x68D533U, 0x68E4E6U, 0x68FC0DU, + 0x6909EEU, 0x691105U, 0x6920D0U, 0x69383BU, 0x694379U, 0x695B92U, 0x696A47U, 0x6972ACU, 0x698428U, 0x699CC3U, + 0x69AD16U, 0x69B5FDU, 0x69CEBFU, 0x69D654U, 0x69E781U, 0x69FF6AU, 0x6A0C44U, 0x6A14AFU, 0x6A257AU, 0x6A3D91U, + 0x6A46D3U, 0x6A5E38U, 0x6A6FEDU, 0x6A7706U, 0x6A8182U, 0x6A9969U, 0x6AA8BCU, 0x6AB057U, 0x6ACB15U, 0x6AD3FEU, + 0x6AE22BU, 0x6AFAC0U, 0x6B0F23U, 0x6B17C8U, 0x6B261DU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5FU, 0x6B6C8AU, 0x6B7461U, + 0x6B82E5U, 0x6B9A0EU, 0x6BABDBU, 0x6BB330U, 0x6BC872U, 0x6BD099U, 0x6BE14CU, 0x6BF9A7U, 0x6C0710U, 0x6C1FFBU, + 0x6C2E2EU, 0x6C36C5U, 0x6C4D87U, 0x6C556CU, 0x6C64B9U, 0x6C7C52U, 0x6C8AD6U, 0x6C923DU, 0x6CA3E8U, 0x6CBB03U, + 0x6CC041U, 0x6CD8AAU, 0x6CE97FU, 0x6CF194U, 0x6D0477U, 0x6D1C9CU, 0x6D2D49U, 0x6D35A2U, 0x6D4EE0U, 0x6D560BU, + 0x6D67DEU, 0x6D7F35U, 0x6D89B1U, 0x6D915AU, 0x6DA08FU, 0x6DB864U, 0x6DC326U, 0x6DDBCDU, 0x6DEA18U, 0x6DF2F3U, + 0x6E01DDU, 0x6E1936U, 0x6E28E3U, 0x6E3008U, 0x6E4B4AU, 0x6E53A1U, 0x6E6274U, 0x6E7A9FU, 0x6E8C1BU, 0x6E94F0U, + 0x6EA525U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE67U, 0x6EEFB2U, 0x6EF759U, 0x6F02BAU, 0x6F1A51U, 0x6F2B84U, 0x6F336FU, + 0x6F482DU, 0x6F50C6U, 0x6F6113U, 0x6F79F8U, 0x6F8F7CU, 0x6F9797U, 0x6FA642U, 0x6FBEA9U, 0x6FC5EBU, 0x6FDD00U, + 0x6FECD5U, 0x6FF43EU, 0x700EE7U, 0x70160CU, 0x7027D9U, 0x703F32U, 0x704470U, 0x705C9BU, 0x706D4EU, 0x7075A5U, + 0x708321U, 0x709BCAU, 0x70AA1FU, 0x70B2F4U, 0x70C9B6U, 0x70D15DU, 0x70E088U, 0x70F863U, 0x710D80U, 0x71156BU, + 0x7124BEU, 0x713C55U, 0x714717U, 0x715FFCU, 0x716E29U, 0x7176C2U, 0x718046U, 0x7198ADU, 0x71A978U, 0x71B193U, + 0x71CAD1U, 0x71D23AU, 0x71E3EFU, 0x71FB04U, 0x72082AU, 0x7210C1U, 0x722114U, 0x7239FFU, 0x7242BDU, 0x725A56U, + 0x726B83U, 0x727368U, 0x7285ECU, 0x729D07U, 0x72ACD2U, 0x72B439U, 0x72CF7BU, 0x72D790U, 0x72E645U, 0x72FEAEU, + 0x730B4DU, 0x7313A6U, 0x732273U, 0x733A98U, 0x7341DAU, 0x735931U, 0x7368E4U, 0x73700FU, 0x73868BU, 0x739E60U, + 0x73AFB5U, 0x73B75EU, 0x73CC1CU, 0x73D4F7U, 0x73E522U, 0x73FDC9U, 0x74037EU, 0x741B95U, 0x742A40U, 0x7432ABU, + 0x7449E9U, 0x745102U, 0x7460D7U, 0x74783CU, 0x748EB8U, 0x749653U, 0x74A786U, 0x74BF6DU, 0x74C42FU, 0x74DCC4U, + 0x74ED11U, 0x74F5FAU, 0x750019U, 0x7518F2U, 0x752927U, 0x7531CCU, 0x754A8EU, 0x755265U, 0x7563B0U, 0x757B5BU, + 0x758DDFU, 0x759534U, 0x75A4E1U, 0x75BC0AU, 0x75C748U, 0x75DFA3U, 0x75EE76U, 0x75F69DU, 0x7605B3U, 0x761D58U, + 0x762C8DU, 0x763466U, 0x764F24U, 0x7657CFU, 0x76661AU, 0x767EF1U, 0x768875U, 0x76909EU, 0x76A14BU, 0x76B9A0U, + 0x76C2E2U, 0x76DA09U, 0x76EBDCU, 0x76F337U, 0x7706D4U, 0x771E3FU, 0x772FEAU, 0x773701U, 0x774C43U, 0x7754A8U, + 0x77657DU, 0x777D96U, 0x778B12U, 0x7793F9U, 0x77A22CU, 0x77BAC7U, 0x77C185U, 0x77D96EU, 0x77E8BBU, 0x77F050U, + 0x780D3DU, 0x7815D6U, 0x782403U, 0x783CE8U, 0x7847AAU, 0x785F41U, 0x786E94U, 0x78767FU, 0x7880FBU, 0x789810U, + 0x78A9C5U, 0x78B12EU, 0x78CA6CU, 0x78D287U, 0x78E352U, 0x78FBB9U, 0x790E5AU, 0x7916B1U, 0x792764U, 0x793F8FU, + 0x7944CDU, 0x795C26U, 0x796DF3U, 0x797518U, 0x79839CU, 0x799B77U, 0x79AAA2U, 0x79B249U, 0x79C90BU, 0x79D1E0U, + 0x79E035U, 0x79F8DEU, 0x7A0BF0U, 0x7A131BU, 0x7A22CEU, 0x7A3A25U, 0x7A4167U, 0x7A598CU, 0x7A6859U, 0x7A70B2U, + 0x7A8636U, 0x7A9EDDU, 0x7AAF08U, 0x7AB7E3U, 0x7ACCA1U, 0x7AD44AU, 0x7AE59FU, 0x7AFD74U, 0x7B0897U, 0x7B107CU, + 0x7B21A9U, 0x7B3942U, 0x7B4200U, 0x7B5AEBU, 0x7B6B3EU, 0x7B73D5U, 0x7B8551U, 0x7B9DBAU, 0x7BAC6FU, 0x7BB484U, + 0x7BCFC6U, 0x7BD72DU, 0x7BE6F8U, 0x7BFE13U, 0x7C00A4U, 0x7C184FU, 0x7C299AU, 0x7C3171U, 0x7C4A33U, 0x7C52D8U, + 0x7C630DU, 0x7C7BE6U, 0x7C8D62U, 0x7C9589U, 0x7CA45CU, 0x7CBCB7U, 0x7CC7F5U, 0x7CDF1EU, 0x7CEECBU, 0x7CF620U, + 0x7D03C3U, 0x7D1B28U, 0x7D2AFDU, 0x7D3216U, 0x7D4954U, 0x7D51BFU, 0x7D606AU, 0x7D7881U, 0x7D8E05U, 0x7D96EEU, + 0x7DA73BU, 0x7DBFD0U, 0x7DC492U, 0x7DDC79U, 0x7DEDACU, 0x7DF547U, 0x7E0669U, 0x7E1E82U, 0x7E2F57U, 0x7E37BCU, + 0x7E4CFEU, 0x7E5415U, 0x7E65C0U, 0x7E7D2BU, 0x7E8BAFU, 0x7E9344U, 0x7EA291U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D3U, + 0x7EE806U, 0x7EF0EDU, 0x7F050EU, 0x7F1DE5U, 0x7F2C30U, 0x7F34DBU, 0x7F4F99U, 0x7F5772U, 0x7F66A7U, 0x7F7E4CU, + 0x7F88C8U, 0x7F9023U, 0x7FA1F6U, 0x7FB91DU, 0x7FC25FU, 0x7FDAB4U, 0x7FEB61U, 0x7FF38AU, 0x800C75U, 0x80149EU, + 0x80254BU, 0x803DA0U, 0x8046E2U, 0x805E09U, 0x806FDCU, 0x807737U, 0x8081B3U, 0x809958U, 0x80A88DU, 0x80B066U, + 0x80CB24U, 0x80D3CFU, 0x80E21AU, 0x80FAF1U, 0x810F12U, 0x8117F9U, 0x81262CU, 0x813EC7U, 0x814585U, 0x815D6EU, + 0x816CBBU, 0x817450U, 0x8182D4U, 0x819A3FU, 0x81ABEAU, 0x81B301U, 0x81C843U, 0x81D0A8U, 0x81E17DU, 0x81F996U, + 0x820AB8U, 0x821253U, 0x822386U, 0x823B6DU, 0x82402FU, 0x8258C4U, 0x826911U, 0x8271FAU, 0x82877EU, 0x829F95U, + 0x82AE40U, 0x82B6ABU, 0x82CDE9U, 0x82D502U, 0x82E4D7U, 0x82FC3CU, 0x8309DFU, 0x831134U, 0x8320E1U, 0x83380AU, + 0x834348U, 0x835BA3U, 0x836A76U, 0x83729DU, 0x838419U, 0x839CF2U, 0x83AD27U, 0x83B5CCU, 0x83CE8EU, 0x83D665U, + 0x83E7B0U, 0x83FF5BU, 0x8401ECU, 0x841907U, 0x8428D2U, 0x843039U, 0x844B7BU, 0x845390U, 0x846245U, 0x847AAEU, + 0x848C2AU, 0x8494C1U, 0x84A514U, 0x84BDFFU, 0x84C6BDU, 0x84DE56U, 0x84EF83U, 0x84F768U, 0x85028BU, 0x851A60U, + 0x852BB5U, 0x85335EU, 0x85481CU, 0x8550F7U, 0x856122U, 0x8579C9U, 0x858F4DU, 0x8597A6U, 0x85A673U, 0x85BE98U, + 0x85C5DAU, 0x85DD31U, 0x85ECE4U, 0x85F40FU, 0x860721U, 0x861FCAU, 0x862E1FU, 0x8636F4U, 0x864DB6U, 0x86555DU, + 0x866488U, 0x867C63U, 0x868AE7U, 0x86920CU, 0x86A3D9U, 0x86BB32U, 0x86C070U, 0x86D89BU, 0x86E94EU, 0x86F1A5U, + 0x870446U, 0x871CADU, 0x872D78U, 0x873593U, 0x874ED1U, 0x87563AU, 0x8767EFU, 0x877F04U, 0x878980U, 0x87916BU, + 0x87A0BEU, 0x87B855U, 0x87C317U, 0x87DBFCU, 0x87EA29U, 0x87F2C2U, 0x880FAFU, 0x881744U, 0x882691U, 0x883E7AU, + 0x884538U, 0x885DD3U, 0x886C06U, 0x8874EDU, 0x888269U, 0x889A82U, 0x88AB57U, 0x88B3BCU, 0x88C8FEU, 0x88D015U, + 0x88E1C0U, 0x88F92BU, 0x890CC8U, 0x891423U, 0x8925F6U, 0x893D1DU, 0x89465FU, 0x895EB4U, 0x896F61U, 0x89778AU, + 0x89810EU, 0x8999E5U, 0x89A830U, 0x89B0DBU, 0x89CB99U, 0x89D372U, 0x89E2A7U, 0x89FA4CU, 0x8A0962U, 0x8A1189U, + 0x8A205CU, 0x8A38B7U, 0x8A43F5U, 0x8A5B1EU, 0x8A6ACBU, 0x8A7220U, 0x8A84A4U, 0x8A9C4FU, 0x8AAD9AU, 0x8AB571U, + 0x8ACE33U, 0x8AD6D8U, 0x8AE70DU, 0x8AFFE6U, 0x8B0A05U, 0x8B12EEU, 0x8B233BU, 0x8B3BD0U, 0x8B4092U, 0x8B5879U, + 0x8B69ACU, 0x8B7147U, 0x8B87C3U, 0x8B9F28U, 0x8BAEFDU, 0x8BB616U, 0x8BCD54U, 0x8BD5BFU, 0x8BE46AU, 0x8BFC81U, + 0x8C0236U, 0x8C1ADDU, 0x8C2B08U, 0x8C33E3U, 0x8C48A1U, 0x8C504AU, 0x8C619FU, 0x8C7974U, 0x8C8FF0U, 0x8C971BU, + 0x8CA6CEU, 0x8CBE25U, 0x8CC567U, 0x8CDD8CU, 0x8CEC59U, 0x8CF4B2U, 0x8D0151U, 0x8D19BAU, 0x8D286FU, 0x8D3084U, + 0x8D4BC6U, 0x8D532DU, 0x8D62F8U, 0x8D7A13U, 0x8D8C97U, 0x8D947CU, 0x8DA5A9U, 0x8DBD42U, 0x8DC600U, 0x8DDEEBU, + 0x8DEF3EU, 0x8DF7D5U, 0x8E04FBU, 0x8E1C10U, 0x8E2DC5U, 0x8E352EU, 0x8E4E6CU, 0x8E5687U, 0x8E6752U, 0x8E7FB9U, + 0x8E893DU, 0x8E91D6U, 0x8EA003U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB41U, 0x8EEA94U, 0x8EF27FU, 0x8F079CU, 0x8F1F77U, + 0x8F2EA2U, 0x8F3649U, 0x8F4D0BU, 0x8F55E0U, 0x8F6435U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B1U, 0x8FA364U, 0x8FBB8FU, + 0x8FC0CDU, 0x8FD826U, 0x8FE9F3U, 0x8FF118U, 0x900BC1U, 0x90132AU, 0x9022FFU, 0x903A14U, 0x904156U, 0x9059BDU, + 0x906868U, 0x907083U, 0x908607U, 0x909EECU, 0x90AF39U, 0x90B7D2U, 0x90CC90U, 0x90D47BU, 0x90E5AEU, 0x90FD45U, + 0x9108A6U, 0x91104DU, 0x912198U, 0x913973U, 0x914231U, 0x915ADAU, 0x916B0FU, 0x9173E4U, 0x918560U, 0x919D8BU, + 0x91AC5EU, 0x91B4B5U, 0x91CFF7U, 0x91D71CU, 0x91E6C9U, 0x91FE22U, 0x920D0CU, 0x9215E7U, 0x922432U, 0x923CD9U, + 0x92479BU, 0x925F70U, 0x926EA5U, 0x92764EU, 0x9280CAU, 0x929821U, 0x92A9F4U, 0x92B11FU, 0x92CA5DU, 0x92D2B6U, + 0x92E363U, 0x92FB88U, 0x930E6BU, 0x931680U, 0x932755U, 0x933FBEU, 0x9344FCU, 0x935C17U, 0x936DC2U, 0x937529U, + 0x9383ADU, 0x939B46U, 0x93AA93U, 0x93B278U, 0x93C93AU, 0x93D1D1U, 0x93E004U, 0x93F8EFU, 0x940658U, 0x941EB3U, + 0x942F66U, 0x94378DU, 0x944CCFU, 0x945424U, 0x9465F1U, 0x947D1AU, 0x948B9EU, 0x949375U, 0x94A2A0U, 0x94BA4BU, + 0x94C109U, 0x94D9E2U, 0x94E837U, 0x94F0DCU, 0x95053FU, 0x951DD4U, 0x952C01U, 0x9534EAU, 0x954FA8U, 0x955743U, + 0x956696U, 0x957E7DU, 0x9588F9U, 0x959012U, 0x95A1C7U, 0x95B92CU, 0x95C26EU, 0x95DA85U, 0x95EB50U, 0x95F3BBU, + 0x960095U, 0x96187EU, 0x9629ABU, 0x963140U, 0x964A02U, 0x9652E9U, 0x96633CU, 0x967BD7U, 0x968D53U, 0x9695B8U, + 0x96A46DU, 0x96BC86U, 0x96C7C4U, 0x96DF2FU, 0x96EEFAU, 0x96F611U, 0x9703F2U, 0x971B19U, 0x972ACCU, 0x973227U, + 0x974965U, 0x97518EU, 0x97605BU, 0x9778B0U, 0x978E34U, 0x9796DFU, 0x97A70AU, 0x97BFE1U, 0x97C4A3U, 0x97DC48U, + 0x97ED9DU, 0x97F576U, 0x98081BU, 0x9810F0U, 0x982125U, 0x9839CEU, 0x98428CU, 0x985A67U, 0x986BB2U, 0x987359U, + 0x9885DDU, 0x989D36U, 0x98ACE3U, 0x98B408U, 0x98CF4AU, 0x98D7A1U, 0x98E674U, 0x98FE9FU, 0x990B7CU, 0x991397U, + 0x992242U, 0x993AA9U, 0x9941EBU, 0x995900U, 0x9968D5U, 0x99703EU, 0x9986BAU, 0x999E51U, 0x99AF84U, 0x99B76FU, + 0x99CC2DU, 0x99D4C6U, 0x99E513U, 0x99FDF8U, 0x9A0ED6U, 0x9A163DU, 0x9A27E8U, 0x9A3F03U, 0x9A4441U, 0x9A5CAAU, + 0x9A6D7FU, 0x9A7594U, 0x9A8310U, 0x9A9BFBU, 0x9AAA2EU, 0x9AB2C5U, 0x9AC987U, 0x9AD16CU, 0x9AE0B9U, 0x9AF852U, + 0x9B0DB1U, 0x9B155AU, 0x9B248FU, 0x9B3C64U, 0x9B4726U, 0x9B5FCDU, 0x9B6E18U, 0x9B76F3U, 0x9B8077U, 0x9B989CU, + 0x9BA949U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20BU, 0x9BE3DEU, 0x9BFB35U, 0x9C0582U, 0x9C1D69U, 0x9C2CBCU, 0x9C3457U, + 0x9C4F15U, 0x9C57FEU, 0x9C662BU, 0x9C7EC0U, 0x9C8844U, 0x9C90AFU, 0x9CA17AU, 0x9CB991U, 0x9CC2D3U, 0x9CDA38U, + 0x9CEBEDU, 0x9CF306U, 0x9D06E5U, 0x9D1E0EU, 0x9D2FDBU, 0x9D3730U, 0x9D4C72U, 0x9D5499U, 0x9D654CU, 0x9D7DA7U, + 0x9D8B23U, 0x9D93C8U, 0x9DA21DU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95FU, 0x9DE88AU, 0x9DF061U, 0x9E034FU, 0x9E1BA4U, + 0x9E2A71U, 0x9E329AU, 0x9E49D8U, 0x9E5133U, 0x9E60E6U, 0x9E780DU, 0x9E8E89U, 0x9E9662U, 0x9EA7B7U, 0x9EBF5CU, + 0x9EC41EU, 0x9EDCF5U, 0x9EED20U, 0x9EF5CBU, 0x9F0028U, 0x9F18C3U, 0x9F2916U, 0x9F31FDU, 0x9F4ABFU, 0x9F5254U, + 0x9F6381U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9505U, 0x9FA4D0U, 0x9FBC3BU, 0x9FC779U, 0x9FDF92U, 0x9FEE47U, 0x9FF6ACU, + 0xA0031DU, 0xA01BF6U, 0xA02A23U, 0xA032C8U, 0xA0498AU, 0xA05161U, 0xA060B4U, 0xA0785FU, 0xA08EDBU, 0xA09630U, + 0xA0A7E5U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA7U, 0xA0ED72U, 0xA0F599U, 0xA1007AU, 0xA11891U, 0xA12944U, 0xA131AFU, + 0xA14AEDU, 0xA15206U, 0xA163D3U, 0xA17B38U, 0xA18DBCU, 0xA19557U, 0xA1A482U, 0xA1BC69U, 0xA1C72BU, 0xA1DFC0U, + 0xA1EE15U, 0xA1F6FEU, 0xA205D0U, 0xA21D3BU, 0xA22CEEU, 0xA23405U, 0xA24F47U, 0xA257ACU, 0xA26679U, 0xA27E92U, + 0xA28816U, 0xA290FDU, 0xA2A128U, 0xA2B9C3U, 0xA2C281U, 0xA2DA6AU, 0xA2EBBFU, 0xA2F354U, 0xA306B7U, 0xA31E5CU, + 0xA32F89U, 0xA33762U, 0xA34C20U, 0xA354CBU, 0xA3651EU, 0xA37DF5U, 0xA38B71U, 0xA3939AU, 0xA3A24FU, 0xA3BAA4U, + 0xA3C1E6U, 0xA3D90DU, 0xA3E8D8U, 0xA3F033U, 0xA40E84U, 0xA4166FU, 0xA427BAU, 0xA43F51U, 0xA44413U, 0xA45CF8U, + 0xA46D2DU, 0xA475C6U, 0xA48342U, 0xA49BA9U, 0xA4AA7CU, 0xA4B297U, 0xA4C9D5U, 0xA4D13EU, 0xA4E0EBU, 0xA4F800U, + 0xA50DE3U, 0xA51508U, 0xA524DDU, 0xA53C36U, 0xA54774U, 0xA55F9FU, 0xA56E4AU, 0xA576A1U, 0xA58025U, 0xA598CEU, + 0xA5A91BU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D259U, 0xA5E38CU, 0xA5FB67U, 0xA60849U, 0xA610A2U, 0xA62177U, 0xA6399CU, + 0xA642DEU, 0xA65A35U, 0xA66BE0U, 0xA6730BU, 0xA6858FU, 0xA69D64U, 0xA6ACB1U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F3U, + 0xA6E626U, 0xA6FECDU, 0xA70B2EU, 0xA713C5U, 0xA72210U, 0xA73AFBU, 0xA741B9U, 0xA75952U, 0xA76887U, 0xA7706CU, + 0xA786E8U, 0xA79E03U, 0xA7AFD6U, 0xA7B73DU, 0xA7CC7FU, 0xA7D494U, 0xA7E541U, 0xA7FDAAU, 0xA800C7U, 0xA8182CU, + 0xA829F9U, 0xA83112U, 0xA84A50U, 0xA852BBU, 0xA8636EU, 0xA87B85U, 0xA88D01U, 0xA895EAU, 0xA8A43FU, 0xA8BCD4U, + 0xA8C796U, 0xA8DF7DU, 0xA8EEA8U, 0xA8F643U, 0xA903A0U, 0xA91B4BU, 0xA92A9EU, 0xA93275U, 0xA94937U, 0xA951DCU, + 0xA96009U, 0xA978E2U, 0xA98E66U, 0xA9968DU, 0xA9A758U, 0xA9BFB3U, 0xA9C4F1U, 0xA9DC1AU, 0xA9EDCFU, 0xA9F524U, + 0xAA060AU, 0xAA1EE1U, 0xAA2F34U, 0xAA37DFU, 0xAA4C9DU, 0xAA5476U, 0xAA65A3U, 0xAA7D48U, 0xAA8BCCU, 0xAA9327U, + 0xAAA2F2U, 0xAABA19U, 0xAAC15BU, 0xAAD9B0U, 0xAAE865U, 0xAAF08EU, 0xAB056DU, 0xAB1D86U, 0xAB2C53U, 0xAB34B8U, + 0xAB4FFAU, 0xAB5711U, 0xAB66C4U, 0xAB7E2FU, 0xAB88ABU, 0xAB9040U, 0xABA195U, 0xABB97EU, 0xABC23CU, 0xABDAD7U, + 0xABEB02U, 0xABF3E9U, 0xAC0D5EU, 0xAC15B5U, 0xAC2460U, 0xAC3C8BU, 0xAC47C9U, 0xAC5F22U, 0xAC6EF7U, 0xAC761CU, + 0xAC8098U, 0xAC9873U, 0xACA9A6U, 0xACB14DU, 0xACCA0FU, 0xACD2E4U, 0xACE331U, 0xACFBDAU, 0xAD0E39U, 0xAD16D2U, + 0xAD2707U, 0xAD3FECU, 0xAD44AEU, 0xAD5C45U, 0xAD6D90U, 0xAD757BU, 0xAD83FFU, 0xAD9B14U, 0xADAAC1U, 0xADB22AU, + 0xADC968U, 0xADD183U, 0xADE056U, 0xADF8BDU, 0xAE0B93U, 0xAE1378U, 0xAE22ADU, 0xAE3A46U, 0xAE4104U, 0xAE59EFU, + 0xAE683AU, 0xAE70D1U, 0xAE8655U, 0xAE9EBEU, 0xAEAF6BU, 0xAEB780U, 0xAECCC2U, 0xAED429U, 0xAEE5FCU, 0xAEFD17U, + 0xAF08F4U, 0xAF101FU, 0xAF21CAU, 0xAF3921U, 0xAF4263U, 0xAF5A88U, 0xAF6B5DU, 0xAF73B6U, 0xAF8532U, 0xAF9DD9U, + 0xAFAC0CU, 0xAFB4E7U, 0xAFCFA5U, 0xAFD74EU, 0xAFE69BU, 0xAFFE70U, 0xB004A9U, 0xB01C42U, 0xB02D97U, 0xB0357CU, + 0xB04E3EU, 0xB056D5U, 0xB06700U, 0xB07FEBU, 0xB0896FU, 0xB09184U, 0xB0A051U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB13U, + 0xB0EAC6U, 0xB0F22DU, 0xB107CEU, 0xB11F25U, 0xB12EF0U, 0xB1361BU, 0xB14D59U, 0xB155B2U, 0xB16467U, 0xB17C8CU, + 0xB18A08U, 0xB192E3U, 0xB1A336U, 0xB1BBDDU, 0xB1C09FU, 0xB1D874U, 0xB1E9A1U, 0xB1F14AU, 0xB20264U, 0xB21A8FU, + 0xB22B5AU, 0xB233B1U, 0xB248F3U, 0xB25018U, 0xB261CDU, 0xB27926U, 0xB28FA2U, 0xB29749U, 0xB2A69CU, 0xB2BE77U, + 0xB2C535U, 0xB2DDDEU, 0xB2EC0BU, 0xB2F4E0U, 0xB30103U, 0xB319E8U, 0xB3283DU, 0xB330D6U, 0xB34B94U, 0xB3537FU, + 0xB362AAU, 0xB37A41U, 0xB38CC5U, 0xB3942EU, 0xB3A5FBU, 0xB3BD10U, 0xB3C652U, 0xB3DEB9U, 0xB3EF6CU, 0xB3F787U, + 0xB40930U, 0xB411DBU, 0xB4200EU, 0xB438E5U, 0xB443A7U, 0xB45B4CU, 0xB46A99U, 0xB47272U, 0xB484F6U, 0xB49C1DU, + 0xB4ADC8U, 0xB4B523U, 0xB4CE61U, 0xB4D68AU, 0xB4E75FU, 0xB4FFB4U, 0xB50A57U, 0xB512BCU, 0xB52369U, 0xB53B82U, + 0xB540C0U, 0xB5582BU, 0xB569FEU, 0xB57115U, 0xB58791U, 0xB59F7AU, 0xB5AEAFU, 0xB5B644U, 0xB5CD06U, 0xB5D5EDU, + 0xB5E438U, 0xB5FCD3U, 0xB60FFDU, 0xB61716U, 0xB626C3U, 0xB63E28U, 0xB6456AU, 0xB65D81U, 0xB66C54U, 0xB674BFU, + 0xB6823BU, 0xB69AD0U, 0xB6AB05U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D047U, 0xB6E192U, 0xB6F979U, 0xB70C9AU, 0xB71471U, + 0xB725A4U, 0xB73D4FU, 0xB7460DU, 0xB75EE6U, 0xB76F33U, 0xB777D8U, 0xB7815CU, 0xB799B7U, 0xB7A862U, 0xB7B089U, + 0xB7CBCBU, 0xB7D320U, 0xB7E2F5U, 0xB7FA1EU, 0xB80773U, 0xB81F98U, 0xB82E4DU, 0xB836A6U, 0xB84DE4U, 0xB8550FU, + 0xB864DAU, 0xB87C31U, 0xB88AB5U, 0xB8925EU, 0xB8A38BU, 0xB8BB60U, 0xB8C022U, 0xB8D8C9U, 0xB8E91CU, 0xB8F1F7U, + 0xB90414U, 0xB91CFFU, 0xB92D2AU, 0xB935C1U, 0xB94E83U, 0xB95668U, 0xB967BDU, 0xB97F56U, 0xB989D2U, 0xB99139U, + 0xB9A0ECU, 0xB9B807U, 0xB9C345U, 0xB9DBAEU, 0xB9EA7BU, 0xB9F290U, 0xBA01BEU, 0xBA1955U, 0xBA2880U, 0xBA306BU, + 0xBA4B29U, 0xBA53C2U, 0xBA6217U, 0xBA7AFCU, 0xBA8C78U, 0xBA9493U, 0xBAA546U, 0xBABDADU, 0xBAC6EFU, 0xBADE04U, + 0xBAEFD1U, 0xBAF73AU, 0xBB02D9U, 0xBB1A32U, 0xBB2BE7U, 0xBB330CU, 0xBB484EU, 0xBB50A5U, 0xBB6170U, 0xBB799BU, + 0xBB8F1FU, 0xBB97F4U, 0xBBA621U, 0xBBBECAU, 0xBBC588U, 0xBBDD63U, 0xBBECB6U, 0xBBF45DU, 0xBC0AEAU, 0xBC1201U, + 0xBC23D4U, 0xBC3B3FU, 0xBC407DU, 0xBC5896U, 0xBC6943U, 0xBC71A8U, 0xBC872CU, 0xBC9FC7U, 0xBCAE12U, 0xBCB6F9U, + 0xBCCDBBU, 0xBCD550U, 0xBCE485U, 0xBCFC6EU, 0xBD098DU, 0xBD1166U, 0xBD20B3U, 0xBD3858U, 0xBD431AU, 0xBD5BF1U, + 0xBD6A24U, 0xBD72CFU, 0xBD844BU, 0xBD9CA0U, 0xBDAD75U, 0xBDB59EU, 0xBDCEDCU, 0xBDD637U, 0xBDE7E2U, 0xBDFF09U, + 0xBE0C27U, 0xBE14CCU, 0xBE2519U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5BU, 0xBE6F8EU, 0xBE7765U, 0xBE81E1U, 0xBE990AU, + 0xBEA8DFU, 0xBEB034U, 0xBECB76U, 0xBED39DU, 0xBEE248U, 0xBEFAA3U, 0xBF0F40U, 0xBF17ABU, 0xBF267EU, 0xBF3E95U, + 0xBF45D7U, 0xBF5D3CU, 0xBF6CE9U, 0xBF7402U, 0xBF8286U, 0xBF9A6DU, 0xBFABB8U, 0xBFB353U, 0xBFC811U, 0xBFD0FAU, + 0xBFE12FU, 0xBFF9C4U, 0xC00A4EU, 0xC012A5U, 0xC02370U, 0xC03B9BU, 0xC040D9U, 0xC05832U, 0xC069E7U, 0xC0710CU, + 0xC08788U, 0xC09F63U, 0xC0AEB6U, 0xC0B65DU, 0xC0CD1FU, 0xC0D5F4U, 0xC0E421U, 0xC0FCCAU, 0xC10929U, 0xC111C2U, + 0xC12017U, 0xC138FCU, 0xC143BEU, 0xC15B55U, 0xC16A80U, 0xC1726BU, 0xC184EFU, 0xC19C04U, 0xC1ADD1U, 0xC1B53AU, + 0xC1CE78U, 0xC1D693U, 0xC1E746U, 0xC1FFADU, 0xC20C83U, 0xC21468U, 0xC225BDU, 0xC23D56U, 0xC24614U, 0xC25EFFU, + 0xC26F2AU, 0xC277C1U, 0xC28145U, 0xC299AEU, 0xC2A87BU, 0xC2B090U, 0xC2CBD2U, 0xC2D339U, 0xC2E2ECU, 0xC2FA07U, + 0xC30FE4U, 0xC3170FU, 0xC326DAU, 0xC33E31U, 0xC34573U, 0xC35D98U, 0xC36C4DU, 0xC374A6U, 0xC38222U, 0xC39AC9U, + 0xC3AB1CU, 0xC3B3F7U, 0xC3C8B5U, 0xC3D05EU, 0xC3E18BU, 0xC3F960U, 0xC407D7U, 0xC41F3CU, 0xC42EE9U, 0xC43602U, + 0xC44D40U, 0xC455ABU, 0xC4647EU, 0xC47C95U, 0xC48A11U, 0xC492FAU, 0xC4A32FU, 0xC4BBC4U, 0xC4C086U, 0xC4D86DU, + 0xC4E9B8U, 0xC4F153U, 0xC504B0U, 0xC51C5BU, 0xC52D8EU, 0xC53565U, 0xC54E27U, 0xC556CCU, 0xC56719U, 0xC57FF2U, + 0xC58976U, 0xC5919DU, 0xC5A048U, 0xC5B8A3U, 0xC5C3E1U, 0xC5DB0AU, 0xC5EADFU, 0xC5F234U, 0xC6011AU, 0xC619F1U, + 0xC62824U, 0xC630CFU, 0xC64B8DU, 0xC65366U, 0xC662B3U, 0xC67A58U, 0xC68CDCU, 0xC69437U, 0xC6A5E2U, 0xC6BD09U, + 0xC6C64BU, 0xC6DEA0U, 0xC6EF75U, 0xC6F79EU, 0xC7027DU, 0xC71A96U, 0xC72B43U, 0xC733A8U, 0xC748EAU, 0xC75001U, + 0xC761D4U, 0xC7793FU, 0xC78FBBU, 0xC79750U, 0xC7A685U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC7U, 0xC7EC12U, 0xC7F4F9U, + 0xC80994U, 0xC8117FU, 0xC820AAU, 0xC83841U, 0xC84303U, 0xC85BE8U, 0xC86A3DU, 0xC872D6U, 0xC88452U, 0xC89CB9U, + 0xC8AD6CU, 0xC8B587U, 0xC8CEC5U, 0xC8D62EU, 0xC8E7FBU, 0xC8FF10U, 0xC90AF3U, 0xC91218U, 0xC923CDU, 0xC93B26U, + 0xC94064U, 0xC9588FU, 0xC9695AU, 0xC971B1U, 0xC98735U, 0xC99FDEU, 0xC9AE0BU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D549U, + 0xC9E49CU, 0xC9FC77U, 0xCA0F59U, 0xCA17B2U, 0xCA2667U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D25U, 0xCA6CF0U, 0xCA741BU, + 0xCA829FU, 0xCA9A74U, 0xCAABA1U, 0xCAB34AU, 0xCAC808U, 0xCAD0E3U, 0xCAE136U, 0xCAF9DDU, 0xCB0C3EU, 0xCB14D5U, + 0xCB2500U, 0xCB3DEBU, 0xCB46A9U, 0xCB5E42U, 0xCB6F97U, 0xCB777CU, 0xCB81F8U, 0xCB9913U, 0xCBA8C6U, 0xCBB02DU, + 0xCBCB6FU, 0xCBD384U, 0xCBE251U, 0xCBFABAU, 0xCC040DU, 0xCC1CE6U, 0xCC2D33U, 0xCC35D8U, 0xCC4E9AU, 0xCC5671U, + 0xCC67A4U, 0xCC7F4FU, 0xCC89CBU, 0xCC9120U, 0xCCA0F5U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB7U, 0xCCEA62U, 0xCCF289U, + 0xCD076AU, 0xCD1F81U, 0xCD2E54U, 0xCD36BFU, 0xCD4DFDU, 0xCD5516U, 0xCD64C3U, 0xCD7C28U, 0xCD8AACU, 0xCD9247U, + 0xCDA392U, 0xCDBB79U, 0xCDC03BU, 0xCDD8D0U, 0xCDE905U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2BU, 0xCE2BFEU, 0xCE3315U, + 0xCE4857U, 0xCE50BCU, 0xCE6169U, 0xCE7982U, 0xCE8F06U, 0xCE97EDU, 0xCEA638U, 0xCEBED3U, 0xCEC591U, 0xCEDD7AU, + 0xCEECAFU, 0xCEF444U, 0xCF01A7U, 0xCF194CU, 0xCF2899U, 0xCF3072U, 0xCF4B30U, 0xCF53DBU, 0xCF620EU, 0xCF7AE5U, + 0xCF8C61U, 0xCF948AU, 0xCFA55FU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1DU, 0xCFEFC8U, 0xCFF723U, 0xD00DFAU, 0xD01511U, + 0xD024C4U, 0xD03C2FU, 0xD0476DU, 0xD05F86U, 0xD06E53U, 0xD076B8U, 0xD0803CU, 0xD098D7U, 0xD0A902U, 0xD0B1E9U, + 0xD0CAABU, 0xD0D240U, 0xD0E395U, 0xD0FB7EU, 0xD10E9DU, 0xD11676U, 0xD127A3U, 0xD13F48U, 0xD1440AU, 0xD15CE1U, + 0xD16D34U, 0xD175DFU, 0xD1835BU, 0xD19BB0U, 0xD1AA65U, 0xD1B28EU, 0xD1C9CCU, 0xD1D127U, 0xD1E0F2U, 0xD1F819U, + 0xD20B37U, 0xD213DCU, 0xD22209U, 0xD23AE2U, 0xD241A0U, 0xD2594BU, 0xD2689EU, 0xD27075U, 0xD286F1U, 0xD29E1AU, + 0xD2AFCFU, 0xD2B724U, 0xD2CC66U, 0xD2D48DU, 0xD2E558U, 0xD2FDB3U, 0xD30850U, 0xD310BBU, 0xD3216EU, 0xD33985U, + 0xD342C7U, 0xD35A2CU, 0xD36BF9U, 0xD37312U, 0xD38596U, 0xD39D7DU, 0xD3ACA8U, 0xD3B443U, 0xD3CF01U, 0xD3D7EAU, + 0xD3E63FU, 0xD3FED4U, 0xD40063U, 0xD41888U, 0xD4295DU, 0xD431B6U, 0xD44AF4U, 0xD4521FU, 0xD463CAU, 0xD47B21U, + 0xD48DA5U, 0xD4954EU, 0xD4A49BU, 0xD4BC70U, 0xD4C732U, 0xD4DFD9U, 0xD4EE0CU, 0xD4F6E7U, 0xD50304U, 0xD51BEFU, + 0xD52A3AU, 0xD532D1U, 0xD54993U, 0xD55178U, 0xD560ADU, 0xD57846U, 0xD58EC2U, 0xD59629U, 0xD5A7FCU, 0xD5BF17U, + 0xD5C455U, 0xD5DCBEU, 0xD5ED6BU, 0xD5F580U, 0xD606AEU, 0xD61E45U, 0xD62F90U, 0xD6377BU, 0xD64C39U, 0xD654D2U, + 0xD66507U, 0xD67DECU, 0xD68B68U, 0xD69383U, 0xD6A256U, 0xD6BABDU, 0xD6C1FFU, 0xD6D914U, 0xD6E8C1U, 0xD6F02AU, + 0xD705C9U, 0xD71D22U, 0xD72CF7U, 0xD7341CU, 0xD74F5EU, 0xD757B5U, 0xD76660U, 0xD77E8BU, 0xD7880FU, 0xD790E4U, + 0xD7A131U, 0xD7B9DAU, 0xD7C298U, 0xD7DA73U, 0xD7EBA6U, 0xD7F34DU, 0xD80E20U, 0xD816CBU, 0xD8271EU, 0xD83FF5U, + 0xD844B7U, 0xD85C5CU, 0xD86D89U, 0xD87562U, 0xD883E6U, 0xD89B0DU, 0xD8AAD8U, 0xD8B233U, 0xD8C971U, 0xD8D19AU, + 0xD8E04FU, 0xD8F8A4U, 0xD90D47U, 0xD915ACU, 0xD92479U, 0xD93C92U, 0xD947D0U, 0xD95F3BU, 0xD96EEEU, 0xD97605U, + 0xD98081U, 0xD9986AU, 0xD9A9BFU, 0xD9B154U, 0xD9CA16U, 0xD9D2FDU, 0xD9E328U, 0xD9FBC3U, 0xDA08EDU, 0xDA1006U, + 0xDA21D3U, 0xDA3938U, 0xDA427AU, 0xDA5A91U, 0xDA6B44U, 0xDA73AFU, 0xDA852BU, 0xDA9DC0U, 0xDAAC15U, 0xDAB4FEU, + 0xDACFBCU, 0xDAD757U, 0xDAE682U, 0xDAFE69U, 0xDB0B8AU, 0xDB1361U, 0xDB22B4U, 0xDB3A5FU, 0xDB411DU, 0xDB59F6U, + 0xDB6823U, 0xDB70C8U, 0xDB864CU, 0xDB9EA7U, 0xDBAF72U, 0xDBB799U, 0xDBCCDBU, 0xDBD430U, 0xDBE5E5U, 0xDBFD0EU, + 0xDC03B9U, 0xDC1B52U, 0xDC2A87U, 0xDC326CU, 0xDC492EU, 0xDC51C5U, 0xDC6010U, 0xDC78FBU, 0xDC8E7FU, 0xDC9694U, + 0xDCA741U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC03U, 0xDCEDD6U, 0xDCF53DU, 0xDD00DEU, 0xDD1835U, 0xDD29E0U, 0xDD310BU, + 0xDD4A49U, 0xDD52A2U, 0xDD6377U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F3U, 0xDDA426U, 0xDDBCCDU, 0xDDC78FU, 0xDDDF64U, + 0xDDEEB1U, 0xDDF65AU, 0xDE0574U, 0xDE1D9FU, 0xDE2C4AU, 0xDE34A1U, 0xDE4FE3U, 0xDE5708U, 0xDE66DDU, 0xDE7E36U, + 0xDE88B2U, 0xDE9059U, 0xDEA18CU, 0xDEB967U, 0xDEC225U, 0xDEDACEU, 0xDEEB1BU, 0xDEF3F0U, 0xDF0613U, 0xDF1EF8U, + 0xDF2F2DU, 0xDF37C6U, 0xDF4C84U, 0xDF546FU, 0xDF65BAU, 0xDF7D51U, 0xDF8BD5U, 0xDF933EU, 0xDFA2EBU, 0xDFBA00U, + 0xDFC142U, 0xDFD9A9U, 0xDFE87CU, 0xDFF097U, 0xE00526U, 0xE01DCDU, 0xE02C18U, 0xE034F3U, 0xE04FB1U, 0xE0575AU, + 0xE0668FU, 0xE07E64U, 0xE088E0U, 0xE0900BU, 0xE0A1DEU, 0xE0B935U, 0xE0C277U, 0xE0DA9CU, 0xE0EB49U, 0xE0F3A2U, + 0xE10641U, 0xE11EAAU, 0xE12F7FU, 0xE13794U, 0xE14CD6U, 0xE1543DU, 0xE165E8U, 0xE17D03U, 0xE18B87U, 0xE1936CU, + 0xE1A2B9U, 0xE1BA52U, 0xE1C110U, 0xE1D9FBU, 0xE1E82EU, 0xE1F0C5U, 0xE203EBU, 0xE21B00U, 0xE22AD5U, 0xE2323EU, + 0xE2497CU, 0xE25197U, 0xE26042U, 0xE278A9U, 0xE28E2DU, 0xE296C6U, 0xE2A713U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC51U, + 0xE2ED84U, 0xE2F56FU, 0xE3008CU, 0xE31867U, 0xE329B2U, 0xE33159U, 0xE34A1BU, 0xE352F0U, 0xE36325U, 0xE37BCEU, + 0xE38D4AU, 0xE395A1U, 0xE3A474U, 0xE3BC9FU, 0xE3C7DDU, 0xE3DF36U, 0xE3EEE3U, 0xE3F608U, 0xE408BFU, 0xE41054U, + 0xE42181U, 0xE4396AU, 0xE44228U, 0xE45AC3U, 0xE46B16U, 0xE473FDU, 0xE48579U, 0xE49D92U, 0xE4AC47U, 0xE4B4ACU, + 0xE4CFEEU, 0xE4D705U, 0xE4E6D0U, 0xE4FE3BU, 0xE50BD8U, 0xE51333U, 0xE522E6U, 0xE53A0DU, 0xE5414FU, 0xE559A4U, + 0xE56871U, 0xE5709AU, 0xE5861EU, 0xE59EF5U, 0xE5AF20U, 0xE5B7CBU, 0xE5CC89U, 0xE5D462U, 0xE5E5B7U, 0xE5FD5CU, + 0xE60E72U, 0xE61699U, 0xE6274CU, 0xE63FA7U, 0xE644E5U, 0xE65C0EU, 0xE66DDBU, 0xE67530U, 0xE683B4U, 0xE69B5FU, + 0xE6AA8AU, 0xE6B261U, 0xE6C923U, 0xE6D1C8U, 0xE6E01DU, 0xE6F8F6U, 0xE70D15U, 0xE715FEU, 0xE7242BU, 0xE73CC0U, + 0xE74782U, 0xE75F69U, 0xE76EBCU, 0xE77657U, 0xE780D3U, 0xE79838U, 0xE7A9EDU, 0xE7B106U, 0xE7CA44U, 0xE7D2AFU, + 0xE7E37AU, 0xE7FB91U, 0xE806FCU, 0xE81E17U, 0xE82FC2U, 0xE83729U, 0xE84C6BU, 0xE85480U, 0xE86555U, 0xE87DBEU, + 0xE88B3AU, 0xE893D1U, 0xE8A204U, 0xE8BAEFU, 0xE8C1ADU, 0xE8D946U, 0xE8E893U, 0xE8F078U, 0xE9059BU, 0xE91D70U, + 0xE92CA5U, 0xE9344EU, 0xE94F0CU, 0xE957E7U, 0xE96632U, 0xE97ED9U, 0xE9885DU, 0xE990B6U, 0xE9A163U, 0xE9B988U, + 0xE9C2CAU, 0xE9DA21U, 0xE9EBF4U, 0xE9F31FU, 0xEA0031U, 0xEA18DAU, 0xEA290FU, 0xEA31E4U, 0xEA4AA6U, 0xEA524DU, + 0xEA6398U, 0xEA7B73U, 0xEA8DF7U, 0xEA951CU, 0xEAA4C9U, 0xEABC22U, 0xEAC760U, 0xEADF8BU, 0xEAEE5EU, 0xEAF6B5U, + 0xEB0356U, 0xEB1BBDU, 0xEB2A68U, 0xEB3283U, 0xEB49C1U, 0xEB512AU, 0xEB60FFU, 0xEB7814U, 0xEB8E90U, 0xEB967BU, + 0xEBA7AEU, 0xEBBF45U, 0xEBC407U, 0xEBDCECU, 0xEBED39U, 0xEBF5D2U, 0xEC0B65U, 0xEC138EU, 0xEC225BU, 0xEC3AB0U, + 0xEC41F2U, 0xEC5919U, 0xEC68CCU, 0xEC7027U, 0xEC86A3U, 0xEC9E48U, 0xECAF9DU, 0xECB776U, 0xECCC34U, 0xECD4DFU, + 0xECE50AU, 0xECFDE1U, 0xED0802U, 0xED10E9U, 0xED213CU, 0xED39D7U, 0xED4295U, 0xED5A7EU, 0xED6BABU, 0xED7340U, + 0xED85C4U, 0xED9D2FU, 0xEDACFAU, 0xEDB411U, 0xEDCF53U, 0xEDD7B8U, 0xEDE66DU, 0xEDFE86U, 0xEE0DA8U, 0xEE1543U, + 0xEE2496U, 0xEE3C7DU, 0xEE473FU, 0xEE5FD4U, 0xEE6E01U, 0xEE76EAU, 0xEE806EU, 0xEE9885U, 0xEEA950U, 0xEEB1BBU, + 0xEECAF9U, 0xEED212U, 0xEEE3C7U, 0xEEFB2CU, 0xEF0ECFU, 0xEF1624U, 0xEF27F1U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB3U, + 0xEF6D66U, 0xEF758DU, 0xEF8309U, 0xEF9BE2U, 0xEFAA37U, 0xEFB2DCU, 0xEFC99EU, 0xEFD175U, 0xEFE0A0U, 0xEFF84BU, + 0xF00292U, 0xF01A79U, 0xF02BACU, 0xF03347U, 0xF04805U, 0xF050EEU, 0xF0613BU, 0xF079D0U, 0xF08F54U, 0xF097BFU, + 0xF0A66AU, 0xF0BE81U, 0xF0C5C3U, 0xF0DD28U, 0xF0ECFDU, 0xF0F416U, 0xF101F5U, 0xF1191EU, 0xF128CBU, 0xF13020U, + 0xF14B62U, 0xF15389U, 0xF1625CU, 0xF17AB7U, 0xF18C33U, 0xF194D8U, 0xF1A50DU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4FU, + 0xF1EF9AU, 0xF1F771U, 0xF2045FU, 0xF21CB4U, 0xF22D61U, 0xF2358AU, 0xF24EC8U, 0xF25623U, 0xF267F6U, 0xF27F1DU, + 0xF28999U, 0xF29172U, 0xF2A0A7U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE5U, 0xF2EA30U, 0xF2F2DBU, 0xF30738U, 0xF31FD3U, + 0xF32E06U, 0xF336EDU, 0xF34DAFU, 0xF35544U, 0xF36491U, 0xF37C7AU, 0xF38AFEU, 0xF39215U, 0xF3A3C0U, 0xF3BB2BU, + 0xF3C069U, 0xF3D882U, 0xF3E957U, 0xF3F1BCU, 0xF40F0BU, 0xF417E0U, 0xF42635U, 0xF43EDEU, 0xF4459CU, 0xF45D77U, + 0xF46CA2U, 0xF47449U, 0xF482CDU, 0xF49A26U, 0xF4ABF3U, 0xF4B318U, 0xF4C85AU, 0xF4D0B1U, 0xF4E164U, 0xF4F98FU, + 0xF50C6CU, 0xF51487U, 0xF52552U, 0xF53DB9U, 0xF546FBU, 0xF55E10U, 0xF56FC5U, 0xF5772EU, 0xF581AAU, 0xF59941U, + 0xF5A894U, 0xF5B07FU, 0xF5CB3DU, 0xF5D3D6U, 0xF5E203U, 0xF5FAE8U, 0xF609C6U, 0xF6112DU, 0xF620F8U, 0xF63813U, + 0xF64351U, 0xF65BBAU, 0xF66A6FU, 0xF67284U, 0xF68400U, 0xF69CEBU, 0xF6AD3EU, 0xF6B5D5U, 0xF6CE97U, 0xF6D67CU, + 0xF6E7A9U, 0xF6FF42U, 0xF70AA1U, 0xF7124AU, 0xF7239FU, 0xF73B74U, 0xF74036U, 0xF758DDU, 0xF76908U, 0xF771E3U, + 0xF78767U, 0xF79F8CU, 0xF7AE59U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51BU, 0xF7E4CEU, 0xF7FC25U, 0xF80148U, 0xF819A3U, + 0xF82876U, 0xF8309DU, 0xF84BDFU, 0xF85334U, 0xF862E1U, 0xF87A0AU, 0xF88C8EU, 0xF89465U, 0xF8A5B0U, 0xF8BD5BU, + 0xF8C619U, 0xF8DEF2U, 0xF8EF27U, 0xF8F7CCU, 0xF9022FU, 0xF91AC4U, 0xF92B11U, 0xF933FAU, 0xF948B8U, 0xF95053U, + 0xF96186U, 0xF9796DU, 0xF98FE9U, 0xF99702U, 0xF9A6D7U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD95U, 0xF9EC40U, 0xF9F4ABU, + 0xFA0785U, 0xFA1F6EU, 0xFA2EBBU, 0xFA3650U, 0xFA4D12U, 0xFA55F9U, 0xFA642CU, 0xFA7CC7U, 0xFA8A43U, 0xFA92A8U, + 0xFAA37DU, 0xFABB96U, 0xFAC0D4U, 0xFAD83FU, 0xFAE9EAU, 0xFAF101U, 0xFB04E2U, 0xFB1C09U, 0xFB2DDCU, 0xFB3537U, + 0xFB4E75U, 0xFB569EU, 0xFB674BU, 0xFB7FA0U, 0xFB8924U, 0xFB91CFU, 0xFBA01AU, 0xFBB8F1U, 0xFBC3B3U, 0xFBDB58U, + 0xFBEA8DU, 0xFBF266U, 0xFC0CD1U, 0xFC143AU, 0xFC25EFU, 0xFC3D04U, 0xFC4646U, 0xFC5EADU, 0xFC6F78U, 0xFC7793U, + 0xFC8117U, 0xFC99FCU, 0xFCA829U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36BU, 0xFCE2BEU, 0xFCFA55U, 0xFD0FB6U, 0xFD175DU, + 0xFD2688U, 0xFD3E63U, 0xFD4521U, 0xFD5DCAU, 0xFD6C1FU, 0xFD74F4U, 0xFD8270U, 0xFD9A9BU, 0xFDAB4EU, 0xFDB3A5U, + 0xFDC8E7U, 0xFDD00CU, 0xFDE1D9U, 0xFDF932U, 0xFE0A1CU, 0xFE12F7U, 0xFE2322U, 0xFE3BC9U, 0xFE408BU, 0xFE5860U, + 0xFE69B5U, 0xFE715EU, 0xFE87DAU, 0xFE9F31U, 0xFEAEE4U, 0xFEB60FU, 0xFECD4DU, 0xFED5A6U, 0xFEE473U, 0xFEFC98U, + 0xFF097BU, 0xFF1190U, 0xFF2045U, 0xFF38AEU, 0xFF43ECU, 0xFF5B07U, 0xFF6AD2U, 0xFF7239U, 0xFF84BDU, 0xFF9C56U, + 0xFFAD83U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C1U, 0xFFE714U, 0xFFFFFFU }; static const U32 DECODING_TABLE_23127[] = { - 0x000000U, 0x000001U, 0x000002U, 0x000003U, 0x000004U, 0x000005U, 0x000006U, 0x000007U, 0x000008U, 0x000009U, - 0x00000AU, 0x00000BU, 0x00000CU, 0x00000DU, 0x00000EU, 0x024020U, 0x000010U, 0x000011U, 0x000012U, 0x000013U, - 0x000014U, 0x000015U, 0x000016U, 0x412000U, 0x000018U, 0x000019U, 0x00001AU, 0x180800U, 0x00001CU, 0x200300U, - 0x048040U, 0x001480U, 0x000020U, 0x000021U, 0x000022U, 0x000023U, 0x000024U, 0x000025U, 0x000026U, 0x024008U, - 0x000028U, 0x000029U, 0x00002AU, 0x024004U, 0x00002CU, 0x024002U, 0x024001U, 0x024000U, 0x000030U, 0x000031U, - 0x000032U, 0x008180U, 0x000034U, 0x000C40U, 0x301000U, 0x0C0200U, 0x000038U, 0x043000U, 0x400600U, 0x210040U, - 0x090080U, 0x508000U, 0x002900U, 0x024010U, 0x000040U, 0x000041U, 0x000042U, 0x000043U, 0x000044U, 0x000045U, - 0x000046U, 0x280080U, 0x000048U, 0x000049U, 0x00004AU, 0x002500U, 0x00004CU, 0x111000U, 0x048010U, 0x400A00U, - 0x000050U, 0x000051U, 0x000052U, 0x021200U, 0x000054U, 0x000C20U, 0x048008U, 0x104100U, 0x000058U, 0x404080U, - 0x048004U, 0x210020U, 0x048002U, 0x0A2000U, 0x048000U, 0x048001U, 0x000060U, 0x000061U, 0x000062U, 0x540000U, - 0x000064U, 0x000C10U, 0x010300U, 0x00B000U, 0x000068U, 0x088200U, 0x001880U, 0x210010U, 0x602000U, 0x040180U, - 0x180400U, 0x024040U, 0x000070U, 0x000C04U, 0x086000U, 0x210008U, 0x000C01U, 0x000C00U, 0x420080U, 0x000C02U, - 0x120100U, 0x210002U, 0x210001U, 0x210000U, 0x005200U, 0x000C08U, 0x048020U, 0x210004U, 0x000080U, 0x000081U, - 0x000082U, 0x000083U, 0x000084U, 0x000085U, 0x000086U, 0x280040U, 0x000088U, 0x000089U, 0x00008AU, 0x050200U, - 0x00008CU, 0x00A800U, 0x500100U, 0x001410U, 0x000090U, 0x000091U, 0x000092U, 0x008120U, 0x000094U, 0x160000U, - 0x004A00U, 0x001408U, 0x000098U, 0x404040U, 0x222000U, 0x001404U, 0x090020U, 0x001402U, 0x001401U, 0x001400U, - 0x0000A0U, 0x0000A1U, 0x0000A2U, 0x008110U, 0x0000A4U, 0x401200U, 0x042400U, 0x110800U, 0x0000A8U, 0x300400U, - 0x001840U, 0x482000U, 0x090010U, 0x040140U, 0x208200U, 0x024080U, 0x0000B0U, 0x008102U, 0x008101U, 0x008100U, - 0x090008U, 0x206000U, 0x420040U, 0x008104U, 0x090004U, 0x020A00U, 0x144000U, 0x008108U, 0x090000U, 0x090001U, - 0x090002U, 0x001420U, 0x0000C0U, 0x0000C1U, 0x0000C2U, 0x280004U, 0x0000C4U, 0x280002U, 0x280001U, 0x280000U, - 0x0000C8U, 0x404010U, 0x001820U, 0x128000U, 0x020600U, 0x040120U, 0x016000U, 0x280008U, 0x0000D0U, 0x404008U, - 0x110400U, 0x042800U, 0x003100U, 0x018200U, 0x420020U, 0x280010U, 0x404001U, 0x404000U, 0x080300U, 0x404002U, - 0x300800U, 0x404004U, 0x048080U, 0x001440U, 0x0000E0U, 0x032000U, 0x001808U, 0x004600U, 0x10C000U, 0x040108U, - 0x420010U, 0x280020U, 0x001802U, 0x040104U, 0x001800U, 0x001801U, 0x040101U, 0x040100U, 0x001804U, 0x040102U, - 0x240200U, 0x181000U, 0x420004U, 0x008140U, 0x420002U, 0x000C80U, 0x420000U, 0x420001U, 0x00A400U, 0x404020U, - 0x001810U, 0x210080U, 0x090040U, 0x040110U, 0x420008U, 0x102200U, 0x000100U, 0x000101U, 0x000102U, 0x000103U, - 0x000104U, 0x000105U, 0x000106U, 0x041800U, 0x000108U, 0x000109U, 0x00010AU, 0x002440U, 0x00010CU, 0x200210U, - 0x500080U, 0x098000U, 0x000110U, 0x000111U, 0x000112U, 0x0080A0U, 0x000114U, 0x200208U, 0x0A0400U, 0x104040U, - 0x000118U, 0x200204U, 0x015000U, 0x460000U, 0x200201U, 0x200200U, 0x002820U, 0x200202U, 0x000120U, 0x000121U, - 0x000122U, 0x008090U, 0x000124U, 0x182000U, 0x010240U, 0x600400U, 0x000128U, 0x410800U, 0x2C0000U, 0x101200U, - 0x009400U, 0x0400C0U, 0x002810U, 0x024100U, 0x000130U, 0x008082U, 0x008081U, 0x008080U, 0x444000U, 0x031000U, - 0x002808U, 0x008084U, 0x120040U, 0x084400U, 0x002804U, 0x008088U, 0x002802U, 0x200220U, 0x002800U, 0x002801U, - 0x000140U, 0x000141U, 0x000142U, 0x002408U, 0x000144U, 0x428000U, 0x010220U, 0x104010U, 0x000148U, 0x002402U, - 0x002401U, 0x002400U, 0x084800U, 0x0400A0U, 0x221000U, 0x002404U, 0x000150U, 0x0D0000U, 0x600800U, 0x104004U, - 0x003080U, 0x104002U, 0x104001U, 0x104000U, 0x120020U, 0x009800U, 0x080280U, 0x002410U, 0x410400U, 0x200240U, - 0x048100U, 0x104008U, 0x000160U, 0x205000U, 0x010204U, 0x0A0800U, 0x010202U, 0x040088U, 0x010200U, 0x010201U, - 0x120010U, 0x040084U, 0x40C000U, 0x002420U, 0x040081U, 0x040080U, 0x010208U, 0x040082U, 0x120008U, 0x402200U, - 0x041400U, 0x0080C0U, 0x288000U, 0x000D00U, 0x010210U, 0x104020U, 0x120000U, 0x120001U, 0x120002U, 0x210100U, - 0x120004U, 0x040090U, 0x002840U, 0x481000U, 0x000180U, 0x000181U, 0x000182U, 0x008030U, 0x000184U, 0x014400U, - 0x500008U, 0x022200U, 0x000188U, 0x0A1000U, 0x500004U, 0x204800U, 0x500002U, 0x040060U, 0x500000U, 0x500001U, - 0x000190U, 0x008022U, 0x008021U, 0x008020U, 0x003040U, 0x480800U, 0x250000U, 0x008024U, 0x040C00U, 0x112000U, - 0x080240U, 0x008028U, 0x02C000U, 0x200280U, 0x500010U, 0x001500U, 0x0001A0U, 0x008012U, 0x008011U, 0x008010U, - 0x220800U, 0x040048U, 0x085000U, 0x008014U, 0x006200U, 0x040044U, 0x030400U, 0x008018U, 0x040041U, 0x040040U, - 0x500020U, 0x040042U, 0x008003U, 0x008002U, 0x008001U, 0x008000U, 0x100600U, 0x008006U, 0x008005U, 0x008004U, - 0x601000U, 0x00800AU, 0x008009U, 0x008008U, 0x090100U, 0x040050U, 0x002880U, 0x00800CU, 0x0001C0U, 0x100A00U, - 0x064000U, 0x411000U, 0x003010U, 0x040028U, 0x008C00U, 0x280100U, 0x218000U, 0x040024U, 0x080210U, 0x002480U, - 0x040021U, 0x040020U, 0x500040U, 0x040022U, 0x003004U, 0x220400U, 0x080208U, 0x008060U, 0x003000U, 0x003001U, - 0x003002U, 0x104080U, 0x080202U, 0x404100U, 0x080200U, 0x080201U, 0x003008U, 0x040030U, 0x080204U, 0x030800U, - 0x480400U, 0x04000CU, 0x302000U, 0x008050U, 0x040009U, 0x040008U, 0x010280U, 0x04000AU, 0x040005U, 0x040004U, - 0x001900U, 0x040006U, 0x040001U, 0x040000U, 0x040003U, 0x040002U, 0x014800U, 0x008042U, 0x008041U, 0x008040U, - 0x003020U, 0x040018U, 0x420100U, 0x008044U, 0x120080U, 0x040014U, 0x080220U, 0x008048U, 0x040011U, 0x040010U, - 0x204400U, 0x040012U, 0x000200U, 0x000201U, 0x000202U, 0x000203U, 0x000204U, 0x000205U, 0x000206U, 0x108400U, - 0x000208U, 0x000209U, 0x00020AU, 0x050080U, 0x00020CU, 0x200110U, 0x083000U, 0x400840U, 0x000210U, 0x000211U, - 0x000212U, 0x021040U, 0x000214U, 0x200108U, 0x004880U, 0x0C0020U, 0x000218U, 0x200104U, 0x400420U, 0x00E000U, - 0x200101U, 0x200100U, 0x130000U, 0x200102U, 0x000220U, 0x000221U, 0x000222U, 0x202800U, 0x000224U, 0x401080U, - 0x010140U, 0x0C0010U, 0x000228U, 0x088040U, 0x400410U, 0x101100U, 0x140800U, 0x012400U, 0x208080U, 0x024200U, - 0x000230U, 0x114000U, 0x400408U, 0x0C0004U, 0x02A000U, 0x0C0002U, 0x0C0001U, 0x0C0000U, 0x400402U, 0x020880U, - 0x400400U, 0x400401U, 0x005040U, 0x200120U, 0x400404U, 0x0C0008U, 0x000240U, 0x000241U, 0x000242U, 0x021010U, - 0x000244U, 0x046000U, 0x010120U, 0x400808U, 0x000248U, 0x088020U, 0x304000U, 0x400804U, 0x020480U, 0x400802U, - 0x400801U, 0x400800U, 0x000250U, 0x021002U, 0x021001U, 0x021000U, 0x580000U, 0x018080U, 0x202400U, 0x021004U, - 0x012800U, 0x140400U, 0x080180U, 0x021008U, 0x005020U, 0x200140U, 0x048200U, 0x400810U, 0x000260U, 0x088008U, - 0x010104U, 0x004480U, 0x010102U, 0x320000U, 0x010100U, 0x010101U, 0x088001U, 0x088000U, 0x062000U, 0x088002U, - 0x005010U, 0x088004U, 0x010108U, 0x400820U, 0x240080U, 0x402100U, 0x108800U, 0x021020U, 0x005008U, 0x000E00U, - 0x010110U, 0x0C0040U, 0x005004U, 0x088010U, 0x400440U, 0x210200U, 0x005000U, 0x005001U, 0x005002U, 0x102080U, - 0x000280U, 0x000281U, 0x000282U, 0x050008U, 0x000284U, 0x401020U, 0x004810U, 0x022100U, 0x000288U, 0x050002U, - 0x050001U, 0x050000U, 0x020440U, 0x184000U, 0x208020U, 0x050004U, 0x000290U, 0x082400U, 0x004804U, 0x700000U, - 0x004802U, 0x018040U, 0x004800U, 0x004801U, 0x109000U, 0x020820U, 0x080140U, 0x050010U, 0x442000U, 0x200180U, - 0x004808U, 0x001600U, 0x0002A0U, 0x401004U, 0x1A0000U, 0x004440U, 0x401001U, 0x401000U, 0x208008U, 0x401002U, - 0x006100U, 0x020810U, 0x208004U, 0x050020U, 0x208002U, 0x401008U, 0x208000U, 0x208001U, 0x240040U, 0x020808U, - 0x013000U, 0x008300U, 0x100500U, 0x401010U, 0x004820U, 0x0C0080U, 0x020801U, 0x020800U, 0x400480U, 0x020802U, - 0x090200U, 0x020804U, 0x208010U, 0x102040U, 0x0002C0U, 0x100900U, 0x40A000U, 0x004420U, 0x020408U, 0x018010U, - 0x141000U, 0x280200U, 0x020404U, 0x203000U, 0x080110U, 0x050040U, 0x020400U, 0x020401U, 0x020402U, 0x400880U, - 0x240020U, 0x018004U, 0x080108U, 0x021080U, 0x018001U, 0x018000U, 0x004840U, 0x018002U, 0x080102U, 0x404200U, - 0x080100U, 0x080101U, 0x020410U, 0x018008U, 0x080104U, 0x102020U, 0x240010U, 0x004402U, 0x004401U, 0x004400U, - 0x082800U, 0x401040U, 0x010180U, 0x004404U, 0x510000U, 0x088080U, 0x001A00U, 0x004408U, 0x020420U, 0x040300U, - 0x208040U, 0x102010U, 0x240000U, 0x240001U, 0x240002U, 0x004410U, 0x240004U, 0x018020U, 0x420200U, 0x102008U, - 0x240008U, 0x020840U, 0x080120U, 0x102004U, 0x005080U, 0x102002U, 0x102001U, 0x102000U, 0x000300U, 0x000301U, - 0x000302U, 0x484000U, 0x000304U, 0x200018U, 0x010060U, 0x022080U, 0x000308U, 0x200014U, 0x028800U, 0x101020U, - 0x200011U, 0x200010U, 0x044400U, 0x200012U, 0x000310U, 0x20000CU, 0x142000U, 0x010C00U, 0x200009U, 0x200008U, - 0x409000U, 0x20000AU, 0x200005U, 0x200004U, 0x0800C0U, 0x200006U, 0x200001U, 0x200000U, 0x200003U, 0x200002U, - 0x000320U, 0x060400U, 0x010044U, 0x101008U, 0x010042U, 0x00C800U, 0x010040U, 0x010041U, 0x006080U, 0x101002U, - 0x101001U, 0x101000U, 0x4A0000U, 0x200030U, 0x010048U, 0x101004U, 0x081800U, 0x402040U, 0x224000U, 0x008280U, - 0x100480U, 0x200028U, 0x010050U, 0x0C0100U, 0x058000U, 0x200024U, 0x400500U, 0x101010U, 0x200021U, 0x200020U, - 0x002A00U, 0x200022U, 0x000340U, 0x100880U, 0x010024U, 0x248000U, 0x010022U, 0x081400U, 0x010020U, 0x010021U, - 0x441000U, 0x034000U, 0x080090U, 0x002600U, 0x10A000U, 0x200050U, 0x010028U, 0x400900U, 0x00C400U, 0x402020U, - 0x080088U, 0x021100U, 0x060800U, 0x200048U, 0x010030U, 0x104200U, 0x080082U, 0x200044U, 0x080080U, 0x080081U, - 0x200041U, 0x200040U, 0x080084U, 0x200042U, 0x010006U, 0x402010U, 0x010004U, 0x010005U, 0x010002U, 0x010003U, - 0x010000U, 0x010001U, 0x200C00U, 0x088100U, 0x01000CU, 0x101040U, 0x01000AU, 0x040280U, 0x010008U, 0x010009U, - 0x402001U, 0x402000U, 0x010014U, 0x402002U, 0x010012U, 0x402004U, 0x010010U, 0x010011U, 0x120200U, 0x402008U, - 0x0800A0U, 0x044800U, 0x005100U, 0x200060U, 0x010018U, 0x028400U, 0x000380U, 0x100840U, 0x201400U, 0x022004U, - 0x0C8000U, 0x022002U, 0x022001U, 0x022000U, 0x006020U, 0x408400U, 0x080050U, 0x050100U, 0x011800U, 0x200090U, - 0x500200U, 0x022008U, 0x430000U, 0x045000U, 0x080048U, 0x008220U, 0x100420U, 0x200088U, 0x004900U, 0x022010U, - 0x080042U, 0x200084U, 0x080040U, 0x080041U, 0x200081U, 0x200080U, 0x080044U, 0x200082U, 0x006008U, 0x290000U, - 0x440800U, 0x008210U, 0x100410U, 0x401100U, 0x0100C0U, 0x022020U, 0x006000U, 0x006001U, 0x006002U, 0x101080U, - 0x006004U, 0x040240U, 0x208100U, 0x080C00U, 0x100404U, 0x008202U, 0x008201U, 0x008200U, 0x100400U, 0x100401U, - 0x100402U, 0x008204U, 0x006010U, 0x020900U, 0x080060U, 0x008208U, 0x100408U, 0x2000A0U, 0x061000U, 0x414000U, - 0x100801U, 0x100800U, 0x080018U, 0x100802U, 0x604000U, 0x100804U, 0x0100A0U, 0x022040U, 0x080012U, 0x100808U, - 0x080010U, 0x080011U, 0x020500U, 0x040220U, 0x080014U, 0x00D000U, 0x08000AU, 0x100810U, 0x080008U, 0x080009U, - 0x003200U, 0x018100U, 0x08000CU, 0x440400U, 0x080002U, 0x080003U, 0x080000U, 0x080001U, 0x080006U, 0x2000C0U, - 0x080004U, 0x080005U, 0x029000U, 0x100820U, 0x010084U, 0x004500U, 0x010082U, 0x040208U, 0x010080U, 0x010081U, - 0x006040U, 0x040204U, 0x080030U, 0x620000U, 0x040201U, 0x040200U, 0x010088U, 0x040202U, 0x240100U, 0x402080U, - 0x080028U, 0x008240U, 0x100440U, 0x0A4000U, 0x010090U, 0x201800U, 0x080022U, 0x011400U, 0x080020U, 0x080021U, - 0x408800U, 0x040210U, 0x080024U, 0x102100U, 0x000400U, 0x000401U, 0x000402U, 0x000403U, 0x000404U, 0x000405U, - 0x000406U, 0x108200U, 0x000408U, 0x000409U, 0x00040AU, 0x002140U, 0x00040CU, 0x4C0000U, 0x210800U, 0x001090U, - 0x000410U, 0x000411U, 0x000412U, 0x244000U, 0x000414U, 0x000860U, 0x0A0100U, 0x001088U, 0x000418U, 0x038000U, - 0x400220U, 0x001084U, 0x106000U, 0x001082U, 0x001081U, 0x001080U, 0x000420U, 0x000421U, 0x000422U, 0x091000U, - 0x000424U, 0x000850U, 0x042080U, 0x600100U, 0x000428U, 0x300080U, 0x400210U, 0x048800U, 0x009100U, 0x012200U, - 0x180040U, 0x024400U, 0x000430U, 0x000844U, 0x400208U, 0x122000U, 0x000841U, 0x000840U, 0x01C000U, 0x000842U, - 0x400202U, 0x084100U, 0x400200U, 0x400201U, 0x260000U, 0x000848U, 0x400204U, 0x0010A0U, 0x000440U, 0x000441U, - 0x000442U, 0x002108U, 0x000444U, 0x000830U, 0x405000U, 0x070000U, 0x000448U, 0x002102U, 0x002101U, 0x002100U, - 0x020280U, 0x20C000U, 0x180020U, 0x002104U, 0x000450U, 0x000824U, 0x110080U, 0x488000U, 0x000821U, 0x000820U, - 0x202200U, 0x000822U, 0x281000U, 0x140200U, 0x024800U, 0x002110U, 0x410100U, 0x000828U, 0x048400U, 0x0010C0U, - 0x000460U, 0x000814U, 0x228000U, 0x004280U, 0x000811U, 0x000810U, 0x180008U, 0x000812U, 0x054000U, 0x421000U, - 0x180004U, 0x002120U, 0x180002U, 0x000818U, 0x180000U, 0x180001U, 0x000805U, 0x000804U, 0x041100U, 0x000806U, - 0x000801U, 0x000800U, 0x000803U, 0x000802U, 0x00A080U, 0x00080CU, 0x400240U, 0x210400U, 0x000809U, 0x000808U, - 0x180010U, 0x00080AU, 0x000480U, 0x000481U, 0x000482U, 0x420800U, 0x000484U, 0x014100U, 0x042020U, 0x001018U, - 0x000488U, 0x300020U, 0x08C000U, 0x001014U, 0x020240U, 0x001012U, 0x001011U, 0x001010U, 0x000490U, 0x082200U, - 0x110040U, 0x00100CU, 0x608000U, 0x00100AU, 0x001009U, 0x001008U, 0x040900U, 0x001006U, 0x001005U, 0x001004U, - 0x001003U, 0x001002U, 0x001001U, 0x001000U, 0x0004A0U, 0x300008U, 0x042004U, 0x004240U, 0x042002U, 0x0A8000U, - 0x042000U, 0x042001U, 0x300001U, 0x300000U, 0x030100U, 0x300002U, 0x404800U, 0x300004U, 0x042008U, 0x001030U, - 0x025000U, 0x450000U, 0x280800U, 0x008500U, 0x100300U, 0x0008C0U, 0x042010U, 0x001028U, 0x00A040U, 0x300010U, - 0x400280U, 0x001024U, 0x090400U, 0x001022U, 0x001021U, 0x001020U, 0x0004C0U, 0x049000U, 0x110010U, 0x004220U, - 0x020208U, 0x502000U, 0x008900U, 0x280400U, 0x020204U, 0x090800U, 0x640000U, 0x002180U, 0x020200U, 0x020201U, - 0x020202U, 0x001050U, 0x110002U, 0x220100U, 0x110000U, 0x110001U, 0x0C4000U, 0x0008A0U, 0x110004U, 0x001048U, - 0x00A020U, 0x404400U, 0x110008U, 0x001044U, 0x020210U, 0x001042U, 0x001041U, 0x001040U, 0x480100U, 0x004202U, - 0x004201U, 0x004200U, 0x211000U, 0x000890U, 0x042040U, 0x004204U, 0x00A010U, 0x300040U, 0x001C00U, 0x004208U, - 0x020220U, 0x040500U, 0x180080U, 0x418000U, 0x00A008U, 0x000884U, 0x110020U, 0x004210U, 0x000881U, 0x000880U, - 0x420400U, 0x000882U, 0x00A000U, 0x00A001U, 0x00A002U, 0x0E0000U, 0x00A004U, 0x000888U, 0x204100U, 0x001060U, - 0x000500U, 0x000501U, 0x000502U, 0x002048U, 0x000504U, 0x014080U, 0x0A0010U, 0x600020U, 0x000508U, 0x002042U, - 0x002041U, 0x002040U, 0x009020U, 0x120800U, 0x044200U, 0x002044U, 0x000510U, 0x501000U, 0x0A0004U, 0x010A00U, - 0x0A0002U, 0x04A000U, 0x0A0000U, 0x0A0001U, 0x040880U, 0x084020U, 0x308000U, 0x002050U, 0x410040U, 0x200600U, - 0x0A0008U, 0x001180U, 0x000520U, 0x060200U, 0x104800U, 0x600004U, 0x009008U, 0x600002U, 0x600001U, 0x600000U, - 0x009004U, 0x084010U, 0x030080U, 0x002060U, 0x009000U, 0x009001U, 0x009002U, 0x600008U, 0x212000U, 0x084008U, - 0x041040U, 0x008480U, 0x100280U, 0x000940U, 0x0A0020U, 0x600010U, 0x084001U, 0x084000U, 0x400300U, 0x084002U, - 0x009010U, 0x084004U, 0x002C00U, 0x150000U, 0x000540U, 0x00200AU, 0x002009U, 0x002008U, 0x340000U, 0x081200U, - 0x008880U, 0x00200CU, 0x002003U, 0x002002U, 0x002001U, 0x002000U, 0x410010U, 0x002006U, 0x002005U, 0x002004U, - 0x00C200U, 0x220080U, 0x041020U, 0x002018U, 0x410008U, 0x000920U, 0x0A0040U, 0x104400U, 0x410004U, 0x002012U, - 0x002011U, 0x002010U, 0x410000U, 0x410001U, 0x410002U, 0x002014U, 0x480080U, 0x118000U, 0x041010U, 0x002028U, - 0x026000U, 0x000910U, 0x010600U, 0x600040U, 0x200A00U, 0x002022U, 0x002021U, 0x002020U, 0x009040U, 0x040480U, - 0x180100U, 0x002024U, 0x041002U, 0x000904U, 0x041000U, 0x041001U, 0x000901U, 0x000900U, 0x041004U, 0x000902U, - 0x120400U, 0x084040U, 0x041008U, 0x002030U, 0x410020U, 0x000908U, 0x204080U, 0x028200U, 0x000580U, 0x014004U, - 0x201200U, 0x1C0000U, 0x014001U, 0x014000U, 0x008840U, 0x014002U, 0x040810U, 0x408200U, 0x030020U, 0x0020C0U, - 0x282000U, 0x014008U, 0x500400U, 0x001110U, 0x040808U, 0x220040U, 0x406000U, 0x008420U, 0x100220U, 0x014010U, - 0x0A0080U, 0x001108U, 0x040800U, 0x040801U, 0x040802U, 0x001104U, 0x040804U, 0x001102U, 0x001101U, 0x001100U, - 0x480040U, 0x003800U, 0x030008U, 0x008410U, 0x100210U, 0x014020U, 0x042100U, 0x600080U, 0x030002U, 0x300100U, - 0x030000U, 0x030001U, 0x009080U, 0x040440U, 0x030004U, 0x080A00U, 0x100204U, 0x008402U, 0x008401U, 0x008400U, - 0x100200U, 0x100201U, 0x100202U, 0x008404U, 0x040820U, 0x084080U, 0x030010U, 0x008408U, 0x100208U, 0x422000U, - 0x204040U, 0x001120U, 0x480020U, 0x220010U, 0x008804U, 0x002088U, 0x008802U, 0x014040U, 0x008800U, 0x008801U, - 0x105000U, 0x002082U, 0x002081U, 0x002080U, 0x020300U, 0x040420U, 0x008808U, 0x002084U, 0x220001U, 0x220000U, - 0x110100U, 0x220002U, 0x003400U, 0x220004U, 0x008810U, 0x440200U, 0x040840U, 0x220008U, 0x080600U, 0x002090U, - 0x410080U, 0x188000U, 0x204020U, 0x001140U, 0x480000U, 0x480001U, 0x480002U, 0x004300U, 0x480004U, 0x040408U, - 0x008820U, 0x121000U, 0x480008U, 0x040404U, 0x030040U, 0x0020A0U, 0x040401U, 0x040400U, 0x204010U, 0x040402U, - 0x480010U, 0x220020U, 0x041080U, 0x008440U, 0x100240U, 0x000980U, 0x204008U, 0x092000U, 0x00A100U, 0x011200U, - 0x204004U, 0x500800U, 0x204002U, 0x040410U, 0x204000U, 0x204001U, 0x000600U, 0x000601U, 0x000602U, 0x108004U, - 0x000604U, 0x108002U, 0x108001U, 0x108000U, 0x000608U, 0x005800U, 0x400030U, 0x2A0000U, 0x0200C0U, 0x012020U, - 0x044100U, 0x108008U, 0x000610U, 0x082080U, 0x400028U, 0x010900U, 0x051000U, 0x424000U, 0x202040U, 0x108010U, - 0x400022U, 0x140040U, 0x400020U, 0x400021U, 0x088800U, 0x200500U, 0x400024U, 0x001280U, 0x000620U, 0x060100U, - 0x400018U, 0x0040C0U, 0x284000U, 0x012008U, 0x021800U, 0x108020U, 0x400012U, 0x012004U, 0x400010U, 0x400011U, - 0x012001U, 0x012000U, 0x400014U, 0x012002U, 0x40000AU, 0x209000U, 0x400008U, 0x400009U, 0x100180U, 0x000A40U, - 0x40000CU, 0x0C0400U, 0x400002U, 0x400003U, 0x400000U, 0x400001U, 0x400006U, 0x012010U, 0x400004U, 0x400005U, - 0x000640U, 0x610000U, 0x0C0800U, 0x0040A0U, 0x020088U, 0x081100U, 0x202010U, 0x108040U, 0x020084U, 0x140010U, - 0x019000U, 0x002300U, 0x020080U, 0x020081U, 0x020082U, 0x400C00U, 0x00C100U, 0x140008U, 0x202004U, 0x021400U, - 0x202002U, 0x000A20U, 0x202000U, 0x202001U, 0x140001U, 0x140000U, 0x400060U, 0x140002U, 0x020090U, 0x140004U, - 0x202008U, 0x094000U, 0x103000U, 0x004082U, 0x004081U, 0x004080U, 0x448000U, 0x000A10U, 0x010500U, 0x004084U, - 0x200900U, 0x088400U, 0x400050U, 0x004088U, 0x0200A0U, 0x012040U, 0x180200U, 0x241000U, 0x0B0000U, 0x000A04U, - 0x400048U, 0x004090U, 0x000A01U, 0x000A00U, 0x202020U, 0x000A02U, 0x400042U, 0x140020U, 0x400040U, 0x400041U, - 0x005400U, 0x000A08U, 0x400044U, 0x028100U, 0x000680U, 0x082010U, 0x201100U, 0x004060U, 0x020048U, 0x240800U, - 0x490000U, 0x108080U, 0x020044U, 0x408100U, 0x102800U, 0x050400U, 0x020040U, 0x020041U, 0x020042U, 0x001210U, - 0x082001U, 0x082000U, 0x068000U, 0x082002U, 0x100120U, 0x082004U, 0x004C00U, 0x001208U, 0x214000U, 0x082008U, - 0x4000A0U, 0x001204U, 0x020050U, 0x001202U, 0x001201U, 0x001200U, 0x018800U, 0x004042U, 0x004041U, 0x004040U, - 0x100110U, 0x401400U, 0x042200U, 0x004044U, 0x0C1000U, 0x300200U, 0x400090U, 0x004048U, 0x020060U, 0x012080U, - 0x208400U, 0x080900U, 0x100104U, 0x082020U, 0x400088U, 0x004050U, 0x100100U, 0x100101U, 0x100102U, 0x230000U, - 0x400082U, 0x020C00U, 0x400080U, 0x400081U, 0x100108U, 0x04C000U, 0x400084U, 0x001220U, 0x02000CU, 0x004022U, - 0x004021U, 0x004020U, 0x020008U, 0x020009U, 0x02000AU, 0x004024U, 0x020004U, 0x020005U, 0x020006U, 0x004028U, - 0x020000U, 0x020001U, 0x020002U, 0x020003U, 0x401800U, 0x082040U, 0x110200U, 0x004030U, 0x020018U, 0x018400U, - 0x202080U, 0x440100U, 0x020014U, 0x140080U, 0x080500U, 0x208800U, 0x020010U, 0x020011U, 0x020012U, 0x001240U, - 0x004003U, 0x004002U, 0x004001U, 0x004000U, 0x020028U, 0x004006U, 0x004005U, 0x004004U, 0x020024U, 0x00400AU, - 0x004009U, 0x004008U, 0x020020U, 0x020021U, 0x020022U, 0x00400CU, 0x240400U, 0x004012U, 0x004011U, 0x004010U, - 0x100140U, 0x000A80U, 0x089000U, 0x004014U, 0x00A200U, 0x011100U, 0x4000C0U, 0x004018U, 0x020030U, 0x680000U, - 0x050800U, 0x102400U, 0x000700U, 0x060020U, 0x201080U, 0x010810U, 0x402800U, 0x081040U, 0x044008U, 0x108100U, - 0x190000U, 0x408080U, 0x044004U, 0x002240U, 0x044002U, 0x200410U, 0x044000U, 0x044001U, 0x00C040U, 0x010802U, - 0x010801U, 0x010800U, 0x1000A0U, 0x200408U, 0x0A0200U, 0x010804U, 0x023000U, 0x200404U, 0x400120U, 0x010808U, - 0x200401U, 0x200400U, 0x044010U, 0x200402U, 0x060001U, 0x060000U, 0x08A000U, 0x060002U, 0x100090U, 0x060004U, - 0x010440U, 0x600200U, 0x200840U, 0x060008U, 0x400110U, 0x101400U, 0x009200U, 0x012100U, 0x044020U, 0x080880U, - 0x100084U, 0x060010U, 0x400108U, 0x010820U, 0x100080U, 0x100081U, 0x100082U, 0x007000U, 0x400102U, 0x084200U, - 0x400100U, 0x400101U, 0x100088U, 0x200420U, 0x400104U, 0x028040U, 0x00C010U, 0x081004U, 0x520000U, 0x002208U, - 0x081001U, 0x081000U, 0x010420U, 0x081002U, 0x200820U, 0x002202U, 0x002201U, 0x002200U, 0x020180U, 0x081008U, - 0x044040U, 0x002204U, 0x00C000U, 0x00C001U, 0x00C002U, 0x010840U, 0x00C004U, 0x081010U, 0x202100U, 0x440080U, - 0x00C008U, 0x140100U, 0x080480U, 0x002210U, 0x410200U, 0x200440U, 0x101800U, 0x028020U, 0x200808U, 0x060040U, - 0x010404U, 0x004180U, 0x010402U, 0x081020U, 0x010400U, 0x010401U, 0x200800U, 0x200801U, 0x200802U, 0x002220U, - 0x200804U, 0x504000U, 0x010408U, 0x028010U, 0x00C020U, 0x402400U, 0x041200U, 0x380000U, 0x1000C0U, 0x000B00U, - 0x010410U, 0x028008U, 0x200810U, 0x011080U, 0x400140U, 0x028004U, 0x0C2000U, 0x028002U, 0x028001U, 0x028000U, - 0x201002U, 0x408008U, 0x201000U, 0x201001U, 0x100030U, 0x014200U, 0x201004U, 0x022400U, 0x408001U, 0x408000U, - 0x201008U, 0x408002U, 0x020140U, 0x408004U, 0x044080U, 0x080820U, 0x100024U, 0x082100U, 0x201010U, 0x010880U, - 0x100020U, 0x100021U, 0x100022U, 0x440040U, 0x040A00U, 0x408010U, 0x080440U, 0x124000U, 0x100028U, 0x200480U, - 0x01A000U, 0x001300U, 0x100014U, 0x060080U, 0x201020U, 0x004140U, 0x100010U, 0x100011U, 0x100012U, 0x080808U, - 0x006400U, 0x408020U, 0x030200U, 0x080804U, 0x100018U, 0x080802U, 0x080801U, 0x080800U, 0x100004U, 0x100005U, - 0x100006U, 0x008600U, 0x100000U, 0x100001U, 0x100002U, 0x100003U, 0x10000CU, 0x011040U, 0x400180U, 0x242000U, - 0x100008U, 0x100009U, 0x10000AU, 0x080810U, 0x052000U, 0x100C00U, 0x201040U, 0x004120U, 0x020108U, 0x081080U, - 0x008A00U, 0x440010U, 0x020104U, 0x408040U, 0x080410U, 0x002280U, 0x020100U, 0x020101U, 0x020102U, 0x310000U, - 0x00C080U, 0x220200U, 0x080408U, 0x440004U, 0x100060U, 0x440002U, 0x440001U, 0x440000U, 0x080402U, 0x011020U, - 0x080400U, 0x080401U, 0x020110U, 0x006800U, 0x080404U, 0x440008U, 0x480200U, 0x004102U, 0x004101U, 0x004100U, - 0x100050U, 0x20A000U, 0x010480U, 0x004104U, 0x200880U, 0x011010U, 0x148000U, 0x004108U, 0x020120U, 0x040600U, - 0x403000U, 0x080840U, 0x100044U, 0x011008U, 0x022800U, 0x004110U, 0x100040U, 0x100041U, 0x100042U, 0x440020U, - 0x011001U, 0x011000U, 0x080420U, 0x011002U, 0x100048U, 0x011004U, 0x204200U, 0x028080U + 0x000000U, 0x000001U, 0x000002U, 0x000003U, 0x000004U, 0x000005U, 0x000006U, 0x000007U, 0x000008U, 0x000009U, + 0x00000AU, 0x00000BU, 0x00000CU, 0x00000DU, 0x00000EU, 0x024020U, 0x000010U, 0x000011U, 0x000012U, 0x000013U, + 0x000014U, 0x000015U, 0x000016U, 0x412000U, 0x000018U, 0x000019U, 0x00001AU, 0x180800U, 0x00001CU, 0x200300U, + 0x048040U, 0x001480U, 0x000020U, 0x000021U, 0x000022U, 0x000023U, 0x000024U, 0x000025U, 0x000026U, 0x024008U, + 0x000028U, 0x000029U, 0x00002AU, 0x024004U, 0x00002CU, 0x024002U, 0x024001U, 0x024000U, 0x000030U, 0x000031U, + 0x000032U, 0x008180U, 0x000034U, 0x000C40U, 0x301000U, 0x0C0200U, 0x000038U, 0x043000U, 0x400600U, 0x210040U, + 0x090080U, 0x508000U, 0x002900U, 0x024010U, 0x000040U, 0x000041U, 0x000042U, 0x000043U, 0x000044U, 0x000045U, + 0x000046U, 0x280080U, 0x000048U, 0x000049U, 0x00004AU, 0x002500U, 0x00004CU, 0x111000U, 0x048010U, 0x400A00U, + 0x000050U, 0x000051U, 0x000052U, 0x021200U, 0x000054U, 0x000C20U, 0x048008U, 0x104100U, 0x000058U, 0x404080U, + 0x048004U, 0x210020U, 0x048002U, 0x0A2000U, 0x048000U, 0x048001U, 0x000060U, 0x000061U, 0x000062U, 0x540000U, + 0x000064U, 0x000C10U, 0x010300U, 0x00B000U, 0x000068U, 0x088200U, 0x001880U, 0x210010U, 0x602000U, 0x040180U, + 0x180400U, 0x024040U, 0x000070U, 0x000C04U, 0x086000U, 0x210008U, 0x000C01U, 0x000C00U, 0x420080U, 0x000C02U, + 0x120100U, 0x210002U, 0x210001U, 0x210000U, 0x005200U, 0x000C08U, 0x048020U, 0x210004U, 0x000080U, 0x000081U, + 0x000082U, 0x000083U, 0x000084U, 0x000085U, 0x000086U, 0x280040U, 0x000088U, 0x000089U, 0x00008AU, 0x050200U, + 0x00008CU, 0x00A800U, 0x500100U, 0x001410U, 0x000090U, 0x000091U, 0x000092U, 0x008120U, 0x000094U, 0x160000U, + 0x004A00U, 0x001408U, 0x000098U, 0x404040U, 0x222000U, 0x001404U, 0x090020U, 0x001402U, 0x001401U, 0x001400U, + 0x0000A0U, 0x0000A1U, 0x0000A2U, 0x008110U, 0x0000A4U, 0x401200U, 0x042400U, 0x110800U, 0x0000A8U, 0x300400U, + 0x001840U, 0x482000U, 0x090010U, 0x040140U, 0x208200U, 0x024080U, 0x0000B0U, 0x008102U, 0x008101U, 0x008100U, + 0x090008U, 0x206000U, 0x420040U, 0x008104U, 0x090004U, 0x020A00U, 0x144000U, 0x008108U, 0x090000U, 0x090001U, + 0x090002U, 0x001420U, 0x0000C0U, 0x0000C1U, 0x0000C2U, 0x280004U, 0x0000C4U, 0x280002U, 0x280001U, 0x280000U, + 0x0000C8U, 0x404010U, 0x001820U, 0x128000U, 0x020600U, 0x040120U, 0x016000U, 0x280008U, 0x0000D0U, 0x404008U, + 0x110400U, 0x042800U, 0x003100U, 0x018200U, 0x420020U, 0x280010U, 0x404001U, 0x404000U, 0x080300U, 0x404002U, + 0x300800U, 0x404004U, 0x048080U, 0x001440U, 0x0000E0U, 0x032000U, 0x001808U, 0x004600U, 0x10C000U, 0x040108U, + 0x420010U, 0x280020U, 0x001802U, 0x040104U, 0x001800U, 0x001801U, 0x040101U, 0x040100U, 0x001804U, 0x040102U, + 0x240200U, 0x181000U, 0x420004U, 0x008140U, 0x420002U, 0x000C80U, 0x420000U, 0x420001U, 0x00A400U, 0x404020U, + 0x001810U, 0x210080U, 0x090040U, 0x040110U, 0x420008U, 0x102200U, 0x000100U, 0x000101U, 0x000102U, 0x000103U, + 0x000104U, 0x000105U, 0x000106U, 0x041800U, 0x000108U, 0x000109U, 0x00010AU, 0x002440U, 0x00010CU, 0x200210U, + 0x500080U, 0x098000U, 0x000110U, 0x000111U, 0x000112U, 0x0080A0U, 0x000114U, 0x200208U, 0x0A0400U, 0x104040U, + 0x000118U, 0x200204U, 0x015000U, 0x460000U, 0x200201U, 0x200200U, 0x002820U, 0x200202U, 0x000120U, 0x000121U, + 0x000122U, 0x008090U, 0x000124U, 0x182000U, 0x010240U, 0x600400U, 0x000128U, 0x410800U, 0x2C0000U, 0x101200U, + 0x009400U, 0x0400C0U, 0x002810U, 0x024100U, 0x000130U, 0x008082U, 0x008081U, 0x008080U, 0x444000U, 0x031000U, + 0x002808U, 0x008084U, 0x120040U, 0x084400U, 0x002804U, 0x008088U, 0x002802U, 0x200220U, 0x002800U, 0x002801U, + 0x000140U, 0x000141U, 0x000142U, 0x002408U, 0x000144U, 0x428000U, 0x010220U, 0x104010U, 0x000148U, 0x002402U, + 0x002401U, 0x002400U, 0x084800U, 0x0400A0U, 0x221000U, 0x002404U, 0x000150U, 0x0D0000U, 0x600800U, 0x104004U, + 0x003080U, 0x104002U, 0x104001U, 0x104000U, 0x120020U, 0x009800U, 0x080280U, 0x002410U, 0x410400U, 0x200240U, + 0x048100U, 0x104008U, 0x000160U, 0x205000U, 0x010204U, 0x0A0800U, 0x010202U, 0x040088U, 0x010200U, 0x010201U, + 0x120010U, 0x040084U, 0x40C000U, 0x002420U, 0x040081U, 0x040080U, 0x010208U, 0x040082U, 0x120008U, 0x402200U, + 0x041400U, 0x0080C0U, 0x288000U, 0x000D00U, 0x010210U, 0x104020U, 0x120000U, 0x120001U, 0x120002U, 0x210100U, + 0x120004U, 0x040090U, 0x002840U, 0x481000U, 0x000180U, 0x000181U, 0x000182U, 0x008030U, 0x000184U, 0x014400U, + 0x500008U, 0x022200U, 0x000188U, 0x0A1000U, 0x500004U, 0x204800U, 0x500002U, 0x040060U, 0x500000U, 0x500001U, + 0x000190U, 0x008022U, 0x008021U, 0x008020U, 0x003040U, 0x480800U, 0x250000U, 0x008024U, 0x040C00U, 0x112000U, + 0x080240U, 0x008028U, 0x02C000U, 0x200280U, 0x500010U, 0x001500U, 0x0001A0U, 0x008012U, 0x008011U, 0x008010U, + 0x220800U, 0x040048U, 0x085000U, 0x008014U, 0x006200U, 0x040044U, 0x030400U, 0x008018U, 0x040041U, 0x040040U, + 0x500020U, 0x040042U, 0x008003U, 0x008002U, 0x008001U, 0x008000U, 0x100600U, 0x008006U, 0x008005U, 0x008004U, + 0x601000U, 0x00800AU, 0x008009U, 0x008008U, 0x090100U, 0x040050U, 0x002880U, 0x00800CU, 0x0001C0U, 0x100A00U, + 0x064000U, 0x411000U, 0x003010U, 0x040028U, 0x008C00U, 0x280100U, 0x218000U, 0x040024U, 0x080210U, 0x002480U, + 0x040021U, 0x040020U, 0x500040U, 0x040022U, 0x003004U, 0x220400U, 0x080208U, 0x008060U, 0x003000U, 0x003001U, + 0x003002U, 0x104080U, 0x080202U, 0x404100U, 0x080200U, 0x080201U, 0x003008U, 0x040030U, 0x080204U, 0x030800U, + 0x480400U, 0x04000CU, 0x302000U, 0x008050U, 0x040009U, 0x040008U, 0x010280U, 0x04000AU, 0x040005U, 0x040004U, + 0x001900U, 0x040006U, 0x040001U, 0x040000U, 0x040003U, 0x040002U, 0x014800U, 0x008042U, 0x008041U, 0x008040U, + 0x003020U, 0x040018U, 0x420100U, 0x008044U, 0x120080U, 0x040014U, 0x080220U, 0x008048U, 0x040011U, 0x040010U, + 0x204400U, 0x040012U, 0x000200U, 0x000201U, 0x000202U, 0x000203U, 0x000204U, 0x000205U, 0x000206U, 0x108400U, + 0x000208U, 0x000209U, 0x00020AU, 0x050080U, 0x00020CU, 0x200110U, 0x083000U, 0x400840U, 0x000210U, 0x000211U, + 0x000212U, 0x021040U, 0x000214U, 0x200108U, 0x004880U, 0x0C0020U, 0x000218U, 0x200104U, 0x400420U, 0x00E000U, + 0x200101U, 0x200100U, 0x130000U, 0x200102U, 0x000220U, 0x000221U, 0x000222U, 0x202800U, 0x000224U, 0x401080U, + 0x010140U, 0x0C0010U, 0x000228U, 0x088040U, 0x400410U, 0x101100U, 0x140800U, 0x012400U, 0x208080U, 0x024200U, + 0x000230U, 0x114000U, 0x400408U, 0x0C0004U, 0x02A000U, 0x0C0002U, 0x0C0001U, 0x0C0000U, 0x400402U, 0x020880U, + 0x400400U, 0x400401U, 0x005040U, 0x200120U, 0x400404U, 0x0C0008U, 0x000240U, 0x000241U, 0x000242U, 0x021010U, + 0x000244U, 0x046000U, 0x010120U, 0x400808U, 0x000248U, 0x088020U, 0x304000U, 0x400804U, 0x020480U, 0x400802U, + 0x400801U, 0x400800U, 0x000250U, 0x021002U, 0x021001U, 0x021000U, 0x580000U, 0x018080U, 0x202400U, 0x021004U, + 0x012800U, 0x140400U, 0x080180U, 0x021008U, 0x005020U, 0x200140U, 0x048200U, 0x400810U, 0x000260U, 0x088008U, + 0x010104U, 0x004480U, 0x010102U, 0x320000U, 0x010100U, 0x010101U, 0x088001U, 0x088000U, 0x062000U, 0x088002U, + 0x005010U, 0x088004U, 0x010108U, 0x400820U, 0x240080U, 0x402100U, 0x108800U, 0x021020U, 0x005008U, 0x000E00U, + 0x010110U, 0x0C0040U, 0x005004U, 0x088010U, 0x400440U, 0x210200U, 0x005000U, 0x005001U, 0x005002U, 0x102080U, + 0x000280U, 0x000281U, 0x000282U, 0x050008U, 0x000284U, 0x401020U, 0x004810U, 0x022100U, 0x000288U, 0x050002U, + 0x050001U, 0x050000U, 0x020440U, 0x184000U, 0x208020U, 0x050004U, 0x000290U, 0x082400U, 0x004804U, 0x700000U, + 0x004802U, 0x018040U, 0x004800U, 0x004801U, 0x109000U, 0x020820U, 0x080140U, 0x050010U, 0x442000U, 0x200180U, + 0x004808U, 0x001600U, 0x0002A0U, 0x401004U, 0x1A0000U, 0x004440U, 0x401001U, 0x401000U, 0x208008U, 0x401002U, + 0x006100U, 0x020810U, 0x208004U, 0x050020U, 0x208002U, 0x401008U, 0x208000U, 0x208001U, 0x240040U, 0x020808U, + 0x013000U, 0x008300U, 0x100500U, 0x401010U, 0x004820U, 0x0C0080U, 0x020801U, 0x020800U, 0x400480U, 0x020802U, + 0x090200U, 0x020804U, 0x208010U, 0x102040U, 0x0002C0U, 0x100900U, 0x40A000U, 0x004420U, 0x020408U, 0x018010U, + 0x141000U, 0x280200U, 0x020404U, 0x203000U, 0x080110U, 0x050040U, 0x020400U, 0x020401U, 0x020402U, 0x400880U, + 0x240020U, 0x018004U, 0x080108U, 0x021080U, 0x018001U, 0x018000U, 0x004840U, 0x018002U, 0x080102U, 0x404200U, + 0x080100U, 0x080101U, 0x020410U, 0x018008U, 0x080104U, 0x102020U, 0x240010U, 0x004402U, 0x004401U, 0x004400U, + 0x082800U, 0x401040U, 0x010180U, 0x004404U, 0x510000U, 0x088080U, 0x001A00U, 0x004408U, 0x020420U, 0x040300U, + 0x208040U, 0x102010U, 0x240000U, 0x240001U, 0x240002U, 0x004410U, 0x240004U, 0x018020U, 0x420200U, 0x102008U, + 0x240008U, 0x020840U, 0x080120U, 0x102004U, 0x005080U, 0x102002U, 0x102001U, 0x102000U, 0x000300U, 0x000301U, + 0x000302U, 0x484000U, 0x000304U, 0x200018U, 0x010060U, 0x022080U, 0x000308U, 0x200014U, 0x028800U, 0x101020U, + 0x200011U, 0x200010U, 0x044400U, 0x200012U, 0x000310U, 0x20000CU, 0x142000U, 0x010C00U, 0x200009U, 0x200008U, + 0x409000U, 0x20000AU, 0x200005U, 0x200004U, 0x0800C0U, 0x200006U, 0x200001U, 0x200000U, 0x200003U, 0x200002U, + 0x000320U, 0x060400U, 0x010044U, 0x101008U, 0x010042U, 0x00C800U, 0x010040U, 0x010041U, 0x006080U, 0x101002U, + 0x101001U, 0x101000U, 0x4A0000U, 0x200030U, 0x010048U, 0x101004U, 0x081800U, 0x402040U, 0x224000U, 0x008280U, + 0x100480U, 0x200028U, 0x010050U, 0x0C0100U, 0x058000U, 0x200024U, 0x400500U, 0x101010U, 0x200021U, 0x200020U, + 0x002A00U, 0x200022U, 0x000340U, 0x100880U, 0x010024U, 0x248000U, 0x010022U, 0x081400U, 0x010020U, 0x010021U, + 0x441000U, 0x034000U, 0x080090U, 0x002600U, 0x10A000U, 0x200050U, 0x010028U, 0x400900U, 0x00C400U, 0x402020U, + 0x080088U, 0x021100U, 0x060800U, 0x200048U, 0x010030U, 0x104200U, 0x080082U, 0x200044U, 0x080080U, 0x080081U, + 0x200041U, 0x200040U, 0x080084U, 0x200042U, 0x010006U, 0x402010U, 0x010004U, 0x010005U, 0x010002U, 0x010003U, + 0x010000U, 0x010001U, 0x200C00U, 0x088100U, 0x01000CU, 0x101040U, 0x01000AU, 0x040280U, 0x010008U, 0x010009U, + 0x402001U, 0x402000U, 0x010014U, 0x402002U, 0x010012U, 0x402004U, 0x010010U, 0x010011U, 0x120200U, 0x402008U, + 0x0800A0U, 0x044800U, 0x005100U, 0x200060U, 0x010018U, 0x028400U, 0x000380U, 0x100840U, 0x201400U, 0x022004U, + 0x0C8000U, 0x022002U, 0x022001U, 0x022000U, 0x006020U, 0x408400U, 0x080050U, 0x050100U, 0x011800U, 0x200090U, + 0x500200U, 0x022008U, 0x430000U, 0x045000U, 0x080048U, 0x008220U, 0x100420U, 0x200088U, 0x004900U, 0x022010U, + 0x080042U, 0x200084U, 0x080040U, 0x080041U, 0x200081U, 0x200080U, 0x080044U, 0x200082U, 0x006008U, 0x290000U, + 0x440800U, 0x008210U, 0x100410U, 0x401100U, 0x0100C0U, 0x022020U, 0x006000U, 0x006001U, 0x006002U, 0x101080U, + 0x006004U, 0x040240U, 0x208100U, 0x080C00U, 0x100404U, 0x008202U, 0x008201U, 0x008200U, 0x100400U, 0x100401U, + 0x100402U, 0x008204U, 0x006010U, 0x020900U, 0x080060U, 0x008208U, 0x100408U, 0x2000A0U, 0x061000U, 0x414000U, + 0x100801U, 0x100800U, 0x080018U, 0x100802U, 0x604000U, 0x100804U, 0x0100A0U, 0x022040U, 0x080012U, 0x100808U, + 0x080010U, 0x080011U, 0x020500U, 0x040220U, 0x080014U, 0x00D000U, 0x08000AU, 0x100810U, 0x080008U, 0x080009U, + 0x003200U, 0x018100U, 0x08000CU, 0x440400U, 0x080002U, 0x080003U, 0x080000U, 0x080001U, 0x080006U, 0x2000C0U, + 0x080004U, 0x080005U, 0x029000U, 0x100820U, 0x010084U, 0x004500U, 0x010082U, 0x040208U, 0x010080U, 0x010081U, + 0x006040U, 0x040204U, 0x080030U, 0x620000U, 0x040201U, 0x040200U, 0x010088U, 0x040202U, 0x240100U, 0x402080U, + 0x080028U, 0x008240U, 0x100440U, 0x0A4000U, 0x010090U, 0x201800U, 0x080022U, 0x011400U, 0x080020U, 0x080021U, + 0x408800U, 0x040210U, 0x080024U, 0x102100U, 0x000400U, 0x000401U, 0x000402U, 0x000403U, 0x000404U, 0x000405U, + 0x000406U, 0x108200U, 0x000408U, 0x000409U, 0x00040AU, 0x002140U, 0x00040CU, 0x4C0000U, 0x210800U, 0x001090U, + 0x000410U, 0x000411U, 0x000412U, 0x244000U, 0x000414U, 0x000860U, 0x0A0100U, 0x001088U, 0x000418U, 0x038000U, + 0x400220U, 0x001084U, 0x106000U, 0x001082U, 0x001081U, 0x001080U, 0x000420U, 0x000421U, 0x000422U, 0x091000U, + 0x000424U, 0x000850U, 0x042080U, 0x600100U, 0x000428U, 0x300080U, 0x400210U, 0x048800U, 0x009100U, 0x012200U, + 0x180040U, 0x024400U, 0x000430U, 0x000844U, 0x400208U, 0x122000U, 0x000841U, 0x000840U, 0x01C000U, 0x000842U, + 0x400202U, 0x084100U, 0x400200U, 0x400201U, 0x260000U, 0x000848U, 0x400204U, 0x0010A0U, 0x000440U, 0x000441U, + 0x000442U, 0x002108U, 0x000444U, 0x000830U, 0x405000U, 0x070000U, 0x000448U, 0x002102U, 0x002101U, 0x002100U, + 0x020280U, 0x20C000U, 0x180020U, 0x002104U, 0x000450U, 0x000824U, 0x110080U, 0x488000U, 0x000821U, 0x000820U, + 0x202200U, 0x000822U, 0x281000U, 0x140200U, 0x024800U, 0x002110U, 0x410100U, 0x000828U, 0x048400U, 0x0010C0U, + 0x000460U, 0x000814U, 0x228000U, 0x004280U, 0x000811U, 0x000810U, 0x180008U, 0x000812U, 0x054000U, 0x421000U, + 0x180004U, 0x002120U, 0x180002U, 0x000818U, 0x180000U, 0x180001U, 0x000805U, 0x000804U, 0x041100U, 0x000806U, + 0x000801U, 0x000800U, 0x000803U, 0x000802U, 0x00A080U, 0x00080CU, 0x400240U, 0x210400U, 0x000809U, 0x000808U, + 0x180010U, 0x00080AU, 0x000480U, 0x000481U, 0x000482U, 0x420800U, 0x000484U, 0x014100U, 0x042020U, 0x001018U, + 0x000488U, 0x300020U, 0x08C000U, 0x001014U, 0x020240U, 0x001012U, 0x001011U, 0x001010U, 0x000490U, 0x082200U, + 0x110040U, 0x00100CU, 0x608000U, 0x00100AU, 0x001009U, 0x001008U, 0x040900U, 0x001006U, 0x001005U, 0x001004U, + 0x001003U, 0x001002U, 0x001001U, 0x001000U, 0x0004A0U, 0x300008U, 0x042004U, 0x004240U, 0x042002U, 0x0A8000U, + 0x042000U, 0x042001U, 0x300001U, 0x300000U, 0x030100U, 0x300002U, 0x404800U, 0x300004U, 0x042008U, 0x001030U, + 0x025000U, 0x450000U, 0x280800U, 0x008500U, 0x100300U, 0x0008C0U, 0x042010U, 0x001028U, 0x00A040U, 0x300010U, + 0x400280U, 0x001024U, 0x090400U, 0x001022U, 0x001021U, 0x001020U, 0x0004C0U, 0x049000U, 0x110010U, 0x004220U, + 0x020208U, 0x502000U, 0x008900U, 0x280400U, 0x020204U, 0x090800U, 0x640000U, 0x002180U, 0x020200U, 0x020201U, + 0x020202U, 0x001050U, 0x110002U, 0x220100U, 0x110000U, 0x110001U, 0x0C4000U, 0x0008A0U, 0x110004U, 0x001048U, + 0x00A020U, 0x404400U, 0x110008U, 0x001044U, 0x020210U, 0x001042U, 0x001041U, 0x001040U, 0x480100U, 0x004202U, + 0x004201U, 0x004200U, 0x211000U, 0x000890U, 0x042040U, 0x004204U, 0x00A010U, 0x300040U, 0x001C00U, 0x004208U, + 0x020220U, 0x040500U, 0x180080U, 0x418000U, 0x00A008U, 0x000884U, 0x110020U, 0x004210U, 0x000881U, 0x000880U, + 0x420400U, 0x000882U, 0x00A000U, 0x00A001U, 0x00A002U, 0x0E0000U, 0x00A004U, 0x000888U, 0x204100U, 0x001060U, + 0x000500U, 0x000501U, 0x000502U, 0x002048U, 0x000504U, 0x014080U, 0x0A0010U, 0x600020U, 0x000508U, 0x002042U, + 0x002041U, 0x002040U, 0x009020U, 0x120800U, 0x044200U, 0x002044U, 0x000510U, 0x501000U, 0x0A0004U, 0x010A00U, + 0x0A0002U, 0x04A000U, 0x0A0000U, 0x0A0001U, 0x040880U, 0x084020U, 0x308000U, 0x002050U, 0x410040U, 0x200600U, + 0x0A0008U, 0x001180U, 0x000520U, 0x060200U, 0x104800U, 0x600004U, 0x009008U, 0x600002U, 0x600001U, 0x600000U, + 0x009004U, 0x084010U, 0x030080U, 0x002060U, 0x009000U, 0x009001U, 0x009002U, 0x600008U, 0x212000U, 0x084008U, + 0x041040U, 0x008480U, 0x100280U, 0x000940U, 0x0A0020U, 0x600010U, 0x084001U, 0x084000U, 0x400300U, 0x084002U, + 0x009010U, 0x084004U, 0x002C00U, 0x150000U, 0x000540U, 0x00200AU, 0x002009U, 0x002008U, 0x340000U, 0x081200U, + 0x008880U, 0x00200CU, 0x002003U, 0x002002U, 0x002001U, 0x002000U, 0x410010U, 0x002006U, 0x002005U, 0x002004U, + 0x00C200U, 0x220080U, 0x041020U, 0x002018U, 0x410008U, 0x000920U, 0x0A0040U, 0x104400U, 0x410004U, 0x002012U, + 0x002011U, 0x002010U, 0x410000U, 0x410001U, 0x410002U, 0x002014U, 0x480080U, 0x118000U, 0x041010U, 0x002028U, + 0x026000U, 0x000910U, 0x010600U, 0x600040U, 0x200A00U, 0x002022U, 0x002021U, 0x002020U, 0x009040U, 0x040480U, + 0x180100U, 0x002024U, 0x041002U, 0x000904U, 0x041000U, 0x041001U, 0x000901U, 0x000900U, 0x041004U, 0x000902U, + 0x120400U, 0x084040U, 0x041008U, 0x002030U, 0x410020U, 0x000908U, 0x204080U, 0x028200U, 0x000580U, 0x014004U, + 0x201200U, 0x1C0000U, 0x014001U, 0x014000U, 0x008840U, 0x014002U, 0x040810U, 0x408200U, 0x030020U, 0x0020C0U, + 0x282000U, 0x014008U, 0x500400U, 0x001110U, 0x040808U, 0x220040U, 0x406000U, 0x008420U, 0x100220U, 0x014010U, + 0x0A0080U, 0x001108U, 0x040800U, 0x040801U, 0x040802U, 0x001104U, 0x040804U, 0x001102U, 0x001101U, 0x001100U, + 0x480040U, 0x003800U, 0x030008U, 0x008410U, 0x100210U, 0x014020U, 0x042100U, 0x600080U, 0x030002U, 0x300100U, + 0x030000U, 0x030001U, 0x009080U, 0x040440U, 0x030004U, 0x080A00U, 0x100204U, 0x008402U, 0x008401U, 0x008400U, + 0x100200U, 0x100201U, 0x100202U, 0x008404U, 0x040820U, 0x084080U, 0x030010U, 0x008408U, 0x100208U, 0x422000U, + 0x204040U, 0x001120U, 0x480020U, 0x220010U, 0x008804U, 0x002088U, 0x008802U, 0x014040U, 0x008800U, 0x008801U, + 0x105000U, 0x002082U, 0x002081U, 0x002080U, 0x020300U, 0x040420U, 0x008808U, 0x002084U, 0x220001U, 0x220000U, + 0x110100U, 0x220002U, 0x003400U, 0x220004U, 0x008810U, 0x440200U, 0x040840U, 0x220008U, 0x080600U, 0x002090U, + 0x410080U, 0x188000U, 0x204020U, 0x001140U, 0x480000U, 0x480001U, 0x480002U, 0x004300U, 0x480004U, 0x040408U, + 0x008820U, 0x121000U, 0x480008U, 0x040404U, 0x030040U, 0x0020A0U, 0x040401U, 0x040400U, 0x204010U, 0x040402U, + 0x480010U, 0x220020U, 0x041080U, 0x008440U, 0x100240U, 0x000980U, 0x204008U, 0x092000U, 0x00A100U, 0x011200U, + 0x204004U, 0x500800U, 0x204002U, 0x040410U, 0x204000U, 0x204001U, 0x000600U, 0x000601U, 0x000602U, 0x108004U, + 0x000604U, 0x108002U, 0x108001U, 0x108000U, 0x000608U, 0x005800U, 0x400030U, 0x2A0000U, 0x0200C0U, 0x012020U, + 0x044100U, 0x108008U, 0x000610U, 0x082080U, 0x400028U, 0x010900U, 0x051000U, 0x424000U, 0x202040U, 0x108010U, + 0x400022U, 0x140040U, 0x400020U, 0x400021U, 0x088800U, 0x200500U, 0x400024U, 0x001280U, 0x000620U, 0x060100U, + 0x400018U, 0x0040C0U, 0x284000U, 0x012008U, 0x021800U, 0x108020U, 0x400012U, 0x012004U, 0x400010U, 0x400011U, + 0x012001U, 0x012000U, 0x400014U, 0x012002U, 0x40000AU, 0x209000U, 0x400008U, 0x400009U, 0x100180U, 0x000A40U, + 0x40000CU, 0x0C0400U, 0x400002U, 0x400003U, 0x400000U, 0x400001U, 0x400006U, 0x012010U, 0x400004U, 0x400005U, + 0x000640U, 0x610000U, 0x0C0800U, 0x0040A0U, 0x020088U, 0x081100U, 0x202010U, 0x108040U, 0x020084U, 0x140010U, + 0x019000U, 0x002300U, 0x020080U, 0x020081U, 0x020082U, 0x400C00U, 0x00C100U, 0x140008U, 0x202004U, 0x021400U, + 0x202002U, 0x000A20U, 0x202000U, 0x202001U, 0x140001U, 0x140000U, 0x400060U, 0x140002U, 0x020090U, 0x140004U, + 0x202008U, 0x094000U, 0x103000U, 0x004082U, 0x004081U, 0x004080U, 0x448000U, 0x000A10U, 0x010500U, 0x004084U, + 0x200900U, 0x088400U, 0x400050U, 0x004088U, 0x0200A0U, 0x012040U, 0x180200U, 0x241000U, 0x0B0000U, 0x000A04U, + 0x400048U, 0x004090U, 0x000A01U, 0x000A00U, 0x202020U, 0x000A02U, 0x400042U, 0x140020U, 0x400040U, 0x400041U, + 0x005400U, 0x000A08U, 0x400044U, 0x028100U, 0x000680U, 0x082010U, 0x201100U, 0x004060U, 0x020048U, 0x240800U, + 0x490000U, 0x108080U, 0x020044U, 0x408100U, 0x102800U, 0x050400U, 0x020040U, 0x020041U, 0x020042U, 0x001210U, + 0x082001U, 0x082000U, 0x068000U, 0x082002U, 0x100120U, 0x082004U, 0x004C00U, 0x001208U, 0x214000U, 0x082008U, + 0x4000A0U, 0x001204U, 0x020050U, 0x001202U, 0x001201U, 0x001200U, 0x018800U, 0x004042U, 0x004041U, 0x004040U, + 0x100110U, 0x401400U, 0x042200U, 0x004044U, 0x0C1000U, 0x300200U, 0x400090U, 0x004048U, 0x020060U, 0x012080U, + 0x208400U, 0x080900U, 0x100104U, 0x082020U, 0x400088U, 0x004050U, 0x100100U, 0x100101U, 0x100102U, 0x230000U, + 0x400082U, 0x020C00U, 0x400080U, 0x400081U, 0x100108U, 0x04C000U, 0x400084U, 0x001220U, 0x02000CU, 0x004022U, + 0x004021U, 0x004020U, 0x020008U, 0x020009U, 0x02000AU, 0x004024U, 0x020004U, 0x020005U, 0x020006U, 0x004028U, + 0x020000U, 0x020001U, 0x020002U, 0x020003U, 0x401800U, 0x082040U, 0x110200U, 0x004030U, 0x020018U, 0x018400U, + 0x202080U, 0x440100U, 0x020014U, 0x140080U, 0x080500U, 0x208800U, 0x020010U, 0x020011U, 0x020012U, 0x001240U, + 0x004003U, 0x004002U, 0x004001U, 0x004000U, 0x020028U, 0x004006U, 0x004005U, 0x004004U, 0x020024U, 0x00400AU, + 0x004009U, 0x004008U, 0x020020U, 0x020021U, 0x020022U, 0x00400CU, 0x240400U, 0x004012U, 0x004011U, 0x004010U, + 0x100140U, 0x000A80U, 0x089000U, 0x004014U, 0x00A200U, 0x011100U, 0x4000C0U, 0x004018U, 0x020030U, 0x680000U, + 0x050800U, 0x102400U, 0x000700U, 0x060020U, 0x201080U, 0x010810U, 0x402800U, 0x081040U, 0x044008U, 0x108100U, + 0x190000U, 0x408080U, 0x044004U, 0x002240U, 0x044002U, 0x200410U, 0x044000U, 0x044001U, 0x00C040U, 0x010802U, + 0x010801U, 0x010800U, 0x1000A0U, 0x200408U, 0x0A0200U, 0x010804U, 0x023000U, 0x200404U, 0x400120U, 0x010808U, + 0x200401U, 0x200400U, 0x044010U, 0x200402U, 0x060001U, 0x060000U, 0x08A000U, 0x060002U, 0x100090U, 0x060004U, + 0x010440U, 0x600200U, 0x200840U, 0x060008U, 0x400110U, 0x101400U, 0x009200U, 0x012100U, 0x044020U, 0x080880U, + 0x100084U, 0x060010U, 0x400108U, 0x010820U, 0x100080U, 0x100081U, 0x100082U, 0x007000U, 0x400102U, 0x084200U, + 0x400100U, 0x400101U, 0x100088U, 0x200420U, 0x400104U, 0x028040U, 0x00C010U, 0x081004U, 0x520000U, 0x002208U, + 0x081001U, 0x081000U, 0x010420U, 0x081002U, 0x200820U, 0x002202U, 0x002201U, 0x002200U, 0x020180U, 0x081008U, + 0x044040U, 0x002204U, 0x00C000U, 0x00C001U, 0x00C002U, 0x010840U, 0x00C004U, 0x081010U, 0x202100U, 0x440080U, + 0x00C008U, 0x140100U, 0x080480U, 0x002210U, 0x410200U, 0x200440U, 0x101800U, 0x028020U, 0x200808U, 0x060040U, + 0x010404U, 0x004180U, 0x010402U, 0x081020U, 0x010400U, 0x010401U, 0x200800U, 0x200801U, 0x200802U, 0x002220U, + 0x200804U, 0x504000U, 0x010408U, 0x028010U, 0x00C020U, 0x402400U, 0x041200U, 0x380000U, 0x1000C0U, 0x000B00U, + 0x010410U, 0x028008U, 0x200810U, 0x011080U, 0x400140U, 0x028004U, 0x0C2000U, 0x028002U, 0x028001U, 0x028000U, + 0x201002U, 0x408008U, 0x201000U, 0x201001U, 0x100030U, 0x014200U, 0x201004U, 0x022400U, 0x408001U, 0x408000U, + 0x201008U, 0x408002U, 0x020140U, 0x408004U, 0x044080U, 0x080820U, 0x100024U, 0x082100U, 0x201010U, 0x010880U, + 0x100020U, 0x100021U, 0x100022U, 0x440040U, 0x040A00U, 0x408010U, 0x080440U, 0x124000U, 0x100028U, 0x200480U, + 0x01A000U, 0x001300U, 0x100014U, 0x060080U, 0x201020U, 0x004140U, 0x100010U, 0x100011U, 0x100012U, 0x080808U, + 0x006400U, 0x408020U, 0x030200U, 0x080804U, 0x100018U, 0x080802U, 0x080801U, 0x080800U, 0x100004U, 0x100005U, + 0x100006U, 0x008600U, 0x100000U, 0x100001U, 0x100002U, 0x100003U, 0x10000CU, 0x011040U, 0x400180U, 0x242000U, + 0x100008U, 0x100009U, 0x10000AU, 0x080810U, 0x052000U, 0x100C00U, 0x201040U, 0x004120U, 0x020108U, 0x081080U, + 0x008A00U, 0x440010U, 0x020104U, 0x408040U, 0x080410U, 0x002280U, 0x020100U, 0x020101U, 0x020102U, 0x310000U, + 0x00C080U, 0x220200U, 0x080408U, 0x440004U, 0x100060U, 0x440002U, 0x440001U, 0x440000U, 0x080402U, 0x011020U, + 0x080400U, 0x080401U, 0x020110U, 0x006800U, 0x080404U, 0x440008U, 0x480200U, 0x004102U, 0x004101U, 0x004100U, + 0x100050U, 0x20A000U, 0x010480U, 0x004104U, 0x200880U, 0x011010U, 0x148000U, 0x004108U, 0x020120U, 0x040600U, + 0x403000U, 0x080840U, 0x100044U, 0x011008U, 0x022800U, 0x004110U, 0x100040U, 0x100041U, 0x100042U, 0x440020U, + 0x011001U, 0x011000U, 0x080420U, 0x011002U, 0x100048U, 0x011004U, 0x204200U, 0x028080U }; #define GORLAY_X22 0x00400000 // vector representation of X^{22} @@ -1227,453 +1219,453 @@ static const U32 DECODING_TABLE_23127[] = { * obtain its syndrome in decoding. */ -static U32 get_syndrome_23127(U32 pattern) +static U32 get_syndrome_23127(U32 pattern) { - U32 aux = GORLAY_X22; - if (pattern >= GORLAY_X11) { - while (pattern & GORLAY_MASK12) { - while ((aux & pattern)==0) aux >>= 1; - pattern ^= (aux / GORLAY_X11) * GORLAY_GENPOL; - } // ehliw - } // fi pattern doesn't fit - return pattern; + U32 aux = GORLAY_X22; + if (pattern >= GORLAY_X11) { + while (pattern & GORLAY_MASK12) { + while ((aux & pattern)==0) aux >>= 1; + pattern ^= (aux / GORLAY_X11) * GORLAY_GENPOL; + } // ehliw + } // fi pattern doesn't fit + return pattern; } // Gorlay API -__inline unsigned int gorlay_encode23127(unsigned int data) +__inline unsigned int gorlay_encode23127(unsigned int data) { - return ENCODING_TABLE_23127[data]; + return ENCODING_TABLE_23127[data]; } -unsigned int gorlay_decode23127(unsigned int code) +unsigned int gorlay_decode23127(unsigned int code) { - U32 syndrome = get_syndrome_23127(code); - U32 error_pattern = DECODING_TABLE_23127[syndrome]; - code ^= error_pattern; - return code >> 11; + U32 syndrome = get_syndrome_23127(code); + U32 error_pattern = DECODING_TABLE_23127[syndrome]; + code ^= error_pattern; + return code >> 11; } -__inline unsigned int gorlay_encode24128(unsigned int data) +__inline unsigned int gorlay_encode24128(unsigned int data) { - return ENCODING_TABLE_24128[data]; + return ENCODING_TABLE_24128[data]; } -__inline unsigned int gorlay_decode24128(unsigned int code) +__inline unsigned int gorlay_decode24128(unsigned int code) { - return gorlay_decode23127(code >> 1); + return gorlay_decode23127(code >> 1); } static const U32 PRNG_TABLE[] = { - 0x42CC47U, 0x19D6FEU, 0x304729U, 0x6B2CD0U, 0x60BF47U, 0x39650EU, 0x7354F1U, 0xEACF60U, 0x819C9FU, 0xDE25CEU, - 0xD7B745U, 0x8CC8B8U, 0x8D592BU, 0xF71257U, 0xBCA084U, 0xA5B329U, 0xEE6AFAU, 0xF7D9A7U, 0xBCC21CU, 0x4712D9U, - 0x4F2922U, 0x14FA37U, 0x5D43ECU, 0x564115U, 0x299A92U, 0x20A9EBU, 0x7B707DU, 0x3BE3A4U, 0x20D95BU, 0x6B085AU, - 0x5233A5U, 0x99A474U, 0xC0EDCBU, 0xCB5F12U, 0x918455U, 0xF897ECU, 0xE32E3BU, 0xAA7CC2U, 0xB1E7C9U, 0xFC561DU, - 0xA70DE6U, 0x8DBE73U, 0xD4F608U, 0x57658DU, 0x0E5E56U, 0x458DABU, 0x7E15B8U, 0x376645U, 0x2DFD86U, 0x64EC3BU, - 0x3F1F60U, 0x3481B4U, 0x4DA00FU, 0x067BCEU, 0x1B68B1U, 0xD19328U, 0xCA03FFU, 0xA31856U, 0xF8EB81U, 0xF9F2F8U, - 0xA26067U, 0xA91BB6U, 0xF19A59U, 0x9A6148U, 0x8372B6U, 0xC8E86FU, 0x9399DCU, 0x1A0291U, 0x619142U, 0x6DE9FFU, - 0x367A2CU, 0x7D2511U, 0x6484DAU, 0x2F1F0FU, 0x1E6DB4U, 0x55F6E1U, 0x0EA70AU, 0x061C96U, 0xDD0E45U, 0xB4D738U, - 0xAF64ABU, 0xE47F42U, 0xFDBE9DU, 0xB684ACU, 0xFE5773U, 0xC1E4A2U, 0x8AFD0DU, 0x932ED4U, 0xD814E3U, 0x81853AU, - 0x225EECU, 0x7A6945U, 0x31A112U, 0x2AB2EBU, 0x630974U, 0x785AB5U, 0x11E3CEU, 0x4A715BU, 0x402AA0U, 0x199B7DU, - 0x16C05EU, 0x6F5283U, 0xA4FB10U, 0xBFA8ECU, 0xF633B7U, 0xEC4012U, 0xADD8C9U, 0xD6EB1CU, 0xDD3027U, 0x84A1FAU, - 0xCF9E19U, 0xD64C80U, 0xBC4557U, 0xA7B62EU, 0x6E2DA1U, 0x311F50U, 0x38C68EU, 0x63D5BFU, 0x486E60U, 0x10BFE1U, - 0x5BAD1EU, 0x4A4647U, 0x0157F0U, 0x7ACC29U, 0x73BEEAU, 0x2825D7U, 0xA0940CU, 0xFBCFF9U, 0xB05C62U, 0x892426U, - 0xC6B3DDU, 0xDF3840U, 0x9449B3U, 0xCED3BEU, 0xE7804DU, 0xBC3B90U, 0xF5AA0BU, 0xE6D17EU, 0x2D43B5U, 0x345A04U, - 0x5EA9DBU, 0x07A202U, 0x0C7134U, 0x45C9FDU, 0x5EDA0AU, 0x310193U, 0x6830C4U, 0x62AA3DU, 0x3B59B2U, 0xB04043U, - 0xEB975CU, 0x82BCADU, 0x912E62U, 0xD8F7FBU, 0x82C489U, 0x895F54U, 0xF00FE7U, 0xFBBC2AU, 0xA2E771U, 0xE956C4U, - 0xF6CD1FU, 0x3F8FEAU, 0x0534E1U, 0x4C653CU, 0x17FE8FU, 0x1C4C52U, 0x4515A1U, 0x2E86A9U, 0x3FBD56U, 0x756C87U, - 0x6ED218U, 0x279179U, 0x7C0AA6U, 0xD53B17U, 0x8EE0C8U, 0x85F291U, 0xD94B36U, 0x9298EFU, 0xAB8318U, 0xE07301U, - 0xBB68DFU, 0xB2CB7CU, 0xE910A5U, 0xE101D2U, 0x92BB4BU, 0x59E8B4U, 0x407175U, 0x0B026AU, 0x12989BU, 0x792944U, - 0x2376EDU, 0x2EF5BAU, 0x758663U, 0x7C1ED5U, 0x078D0CU, 0x4EF6ABU, 0x5567F2U, 0x9F7C29U, 0xC68E9CU, 0xC51747U, - 0xBC6422U, 0xB7EFB9U, 0xECFD44U, 0xA50497U, 0xAF178AU, 0xD68C69U, 0xD97DB5U, 0x82670EU, 0xCBB45BU, 0x508D90U, - 0x190A25U, 0x63F0FEU, 0x68E3C7U, 0x317A10U, 0x3A09D9U, 0x6B926EU, 0x004237U, 0x1B79C8U, 0x53EA59U, 0x48B3B7U, - 0x811166U, 0xDE4A79U, 0xF5F988U, 0xAC6057U, 0xE733FEU, 0xFF89ADU, 0xB49830U, 0x8F4BC3U, 0xC6F00EU, 0x9DA135U, - 0x942FE0U, 0xC71C3BU, 0x4DC78FU, 0x3476C4U, 0x7F6C39U, 0x66BFAAU, 0x298657U, 0x725504U, 0x5B4E89U, 0x01FE72U, - 0x0835A3U, 0x53269CU, 0x189D4DU, 0x01CDC2U, 0xEA763BU, 0xF3A56DU, 0xB0BCD4U, 0xE80F13U, 0xE355CAU, 0x98C47DU, - 0x91AB24U, 0xCE38DBU, 0x87A35AU, 0x9CD3A5U, 0xD648F4U, 0xAF7B6FU, 0x24A292U, 0x7D3011U, 0x764B6DU, 0x2DDABEU, - 0x44D123U, 0x5E22D8U, 0x1FB09DU, 0x04A926U, 0x4F5AF3U, 0x064128U, 0x3DB105U, 0x70AAD6U, 0xAA392FU, 0xA1C4B8U, - 0xF8C7C0U, 0xD35D0FU, 0x8A2E9EU, 0xC1B761U, 0xDA44F0U, 0x925E8FU, 0x89CF4EU, 0xE8B4D1U, 0xB32728U, 0xB8FE7FU, - 0x61DCC6U, 0x2A4701U, 0x1614D8U, 0x5DADE2U, 0x46BE37U, 0x0F44DCU, 0x54D549U, 0x5D8E32U, 0x263DAFU, 0x2C237CU, - 0x75E291U, 0xBE5982U, 0xA74A7FU, 0xC493A4U, 0xDFA131U, 0x967A5AU, 0xCCCB8EU, 0xC1D835U, 0x9A02ECU, 0xF331BBU, - 0xE8B812U, 0xA3EBC5U, 0xBA507CU, 0x7080ABU, 0x099BC2U, 0x02285DU, 0x59718CU, 0x50C273U, 0x0B1862U, 0x4A1F8CU, - 0x70A655U, 0x3BF5C2U, 0x666FBBU, 0x6DDE68U, 0x3485C5U, 0x9F161EU, 0xC46F4BU, 0x8CFDF0U, 0x97C625U, 0xDE058EU, - 0xC59CD3U, 0xAEAE20U, 0xF775BCU, 0xFC647FU, 0xBD9F02U, 0xE70C91U, 0xCC1468U, 0x11E7B7U, 0x1AFC36U, 0x435B49U, - 0x080398U, 0x139027U, 0x7B63FEU, 0x607AF9U, 0x29E900U, 0x7293D6U, 0x79026FU, 0x00D930U, 0x0BEAF1U, 0xD3614EU, - 0x90119FU, 0x8B8AE4U, 0xC61969U, 0xBD609AU, 0xB4F247U, 0xEFA954U, 0xE518A9U, 0xBC0362U, 0xD7D0D6U, 0xCE7E8DU, - 0x856F18U, 0x1C94E3U, 0x578726U, 0x0D5F1DU, 0x24ECC0U, 0x7FF713U, 0x3E26AAU, 0x251D6DU, 0x6A8F14U, 0x53648BU, - 0x19757AU, 0x40AEB4U, 0xCB9CA5U, 0x90055AU, 0x9956C3U, 0xE2ED34U, 0xAB3C7DU, 0xB126EAU, 0xFA9513U, 0xA3D2C8U, - 0x886BFDU, 0xD9F836U, 0xD2A2E3U, 0x8D1359U, 0x454804U, 0x5EDBF7U, 0x37637AU, 0x2C3089U, 0x67ABD4U, 0x3E8847U, - 0x3551BAU, 0x4D6331U, 0x46B8C4U, 0x1D299FU, 0x54120EU, 0x5FC0E1U, 0x86D93BU, 0xE56A0EU, 0xFBB1D5U, 0xB2B600U, - 0xA94EABU, 0xE05DF6U, 0x9BE605U, 0x90B798U, 0xC92C6BU, 0xC3DE66U, 0x9AC7BDU, 0xD15448U, 0x6A3FD3U, 0x23ADA3U, - 0x78346CU, 0x7147F5U, 0x2BDC02U, 0x0EAD5BU, 0x553FFCU, 0x1EA425U, 0x07D5F2U, 0x4C4ECBU, 0x554C14U, 0x3EB3F5U, - 0xE4A26AU, 0xED799BU, 0xB6CA85U, 0xFFD25CU, 0xC421BFU, 0x8F3A22U, 0x96AB51U, 0xDC518CU, 0x895217U, 0x8289F2U, - 0xF9B8A9U, 0xF0231CU, 0x2BF1C7U, 0x62C80AU, 0x781B39U, 0x1320E5U, 0x4AB156U, 0x41EB8FU, 0x1848E0U, 0x13D771U, - 0x4886AEU, 0x203C5FU, 0x3B6F40U, 0x76F6A1U, 0xE5457EU, 0xAE1EE7U, 0xD7AC10U, 0xDCB549U, 0x8476EFU, 0x8FC536U, - 0xD49DE9U, 0x9D0ED8U, 0xA63513U, 0xEFE4A6U, 0xB4DF7DU, 0x3E0D00U, 0x779693U, 0x4CA75EU, 0x0568ADU, 0x527BB0U, - 0x59C34BU, 0x00109FU, 0x0A0B14U, 0x73FA61U, 0x38E0BAU, 0x23530FU, 0x6A88D4U, 0xB199DDU, 0x98322AU, 0xC260F3U, - 0xCBF944U, 0x908A0DU, 0xDB11F2U, 0xC28163U, 0xADFABDU, 0xBC694CU, 0xF65243U, 0xAD83BAU, 0xA40D6DU, 0x5F7EF4U, - 0x16E787U, 0x0DF44AU, 0x460EF1U, 0x5E1F24U, 0x15CC3FU, 0x6C77CAU, 0x676401U, 0x3C9CBDU, 0x359FEEU, 0x6A0413U, - 0x02F590U, 0x91EE4DU, 0xDA3C3EU, 0xC305A3U, 0x889658U, 0xF14D99U, 0xFA7F86U, 0xA1E677U, 0xE981E8U, 0xF21A10U, - 0xBB4BD7U, 0x80F1CEU, 0xCB6239U, 0x123BE0U, 0x1D885FU, 0x45921EU, 0x6641E1U, 0x3DE870U, 0x74BBAFU, 0x6F00C6U, - 0x261055U, 0x7DCBA8U, 0x57787AU, 0x0E2167U, 0x05B28CU, 0xCC8819U, 0x975BE2U, 0xBC52B7U, 0xE5E52CU, 0xEB37C9U, - 0xB20E12U, 0xF9DD2FU, 0xE8C6FCU, 0x837701U, 0xD8AD82U, 0xD1BE5AU, 0x0B0525U, 0x0244B4U, 0x79FE5BU, 0x322DCAU, - 0x2B3495U, 0x60876CU, 0x79DCFBU, 0x334C12U, 0x4C7745U, 0x45A4DCU, 0x1E3F23U, 0x175FF2U, 0xC4C0D8U, 0xAFF30DU, - 0xB72AF6U, 0xFCB96BU, 0xA5C338U, 0xAE5295U, 0xF54946U, 0xDCBABBU, 0x87A1A8U, 0xCF2165U, 0xD4DA9EU, 0x9FC90BU, - 0x223070U, 0x6922A4U, 0x30B92FU, 0x3348D6U, 0x695B01U, 0x20C038U, 0x1BB2EFU, 0x523B06U, 0x49EC99U, 0x02D7C8U, - 0x5B4777U, 0x713CA6U, 0xA8AF49U, 0xA3B650U, 0xF84586U, 0xB5DF7FU, 0xAE8CF8U, 0xC72581U, 0x9D3652U, 0x9EEDCFU, - 0xC75D34U, 0xCC0671U, 0xB5B5CAU, 0xFEAC1FU, 0x677EA4U, 0x2DC5F9U, 0x26D63AU, 0x7F1F86U, 0x142855U, 0x0DF2A8U, - 0x42E3B3U, 0x195872U, 0x108B8DU, 0x6AB31CU, 0x632063U, 0x307BAAU, 0xFBC83DU, 0xE201C4U, 0xA91393U, 0x90A82AU, - 0xDAF9E4U, 0x816A55U, 0x88D00AU, 0xD383DBU, 0xFA3A64U, 0xA569A5U, 0xEEE2DEU, 0x76D243U, 0x3D0D90U, 0x649E6DU, - 0x47E76EU, 0x1C7491U, 0x156E49U, 0x4E9DDEU, 0x0604B7U, 0x3D3720U, 0x76FDD9U, 0x6FEC06U, 0x2417B7U, 0xFD04F8U, - 0xF29D29U, 0x886F92U, 0xC1744FU, 0xDAC73CU, 0x939EB1U, 0x880C63U, 0xEBE79EU, 0xB2F285U, 0xB86970U, 0xE11ABBU, - 0xEA822EU, 0x311155U, 0x586AC0U, 0x43F92BU, 0x0A81F6U, 0x5412C5U, 0x5D111CU, 0x26E8CBU, 0x2D7B63U, 0x74213CU, - 0x3F90CDU, 0x2E8B52U, 0x645883U, 0xDFE36CU, 0x96F375U, 0xDD0882U, 0xC40B1BU, 0x8FD6CCU, 0xB464A5U, 0xFC7F3EU, - 0xA7AECBU, 0xAA9511U, 0xF10634U, 0xBA5CEFU, 0x83ED32U, 0x483681U, 0x5015DCU, 0x138D3FU, 0x48DEA2U, 0x616571U, - 0x3AF40CU, 0x33AF97U, 0x681D72U, 0x2246E9U, 0x3BD7B9U, 0x506C46U, 0x0D2FDFU, 0x869338U, 0xDDC061U, 0xD45BD6U, - 0xAF6A0FU, 0xE7B8C0U, 0xFC2371U, 0xBF102EU, 0xA6C9DFU, 0xEDDA40U, 0x943089U, 0x9FA1BFU, 0x459A66U, 0x0C4995U, - 0x175108U, 0x7AE243U, 0x6139B6U, 0x2A2A2DU, 0x73D3D8U, 0x79C183U, 0x204A26U, 0x0B3FFDU, 0x5AA420U, 0x111613U, - 0x8A4FDFU, 0xC3DC2CU, 0xF9A7B5U, 0xB034EAU, 0xEBAC5BU, 0xE0CF94U, 0xBD5465U, 0xF605FAU, 0xCFBEA3U, 0x85AC54U, - 0x9E55DDU, 0xD7C62AU, 0x0CDD73U, 0x252FCDU, 0x76361CU, 0x7DF5D3U, 0x3546E2U, 0x6E5B39U, 0x67A98CU, 0x1CB247U, - 0x57231AU, 0x4AD8A9U, 0x01CA74U, 0x191187U, 0xF2208AU, 0xA9AB50U, 0xA0F8A5U, 0xFB403EU, 0xF2D34BU, 0xA9A880U, - 0xCB393DU, 0xD262EEU, 0x99D0B7U, 0xC04B00U, 0xCB1AC9U, 0xB0B176U, 0x39E3A7U, 0x677EF8U, 0x2ECD58U, 0x359687U, - 0x7E277EU, 0x473D69U, 0x0CEEB0U, 0x55D557U, 0x5F04CEU, 0x0C8EBDU, 0x25BD60U, 0x7E64DBU, 0xB7771EU, 0xACCC05U, - 0xE51CF0U, 0xBF2F2AU, 0x90F497U, 0xC9E7D4U, 0xC25F09U, 0x9B9CBAU, 0xD08767U, 0xEB320CU, 0xA36999U, 0x38FB42U, - 0x7180B3U, 0x22112CU, 0x29AA45U, 0x50F9D2U, 0x1B610AU, 0x0202FDU, 0x4899E4U, 0x57080BU, 0x3E72DAU, 0x65E165U, - 0x6CFA34U, 0xB70BEBU, 0xBC104AU, 0xE4E295U, 0x8F7BECU, 0x96787FU, 0xD583B2U, 0x9E9740U, 0x870C5DU, 0xECFFA6U, - 0xF4E433U, 0xBF35F8U, 0xE00F8DU, 0x699C16U, 0x3265EBU, 0x1B6638U, 0x40F515U, 0x0A8DC6U, 0x131E1BU, 0x5845A0U, - 0x21F670U, 0x2A6E1FU, 0x791D8EU, 0x708651U, 0x2AD7E8U, 0xE37CAFU, 0xD8EE56U, 0x97B3C1U, 0x8E0018U, 0xC51B6FU, - 0x9CC9E6U, 0xB67019U, 0xEF23C8U, 0xE498F2U, 0xBF9927U, 0xF643ECU, 0xCD7051U, 0x04E902U, 0x563AFFU, 0x5D006CU, - 0x04D3A1U, 0x0FCA9AU, 0x72794FU, 0x39A2B4U, 0x228231U, 0x6A19EAU, 0x714E96U, 0x18F705U, 0x4324FCU, 0xC83E3BU, - 0x918D02U, 0xDADCD5U, 0xC2470CU, 0xA135B3U, 0xBABCF2U, 0xF30F4DU, 0xA8549EU, 0xA1C543U, 0xDEFF78U, 0xD42CBCU, - 0x0DB747U, 0x46C6D2U, 0x5F5C89U, 0x144F60U, 0x6FA6F7U, 0x66350EU, 0x2C0A59U, 0x35DAE0U, 0x7EC12FU, 0x0D32FEU, - 0x0429C1U, 0x5FB911U, 0xD642AEU, 0x895167U, 0xC3D8B0U, 0xFAAB89U, 0xB1315AU, 0xA8C0A7U, 0xE3DB24U, 0xB84879U, - 0x913382U, 0xCBA317U, 0x82F8FCU, 0x994BA9U, 0x50C213U, 0x4390CEU, 0x282F5DU, 0x713E30U, 0x7FCDE3U, 0x26565EU, - 0x2D0485U, 0x56BDD4U, 0x1FAE7BU, 0x0475AAU, 0x4DD555U, 0x17CE4CU, 0x9C1D9BU, 0xE52473U, 0xEEF7E4U, 0xB7CD1DU, - 0xF45E42U, 0xEF87E3U, 0x87B43CU, 0x986FADU, 0xD16FD2U, 0x8AD403U, 0x8103A8U, 0xD83A75U, 0x33A826U, 0x2BF39BU, - 0x604049U, 0x7B99A4U, 0x328ABFU, 0x49306AU, 0x407191U, 0x1BEA04U, 0x19D96FU, 0x4001F2U, 0x0FB201U, 0x36E9DCU, - 0xFD7ADFU, 0xE64326U, 0xAF91F9U, 0xF51249U, 0xDC2B16U, 0x87F8D7U, 0xCCE668U, 0xC517B1U, 0x9E8C46U, 0x97BF5FU, - 0xED6498U, 0xA67461U, 0x378FF6U, 0x788C8FU, 0x611514U, 0x0AE6F1U, 0x53FC2BU, 0x596F3EU, 0x0216C5U, 0x4B8508U, - 0x507FBBU, 0x396EE6U, 0x22F535U, 0xE99688U, 0xB10F43U, 0xBA1D36U, 0xC3E2ADU, 0xC07178U, 0x9B28C3U, 0xD69A8BU, - 0xCD817CU, 0x8570E5U, 0xFEEB12U, 0xF5E8CBU, 0xAC10C4U, 0x270335U, 0x7ED8EAU, 0x156B5BU, 0x0E7A14U, 0x46A0C5U, - 0x5D937AU, 0x144AA3U, 0x4F79D5U, 0x6CF35CU, 0x31228FU, 0x7A1932U, 0x628E69U, 0xA9D59CU, 0x926517U, 0xDBBEE2U, - 0x80ADB9U, 0x891424U, 0xD246D7U, 0xD8ED1AU, 0xA17C28U, 0xEA27F5U, 0xF3942EU, 0xB8CE8FU, 0xAB5FD0U, 0x466461U, - 0x1CB7BEU, 0x152F6FU, 0x4E1CC0U, 0x05D799U, 0x1CE66EU, 0x773DF7U, 0x7EAB00U, 0x249048U, 0x6D41D7U, 0x765A26U, - 0x1DA9F9U, 0x8431C8U, 0xCF0203U, 0x96C1DEU, 0x90D86DU, 0xCB6A30U, 0xA23193U, 0xB9A24EU, 0xF05B95U, 0xEB48A0U, - 0xA0D27AU, 0xD8A39FU, 0xD33804U, 0x0A9B79U, 0x01C3AAU, 0x5A5437U, 0x132FD4U, 0x28BC0DU, 0x60253AU, 0x3F57E3U, - 0x3CCC7CU, 0x65DD9DU, 0x4E26C2U, 0x172572U, 0xDCDDADU, 0xC64E64U, 0x8F5553U, 0x94A68AU, 0xFDBE7DU, 0xA66DE4U, - 0xADD68BU, 0xF4C75AU, 0xFE0CC1U, 0x873E34U, 0xC8A72FU, 0xDBD0C2U, 0x124B10U, 0x49998DU, 0x40A8FEU, 0x3A3323U, - 0x316088U, 0x68D95DU, 0x235B06U, 0x3A00B3U, 0x51B178U, 0x4AEA89U, 0x025816U, 0x59C36FU, 0xD092B8U, 0x8B2930U, - 0xE43AC7U, 0xF5E2DEU, 0xBEC121U, 0xA71AF0U, 0xED8B7FU, 0x94B40EU, 0x9F66D1U, 0xD45D68U, 0xCD8CBFU, 0x8617F6U, - 0x5F2545U, 0x75FC98U, 0x2EFF62U, 0x674467U, 0x7C959CU, 0x318F09U, 0x0A7CD2U, 0x4967AFU, 0x11D62CU, 0x1A8CD1U, - 0x431F02U, 0x48A69DU, 0xB3E5ECU, 0xFA7623U, 0xE10E9AU, 0xA99948U, 0xB20215U, 0xD971A6U, 0x80E86BU, 0x8BDA90U, - 0xD60185U, 0x9D907EU, 0x8FFBFBU, 0xE66920U, 0x7D705DU, 0x3483CEU, 0x6F9833U, 0x646BF1U, 0x1DF3E8U, 0x17E017U, - 0x4E1BC6U, 0x050A79U, 0x1E8038U, 0x5773E7U, 0x2C685EU, 0xA1BD89U, 0xFB86B0U, 0xF01477U, 0xA16D8EU, 0xCAFE19U, - 0xD365C1U, 0x9815AEU, 0x839E3FU, 0xCBCDC4U, 0x907611U, 0xB9E70AU, 0xE2BDE7U, 0x2B0E34U, 0x301789U, 0x7BE4DAU, - 0x477707U, 0x0C2FACU, 0x558C79U, 0x5E9743U, 0x0D4496U, 0x04786DU, 0x7FABE0U, 0x3730B3U, 0x3C014AU, 0xE7DADDU, - 0xEEE834U, 0x956163U, 0xDCB2FAU, 0xC78905U, 0x8D5BD4U, 0xD0427BU, 0xDBF12BU, 0xA22AB4U, 0xA93B4DU, 0xFA819AU, - 0xB3D2B3U, 0x287B64U, 0x40289DU, 0x5BB206U, 0x100153U, 0x495CB8U, 0x42CF2DU, 0x3BF4D6U, 0x70248BU, 0x6ABF19U, - 0x23CCF4U, 0x3C4527U, 0x75761AU, 0x8EACC1U, 0x853F44U, 0xD44EBFU, 0xDED5EEU, 0x87C751U, 0xEC3E80U, 0xF72D6FU, - 0xBEB676U, 0xE557A1U, 0xEC4D59U, 0xB6BECEU, 0x9DA527U, 0x443078U, 0x0BCAE9U, 0x12D916U, 0x594087U, 0x6033E8U, - 0x22A831U, 0x7948A2U, 0x70535FU, 0x2BC01CU, 0x62BBA1U, 0x592A7BU, 0x92308EU, 0x8AC395U, 0xC15A50U, 0x9809ABU, - 0xB3B336U, 0xECB245U, 0xE54998U, 0xBEDA1BU, 0xF681E6U, 0xED35F5U, 0x8E2E0CU, 0x87FDD3U, 0x5CC453U, 0x1556ACU, - 0x0E85FDU, 0x64AC42U, 0x3D7F8BU, 0x36447CU, 0x6FD665U, 0x640FB2U, 0x3B3C4BU, 0x52A7C4U, 0x48F7B5U, 0x014C2EU, - 0x9A9FFBU, 0xD19601U, 0xA0250CU, 0xAB7FFFU, 0xF2C822U, 0xB8D1B1U, 0xA302CCU, 0xEAB907U, 0xD1E9B2U, 0x987269U, - 0xC3411CU, 0xCC8897U, 0x141A42U, 0x3F61B8U, 0x66F2A1U, 0x2DCB56U, 0x3618DFU, 0x778208U, 0x2CB3F1U, 0x0468EEU, - 0x5F7B1FU, 0x5693D0U, 0x0D8041U, 0x461B3EU, 0xFFECE7U, 0xB4FD50U, 0xA94798U, 0xE314CFU, 0xB88D76U, 0xB17EADU, - 0xCA7508U, 0xC3E553U, 0x989EA6U, 0xDB0D3DU, 0xC396E8U, 0xA8E683U, 0x717D1EU, 0x7A0EEDU, 0x219730U, 0x288422U, - 0x736ECFU, 0x1BFF14U, 0x04A4A1U, 0x4F177AU, 0x56092BU, 0x1DD884U, 0x64635DU, 0xEF70EAU, 0xA589B3U, 0xF49B54U, - 0xFF50CDU, 0xA66312U, 0x8DFA62U, 0xD628FDU, 0x9F131CU, 0x8582C3U, 0xCCF9DAU, 0xF36A29U, 0xB8B2F4U, 0x618157U, - 0x6A020AU, 0x335999U, 0x79E864U, 0x4272BFU, 0x03259AU, 0x189C40U, 0x51CFB5U, 0x0A752EU, 0x216463U, 0x79BF90U, - 0x721C0DU, 0xAB47FEU, 0xE4D727U, 0xFDEC28U, 0x963FD9U, 0x8DA646U, 0xC594B7U, 0x9E4FE8U, 0x977E60U, 0xECA597U, - 0xAF264EU, 0xB61C79U, 0xFDCDA0U, 0x65D64FU, 0x2E61DCU, 0x553881U, 0x5CAA72U, 0x0351FBU, 0x0A400CU, 0x51FB55U, - 0x3BB9CAU, 0x22223AU, 0x6993B5U, 0x30C8C4U, 0x3B5B1BU, 0xE02B82U, 0xC1B075U, 0x9B23BCU, 0xD25A8BU, 0xC9C852U, - 0x82A3A9U, 0xBB303CU, 0xF42977U, 0xADDA82U, 0xA64418U, 0xFC55E5U, 0xB5AEE6U, 0x0EBD3BU, 0x4765C8U, 0x4CD655U, - 0x17DD2EU, 0x562EEBU, 0x6C3770U, 0x25A585U, 0x3E5EDEU, 0x754F6FU, 0x2C94A1U, 0x23A758U, 0x5A3F4FU, 0xD07C96U, - 0x8BC761U, 0xC254E8U, 0xD92C97U, 0xB0BF06U, 0xEBE0D9U, 0xE25138U, 0xB8CAA7U, 0xBB98DEU, 0xE22109U, 0x896291U, - 0x10F172U, 0x5BCB2FU, 0x401A94U, 0x0CA141U, 0x77B2BAU, 0x7E6BBFU, 0x255964U, 0x6E82D9U, 0x77130AU, 0x3C3877U, - 0x04EAF4U, 0x4FD129U, 0x9C40DBU, 0x959BC6U, 0xCEAC2DU, 0xE774FCU, 0xBC6763U, 0xF6DC12U, 0xEB8DCDU, 0xA00664U, - 0xF9F4B3U, 0xD2EF4AU, 0x895E5DU, 0x800584U, 0x5A972BU, 0x132EFBU, 0x287D84U, 0x63E615U, 0x7297CEU, 0x391D23U, - 0x608E30U, 0x6AF5CDU, 0x11641EU, 0x5C5E93U, 0x4789E0U, 0x0E903DU, 0x956386U, 0xFEF053U, 0xB6E879U, 0xAD0BACU, - 0xE41077U, 0xFF83CAU, 0xB47A99U, 0xCD6870U, 0xCE93E7U, 0x96823EU, 0x9D1941U, 0xC4EBD0U, 0x2BF23FU, 0x3031EEU, - 0x790A71U, 0x229909U, 0x2AC1CEU, 0x717677U, 0x5AEDA0U, 0x039C99U, 0x480646U, 0x515587U, 0x1AEC3CU, 0x296F69U, - 0xE13492U, 0xBA8607U, 0xB39FCCU, 0xEC4CB1U, 0xA77723U, 0x9EA7DEU, 0xD51C0DU, 0xCD0F00U, 0x86D4FBU, 0xDDF56EU, - 0xF46F95U, 0x2FBCD4U, 0x268D6BU, 0x7D52B2U, 0x374165U, 0x26F9DCU, 0x4D2A9BU, 0x141163U, 0x1FD2FCU, 0x40CA2DU, - 0x497952U, 0x3322D3U, 0x7AB32CU, 0xE108F5U, 0xAA5AE2U, 0xB3E31BU, 0xF8B098U, 0x812B65U, 0x8B8936U, 0xD0D08AU, - 0xD94341U, 0x8A7894U, 0xE3A9AFU, 0xF8377AU, 0xB74481U, 0x6FDD0CU, 0x64EE5FU, 0x3D35A2U, 0x163731U, 0x5F8ECCU, - 0x045DC7U, 0x0F4616U, 0x57B6E8U, 0x7CAD79U, 0x253E86U, 0x6EC7CFU, 0x7DD478U, 0xB426A1U, 0xCF2D76U, 0xC3BC5FU, - 0x984780U, 0x935571U, 0xCACCEEU, 0x81BBBFU, 0xB82054U, 0xF371C0U, 0xE9CB3BU, 0xA05826U, 0xFB33F5U, 0x52A218U, - 0x09B88BU, 0x424BF6U, 0x53D22DU, 0x198198U, 0x043A53U, 0x6F2A06U, 0x34F1BDU, 0x3DC260U, 0x664982U, 0x6FB81BU, - 0x15A24CU, 0xDE71F5U, 0xC7482AU, 0x8CDFCBU, 0x9505D4U, 0xDE3405U, 0xA5EFFAU, 0xA4FC63U, 0xFE5704U, 0xB387DDU, - 0xA8BC6AU, 0xC32FB2U, 0x5A7EE5U, 0x11C44CU, 0x489797U, 0x420E62U, 0x19BD79U, 0x30E6BCU, 0x6B6407U, 0x225DDAU, - 0x398EA9U, 0x703534U, 0x0A64F7U, 0x09FA0AU, 0xD4C910U, 0xDF10E5U, 0x86833EU, 0xCDB99BU, 0xE67A40U, 0xBE631BU, - 0xB590AEU, 0xEC8B75U, 0xA73BD0U, 0x9CE08BU, 0xD5F35EU, 0x8E0AE5U, 0x061828U, 0x5D835AU, 0x5660C7U, 0x277914U, - 0x68CAE9U, 0x7190E2U, 0x3A0113U, 0x20FECCU, 0x49ED7DU, 0x127522U, 0x1B06ABU, 0x40855CU, 0x8B9E85U, 0x926FB2U, - 0xF8F56AU, 0xE186A5U, 0xAA1F14U, 0xF10CCBU, 0xF0F7BAU, 0x8F6735U, 0x867CECU, 0xDC9F1FU, 0x978402U, 0x8E54F1U, - 0x45EF3CU, 0x7CFC8FU, 0x3705D2U, 0x6C1248U, 0x64C8BDU, 0x3FF976U, 0x566243U, 0x4DA198U, 0x069B45U, 0x1F0AF6U, - 0x5851BBU, 0x00E248U, 0xAB3BD1U, 0xF2090EU, 0xF9926FU, 0xA2C3F1U, 0xEB7800U, 0xD07B9FU, 0x98A1E6U, 0xC31021U, - 0xC84BB8U, 0x91D84FU, 0x9AEC96U, 0x6337A9U, 0x288468U, 0x369FB3U, 0x774E06U, 0x6C645DU, 0x05B7A9U, 0x4E2E22U, - 0x551DFFU, 0x1CC78CU, 0x47D611U, 0x4F2DF2U, 0x343E6FU, 0xBF8514U, 0xE655C1U, 0xAD5E5AU, 0xB4EDBFU, 0xDFB4E4U, - 0xC1265DU, 0x80DD8BU, 0xDBC852U, 0xD25375U, 0x8920ACU, 0xA2BA53U, 0xFB0BC2U, 0x31401DU, 0x28D33CU, 0x63AAE3U, - 0x18381AU, 0x11238DU, 0x4AD2E4U, 0x434933U, 0x195BABU, 0x56A058U, 0x6FB105U, 0x2C5AAEU, 0x35C97BU, 0xFED9A0U, - 0xA52295U, 0x8D314EU, 0xD6ECA3U, 0x9F5E30U, 0x84456DU, 0xCFB6DEU, 0xD6AF03U, 0xBD2CE9U, 0xE556FCU, 0xEEC707U, - 0xB71CD6U, 0x382F59U, 0x43B720U, 0x02E4F7U, 0x195F4EU, 0x51CC99U, 0x0AA550U, 0x013767U, 0x786CBEU, 0x73DD01U, - 0x2AC6D1U, 0x61159EU, 0x7BA92FU, 0x92BAF4U, 0x896109U, 0xC0521AU, 0x9F9AF7U, 0x942924U, 0xC532B9U, 0xEFE3C2U, - 0xA6D807U, 0xFD0ABCU, 0xF69369U, 0xAFA033U, 0x44738EU, 0x5D694DU, 0x17C8F0U, 0x0C93A3U, 0x45207AU, 0x1EF9C5U, - 0x37EB04U, 0x6850FBU, 0x6305EAU, 0x3B9E15U, 0x782DC4U, 0x41774BU, 0x8AF633U, 0xD18DE4U, 0xD81E5DU, 0x83A69AU, - 0x8AF583U, 0xF06E7CU, 0xBB5FADU, 0xA28416U, 0xE99653U, 0xF06D88U, 0x9FEC35U, 0xC4F7E6U, 0x4C059AU, 0x1F1C19U, - 0x56EFC4U, 0x4D743FU, 0x24612AU, 0x3F9BD1U, 0x748814U, 0x2C13AFU, 0x27F276U, 0x5EE861U, 0x553B88U, 0x0E0A5FU, - 0xC791E6U, 0xD8E2B0U, 0x907A69U, 0xABE9C6U, 0xE09217U, 0xB10168U, 0xBA48F9U, 0xE3FA26U, 0x8861CFU, 0x9230D8U, - 0xDB8B21U, 0xC099B2U, 0x09644FU, 0x52F704U, 0x79AC90U, 0x201F6BU, 0x2E17BEU, 0x77C495U, 0x3CFF48U, 0x172E9BU, - 0x4E9426U, 0x0D8775U, 0x145E98U, 0x5E6D03U, 0xC5F6D6U, 0xAC242DU, 0xF70D3CU, 0xFEDED2U, 0xA5C543U, 0xAE74BCU, - 0xD62EE5U, 0x9D9D72U, 0x80029BU, 0xCB534CU, 0x90E175U, 0x19BAAAU, 0x6A3B6BU, 0x6280D4U, 0x39D385U, 0x724B7AU, - 0x6B78E2U, 0x00A321U, 0x19101CU, 0x5248CFU, 0x0ADB30U, 0x01F0A9U, 0x5A21CEU, 0xB73A17U, 0xACC880U, 0xE55179U, - 0xFE42A6U, 0xB4B987U, 0xC5AF58U, 0xCE1688U, 0x97C533U, 0x9CCE76U, 0xC73F8DU, 0x8E2510U, 0xB4B6C3U, 0x7D4FFEU, - 0x665C3DU, 0x2DC7C0U, 0x70B55BU, 0x5B2C2EU, 0x025FF5U, 0x49D470U, 0x53448AU, 0x1A3FD7U, 0x09AC64U, 0x60BDBDU, - 0x3B467AU, 0xB0D043U, 0xE98B9CU, 0xE33A2DU, 0x9A21E2U, 0xD1C3B3U, 0xCA5A0CU, 0x8709DDU, 0xDCB222U, 0xF5A3AAU, - 0xBF79DDU, 0xA44A04U, 0xEDD193U, 0x3E006AU, 0x373B21U, 0x4CF994U, 0x47C04FU, 0x1F53DAU, 0x5488A1U, 0x4DB86CU, - 0x2623DFU, 0x7D7402U, 0x70CF50U, 0x2B9EFDU, 0x232426U, 0xF8A7D3U, 0x91FEC8U, 0x8A4D39U, 0xC117F6U, 0xD0866FU, - 0x9B3D18U, 0xE36EC1U, 0xE8F576U, 0xB3C5BFU, 0xBA1629U, 0xE1BD50U, 0xA8EC8FU, 0x17763EU, 0x5D45F1U, 0x049CA0U, - 0x0F8F1FU, 0x5630C6U, 0x7DE225U, 0x26FB38U, 0x6F08CBU, 0x7D0316U, 0x34B28DU, 0x2F68E9U, 0xC47B72U, 0x9DC287U, - 0x96915CU, 0xCF0B41U, 0x85F8A2U, 0xBAE17FU, 0xF372CCU, 0xE81991U, 0xA1894AU, 0xFAF2EBU, 0xF16134U, 0x89F845U, - 0x0A8ADBU, 0x53153AU, 0x1806E5U, 0x03FF7CU, 0x6A7C0BU, 0x312692U, 0x399775U, 0x628CACU, 0x6D7FB3U, 0x34EE42U, - 0x5FF49DU, 0x56073CU, 0x8D1C67U, 0x87CDBBU, 0xDEE708U, 0xB574D5U, 0xA4ADB6U, 0xEF9E2BU, 0xF605D0U, 0xBD7545U, - 0xE6EE0EU, 0xCE39FBU, 0x950260U, 0xD8929DU, 0x43D9CEU, 0x086A47U, 0x31B3B1U, 0x7AA068U, 0x221ADFU, 0x294B86U, - 0x72F049U, 0x73E3F8U, 0x083927U, 0x418856U, 0x5AC3C9U, 0x105020U, 0xC969B7U, 0xE2BBEEU, 0xBF2019U, 0xB41181U, - 0xEFCA6AU, 0xA6FD3FU, 0xBC27A4U, 0xD53651U, 0xCE9D9AU, 0x854EA7U, 0xDC5E74U, 0xDFE5A9U, 0x26B61AU, 0x6C0D57U, - 0x77DCECU, 0x3EC639U, 0x2575C3U, 0x682CD6U, 0x13AF1DU, 0x1855ECU, 0x404473U, 0x4BDF8AU, 0x12ACDDU, 0xF93754U, - 0xE207A3U, 0xABD87AU, 0xF04B45U, 0xF03284U, 0xABB05BU, 0x80ABEBU, 0xD95AB4U, 0x92C10DU, 0x8FD2CEU, 0xC42833U, - 0xEC3920U, 0x37C2FDU, 0x7C5106U, 0x654883U, 0x2EAAF8U, 0x37B12DU, 0x5C20B6U, 0x065B42U, 0x07C909U, 0x5C12B4U, - 0x152367U, 0x2EB4FAU, 0x65CF19U, 0xFC5F40U, 0xB294FFU, 0xEBA72EU, 0xE03ED1U, 0x9B6CD0U, 0x92D70FU, 0xC944F6U, - 0x801D60U, 0x9AAE19U, 0xF1F4DEU, 0xA85547U, 0xAB4EB8U, 0x729DE9U, 0x792456U, 0x223697U, 0x4BED0CU, 0x55DE71U, - 0x1C03A2U, 0x07910FU, 0x4CAADCU, 0x356BA0U, 0x3E5033U, 0x67C3EEU, 0x2D9B05U, 0xB62810U, 0xFFF3EBU, 0xC4E03EU, - 0x8558A5U, 0xDE0B48U, 0xD5905BU, 0x8D71A2U, 0xA26A75U, 0xFBD8ECU, 0xB08982U, 0xAB1253U, 0xE2A1ECU, 0x79FB3FU, - 0x116E52U, 0x4A15C9U, 0x43861CU, 0x188FE7U, 0x537DF2U, 0x62E619U, 0x29D7C0U, 0x310C57U, 0x7A1F2EU, 0x25E5B8U, - 0xAC7451U, 0xC76F86U, 0xDE9C9FU, 0x959460U, 0xCF27B1U, 0xC6FC1EU, 0xBDEDCFU, 0xF416B0U, 0xEF0429U, 0xA49FEEU, - 0xBDEA17U, 0xFF7104U, 0x06A3F8U, 0x0D8A63U, 0x5219A6U, 0x5B62DDU, 0x00F348U, 0x6969B3U, 0x731A6EU, 0x38816DU, - 0x61D090U, 0x6A6343U, 0x33F9FEU, 0x18B8A5U, 0xC30340U, 0x8B10DAU, 0x98E80BU, 0xD1FB74U, 0xEA20F5U, 0xA5930AU, - 0xFC8E93U, 0xF75CC4U, 0xAF673DU, 0xA4E6BAU, 0xDF3D43U, 0x960F9CU, 0x0DD68DU, 0x44E572U, 0x1F7EB2U, 0x35AD09U, - 0x6C9554U, 0x6746A7U, 0x365D3AU, 0x7DFCF9U, 0x64A6C4U, 0x0B351FU, 0x118CEAU, 0x58DF61U, 0x836434U, 0x8A36CFU, - 0xF1AB5BU, 0xBA18A0U, 0xA343EDU, 0xE8C27EU, 0xF0F887U, 0xBB2B50U, 0xC03A69U, 0xC9C1A6U, 0x9A5317U, 0x9368C8U, - 0x5CB919U, 0x26A226U, 0x2F01EFU, 0x74D919U, 0x3DCA80U, 0x2631D7U, 0x6D223EU, 0x54BAA1U, 0x1E4950U, 0x47520BU, - 0x4CA79EU, 0x97BC75U, 0xBE3EA8U, 0xED479BU, 0xA4D446U, 0xBA4FF5U, 0xF13C39U, 0xE8A46AU, 0x83D7D7U, 0xDA4C0CU, - 0xD1DDF9U, 0x8AA7F2U, 0xC22427U, 0x793DDCU, 0x30CE45U, 0x2B5522U, 0x6007FBU, 0x39BE6CU, 0x32AD95U, 0x42560BU, - 0x4D426AU, 0x16D1B5U, 0x5F3A04U, 0x442BDBU, 0x2DF082U, 0xF6C225U, 0xFE59FCU, 0xA5880FU, 0xAEB312U, 0xF761C9U, - 0x9C582CU, 0x85CBB7U, 0xCE00C3U, 0xD43118U, 0x9DAB9DU, 0xEAF866U, 0xE3437BU, 0x381288U, 0x738955U, 0x6A3BF6U, - 0x2066ABU, 0x19D570U, 0x52DEC1U, 0x090E1EU, 0x00B5FFU, 0x5BE6E1U, 0x727D38U, 0x284CCFU, 0x639656U, 0xFA8531U, - 0xBD3CA8U, 0xD4EF77U, 0xCFC586U, 0x841489U, 0x9C0F78U, 0xD7BCA7U, 0x8E671EU, 0xA5774DU, 0xFE8481U, 0xF79F32U, - 0xAC0AEFU, 0x65F09CU, 0x5FF301U, 0x144ACAU, 0x0D193FU, 0x468224U, 0x13F0D1U, 0x18694AU, 0x63FA87U, 0x2B81F4U, - 0x30106DU, 0x790A9BU, 0xE2E952U, 0x8970CDU, 0xD003BCU, 0xDB9963U, 0x838AD2U, 0x88731DU, 0xD1E064U, 0xBAFFF3U, - 0xA10F2AU, 0xEC049DU, 0xBFD7D4U, 0xB7EE2BU, 0x4C7CBBU, 0x478760U, 0x1E9415U, 0x554D9EU, 0x4C7E6BU, 0x07E4B0U, - 0x3D35ADU, 0x741E4EU, 0x2F8D93U, 0x26FC20U, 0x7D667DU, 0x16B586U, 0x8B8E02U, 0xC91FD9U, 0xD0456CU, 0x9BF237U, - 0xC0EBCEU, 0xE92849U, 0xB29390U, 0xBBC3E7U, 0xE1787EU, 0xAA6B81U, 0x93B040U, 0xD8005FU, 0x411BAEU, 0x0AC870U, - 0x51F1D1U, 0x5D328EU, 0x362837U, 0x6799E0U, 0x6C4239U, 0x37711AU, 0x3EABC7U, 0x45BA3CU, 0x0D01A9U, 0x16D6F2U, - 0xDDCF17U, 0xC46D8CU, 0x8F3670U, 0xF6A723U, 0xFD5CBCU, 0xA74F5DU, 0xEAF582U, 0xF1A43BU, 0x903768U, 0x8B0CC5U, - 0xC0DC16U, 0x9957CBU, 0x1324F0U, 0x4ABD25U, 0x61AECEU, 0x38545AU, 0x73C701U, 0x68FEF4U, 0x212D6FU, 0x5B3382U, - 0x52C2D1U, 0x09494CU, 0x065ABFU, 0xDFA126U, 0x9CB149U, 0xA56A98U, 0xEE5927U, 0xF4C0F6U, 0xBD33B8U, 0xE62901U, - 0xCFB8D6U, 0x94D32FU, 0x9F40B8U, 0xC69AF1U, 0x8CAB0EU, 0x15309FU, 0x7E6360U, 0x21DA31U, 0x2848BAU, 0x733747U, - 0x72A6D4U, 0x08EDA8U, 0x435F7BU, 0x5A4CD6U, 0x119505U, 0x082658U, 0x433DE3U, 0xB8ED26U, 0xB0D6DDU, 0xEB05C8U, - 0xA2BC13U, 0xA9BEEAU, 0xD6656DU, 0xDF5614U, 0x848F82U, 0xC41C5BU, 0xDF26A4U, 0x94F7A5U, 0xADCC5AU, 0x665B8BU, - 0x3F1234U, 0x34A0EDU, 0x6E7BAAU, 0x076813U, 0x1CD1C4U, 0x55833DU, 0x4E1836U, 0x03A9E2U, 0x58F219U, 0x72418CU, - 0x2B09F7U, 0xA89A72U, 0xF1A1A9U, 0xBA7254U, 0x81EA47U, 0xC899BAU, 0xD20279U, 0x9B13C4U, 0xC0E09FU, 0xCB7E4BU, - 0xB25FF0U, 0xF98431U, 0xE4974EU, 0x2E6CD7U, 0x35FC00U, 0x5CE7A9U, 0x07147EU, 0x060D07U, 0x5D9F98U, 0x56E449U, - 0x0E65A6U, 0x659EB7U, 0x7C8D49U, 0x371790U, 0x6C6623U, 0xE5FD6EU, 0x9E6EBDU, 0x921600U, 0xC985D3U, 0x82DAEEU, - 0x9B7B25U, 0xD0E0F0U, 0xE1924BU, 0xAA091EU, 0xF158F5U, 0xF9E369U, 0x22F1BAU, 0x4B28C7U, 0x509B54U, 0x1B80BDU, - 0x024162U, 0x497B53U, 0x01A88CU, 0x3E1B5DU, 0x7502F2U, 0x6CD12BU, 0x27EB1CU, 0x7E7AC5U, 0xDDA113U, 0x8596BAU, - 0xCE5EEDU, 0xD54D14U, 0x9CF68BU, 0x87A54AU, 0xEE1C31U, 0xB58EA4U, 0xBFD55FU, 0xE66482U, 0xE93FA1U, 0x90AD7CU, - 0x5B04EFU, 0x405713U, 0x09CC48U, 0x13BFEDU, 0x522736U, 0x2914E3U, 0x22CFD8U, 0x7B5E05U, 0x3061E6U, 0x29B37FU, - 0x43BAA8U, 0x5849D1U, 0x91D25EU, 0xCEE0AFU, 0xC73971U, 0x9C2A40U, 0xB7919FU, 0xEF401EU, 0xA452E1U, 0xB5B9B8U, - 0xFEA80FU, 0x8533D6U, 0x8C4115U, 0xD7DA28U, 0x5F6BF3U, 0x043006U, 0x4FA39DU, 0x76DBD9U, 0x394C22U, 0x20C7BFU, - 0x6BB64CU, 0x312C41U, 0x187FB2U, 0x43C46FU, 0x0A55F4U, 0x192E81U, 0xD2BC4AU, 0xCBA5FBU, 0xA15624U, 0xF85DFDU, - 0xF38ECBU, 0xBA3602U, 0xA125F5U, 0xCEFE6CU, 0x97CF3BU, 0x9D55C2U, 0xC4A64DU, 0x4FBFBCU, 0x1468A3U, 0x7D4352U, - 0x6ED19DU, 0x270804U, 0x7D3B76U, 0x76A0ABU, 0x0FF018U, 0x0443D5U, 0x5D188EU, 0x16A93BU, 0x0932E0U, 0xC07015U, - 0xFACB1EU, 0xB39AC3U, 0xE80170U, 0xE3B3ADU, 0xBAEA5EU, 0xD17956U, 0xC042A9U, 0x8A9378U, 0x912DE7U, 0xD86E86U, - 0x83F559U, 0x2AC4E8U, 0x711F37U, 0x7A0D6EU, 0x26B4C9U, 0x6D6710U, 0x547CE7U, 0x1F8CFEU, 0x449720U, 0x4D3483U, - 0x16EF5AU, 0x1EFE2DU, 0x6D44B4U, 0xA6174BU, 0xBF8E8AU, 0xF4FD95U, 0xED6764U, 0x86D6BBU, 0xDC8912U, 0xD10A45U, - 0x8A799CU, 0x83E12AU, 0xF872F3U, 0xB10954U, 0xAA980DU, 0x6083D6U, 0x397163U, 0x3AE8B8U, 0x439BDDU, 0x481046U, - 0x1302BBU, 0x5AFB68U, 0x50E875U, 0x297396U, 0x26824AU, 0x7D98F1U, 0x344BA4U, 0xAF726FU, 0xE6F5DAU, 0x9C0F01U, - 0x971C38U, 0xCE85EFU, 0xC5F626U, 0x946D91U, 0xFFBDC8U, 0xE48637U, 0xAC15A6U, 0xB74C48U, 0x7EEE99U, 0x21B586U, - 0x0A0677U, 0x539FA8U, 0x18CC01U, 0x007652U, 0x4B67CFU, 0x70B43CU, 0x390FF1U, 0x625ECAU, 0x6BD01FU, 0x38E3C4U, - 0xB23870U, 0xCB893BU, 0x8093C6U, 0x994055U, 0xD679A8U, 0x8DAAFBU, 0xA4B176U, 0xFE018DU, 0xF7CA5CU, 0xACD963U, - 0xE762B2U, 0xFE323DU, 0x1589C4U, 0x0C5A92U, 0x4F432BU, 0x17F0ECU, 0x1CAA35U, 0x673B82U, 0x6E54DBU, 0x31C724U, - 0x785CA5U, 0x632C5AU, 0x29B70BU, 0x508490U, 0xDB5D6DU, 0x82CFEEU, 0x89B492U, 0xD22541U, 0xBB2EDCU, 0xA1DD27U, - 0xE04F62U, 0xFB56D9U, 0xB0A50CU, 0xF9BED7U, 0xC24EFAU, 0x8F5529U, 0x55C6D0U, 0x5E3B47U, 0x07383FU, 0x2CA2F0U, - 0x75D161U, 0x3E489EU, 0x25BB0FU, 0x6DA170U, 0x7630B1U, 0x174B2EU, 0x4CD8D7U, 0x470180U, 0x9E2339U, 0xD5B8FEU, - 0xE9EB27U, 0xA2521DU, 0xB941C8U, 0xF0BB23U, 0xAB2AB6U, 0xA271CDU, 0xD9C250U, 0xD3DC83U, 0x8A1D6EU, 0x41A67DU, - 0x58B580U, 0x3B6C5BU, 0x205ECEU, 0x6985A5U, 0x333471U, 0x3E27CAU, 0x65FD13U, 0x0CCE44U, 0x1747EDU, 0x5C143AU, - 0x45AF83U, 0x8F7F54U, 0xF6643DU, 0xFDD7A2U, 0xA68E73U, 0xAF3D8CU, 0xF4E79DU, 0xB5E073U, 0x8F59AAU, 0xC40A3DU, - 0x999044U, 0x922197U, 0xCB7A3AU, 0x60E9E1U, 0x3B90B4U, 0x73020FU, 0x6839DAU, 0x21FA71U, 0x3A632CU, 0x5151DFU, - 0x088A43U, 0x039B80U, 0x4260FDU, 0x18F36EU, 0x33EB97U, 0xEE1848U, 0xE503C9U, 0xBCA4B6U, 0xF7FC67U, 0xEC6FD8U, - 0x849C01U, 0x9F8506U, 0xD616FFU, 0x8D6C29U, 0x86FD90U, 0xFF26CFU, 0xF4150EU, 0x2C9EB1U, 0x6FEE60U, 0x74751BU, - 0x39E696U, 0x429F65U, 0x4B0DB8U, 0x1056ABU, 0x1AE756U, 0x43FC9DU, 0x282F29U, 0x318172U, 0x7A90E7U, 0xE36B1CU, - 0xA878D9U, 0xF2A0E2U, 0xDB133FU, 0x8008ECU, 0xC1D955U, 0xDAE292U, 0x9570EBU, 0xAC9B74U, 0xE68A85U, 0xBF514BU, - 0x34635AU, 0x6FFAA5U, 0x66A93CU, 0x1D12CBU, 0x54C382U, 0x4ED915U, 0x056AECU, 0x5C2D37U, 0x779402U, 0x2607C9U, - 0x2D5D1CU, 0x72ECA6U, 0xBAB7FBU, 0xA12408U, 0xC89C85U, 0xD3CF76U, 0x98542BU, 0xC177B8U, 0xCAAE45U, 0xB29CCEU, - 0xB9473BU, 0xE2D660U, 0xABEDF1U, 0xA03F1EU, 0x7926C4U, 0x1A95F1U, 0x044E2AU, 0x4D49FFU, 0x56B154U, 0x1FA209U, - 0x6419FAU, 0x6F4867U, 0x36D394U, 0x3C2199U, 0x653842U, 0x2EABB7U, 0x95C02CU, 0xDC525CU, 0x87CB93U, 0x8EB80AU, - 0xD423FDU, 0xF152A4U, 0xAAC003U, 0xE15BDAU, 0xF82A0DU, 0xB3B134U, 0xAAB3EBU, 0xC14C0AU, 0x1B5D95U, 0x128664U, - 0x49357AU, 0x002DA3U, 0x3BDE40U, 0x70C5DDU, 0x6954AEU, 0x23AE73U, 0x76ADE8U, 0x7D760DU, 0x064756U, 0x0FDCE3U, - 0xD40E38U, 0x9D37F5U, 0x87E4C6U, 0xECDF1AU, 0xB54EA9U, 0xBE1470U, 0xE7B71FU, 0xEC288EU, 0xB77951U, 0xDFC3A0U, - 0xC490BFU, 0x89095EU, 0x1ABA81U, 0x51E118U, 0x2853EFU, 0x234AB6U, 0x7B8910U, 0x703AC9U, 0x2B6216U, 0x62F127U, - 0x59CAECU, 0x101B59U, 0x4B2082U, 0xC1F2FFU, 0x88696CU, 0xB358A1U, 0xFA9752U, 0xAD844FU, 0xA63CB4U, 0xFFEF60U, - 0xF5F4EBU, 0x8C059EU, 0xC71F45U, 0xDCACF0U, 0x95772BU, 0x4E6622U, 0x67CDD5U, 0x3D9F0CU, 0x3406BBU, 0x6F75F2U, - 0x24EE0DU, 0x3D7E9CU, 0x520542U, 0x4396B3U, 0x09ADBCU, 0x527C45U, 0x5BF292U, 0xA0810BU, 0xE91878U, 0xF20BB5U, - 0xB9F10EU, 0xA1E0DBU, 0xEA33C0U, 0x938835U, 0x989BFEU, 0xC36342U, 0xCA6011U, 0x95FBECU, 0xFD0A6FU, 0x6E11B2U, - 0x25C3C1U, 0x3CFA5CU, 0x7769A7U, 0x0EB266U, 0x058079U, 0x5E1988U, 0x167E17U, 0x0DE5EFU, 0x44B428U, 0x7F0E31U, - 0x349DC6U, 0xEDC41FU, 0xE277A0U, 0xBA6DE1U, 0x99BE1EU, 0xC2178FU, 0x8B4450U, 0x90FF39U, 0xD9EFAAU, 0x823457U, - 0xA88785U, 0xF1DE98U, 0xFA4D73U, 0x3377E6U, 0x68A41DU, 0x43AD48U, 0x1A1AD3U, 0x14C836U, 0x4DF1EDU, 0x0622D0U, - 0x173903U, 0x7C88FEU, 0x27527DU, 0x2E41A5U, 0xF4FADAU, 0xFDBB4BU, 0x8601A4U, 0xCDD235U, 0xD4CB6AU, 0x9F7893U, - 0x862304U, 0xCCB3EDU, 0xB388BAU, 0xBA5B23U, 0xE1C0DCU, 0xE8A00DU, 0x3B3F27U, 0x500CF2U, 0x48D509U, 0x034694U, - 0x5A3CC7U, 0x51AD6AU, 0x0AB6B9U, 0x234544U, 0x785E57U, 0x30DE9AU, 0x2B2561U, 0x6036F4U, 0xDDCF8FU, 0x96DD5BU, - 0xCF46D0U, 0xCCB729U, 0x96A4FEU, 0xDF3FC7U, 0xE44D10U, 0xADC4F9U, 0xB61366U, 0xFD2837U, 0xA4B888U, 0x8EC359U, - 0x5750B6U, 0x5C49AFU, 0x07BA79U, 0x4A2080U, 0x517307U, 0x38DA7EU, 0x62C9ADU, 0x611230U, 0x38A2CBU, 0x33F98EU, - 0x4A4A35U, 0x0153E0U, 0x98815BU, 0xD23A06U, 0xD929C5U, 0x80E079U, 0xEBD7AAU, 0xF20D57U, 0xBD1C4CU, 0xE6A78DU, - 0xEF7472U, 0x954CE3U, 0x9CDF9CU, 0xCF8455U, 0x0437C2U, 0x1DFE3BU, 0x56EC6CU, 0x6F57D5U, 0x25061BU, 0x7E95AAU, - 0x772FF5U, 0x2C7C24U, 0x05C59BU, 0x5A965AU, 0x111D21U, 0x892DBCU, 0xC2F26FU, 0x9B6192U, 0xB81891U, 0xE38B6EU, - 0xEA91B6U, 0xB16221U, 0xF9FB48U, 0xC2C8DFU, 0x890226U, 0x9013F9U, 0xDBE848U, 0x02FB07U, 0x0D62D6U, 0x77906DU, - 0x3E8BB0U, 0x2538C3U, 0x6C614EU, 0x77F39CU, 0x141861U, 0x4D0D7AU, 0x47968FU, 0x1EE544U, 0x157DD1U, 0xCEEEAAU, - 0xA7953FU, 0xBC06D4U, 0xF57E09U, 0xABED3AU, 0xA2EEE3U, 0xD91734U, 0xD2849CU, 0x8BDEC3U, 0xC06F32U, 0xD174ADU, - 0x9BA77CU, 0x201C93U, 0x690C8AU, 0x22F77DU, 0x3BF4E4U, 0x702933U, 0x4B9B5AU, 0x0380C1U, 0x585134U, 0x556AEEU, - 0x0EF9CBU, 0x45A310U, 0x7C12CDU, 0xB7C97EU, 0xAFEA23U, 0xEC72C0U, 0xB7215DU, 0x9E9A8EU, 0xC50BF3U, 0xCC5068U, - 0x97E28DU, 0xDDB916U, 0xC42846U, 0xAF93B9U, 0xF2D020U, 0x796CC7U, 0x223F9EU, 0x2BA429U, 0x5095F0U, 0x18473FU, - 0x03DC8EU, 0x40EFD1U, 0x593620U, 0x1225BFU, 0x6BCF76U, 0x605E40U, 0xBA6599U, 0xF3B66AU, 0xE8AEF7U, 0x851DBCU, - 0x9EC649U, 0xD5D5D2U, 0x8C2C27U, 0x863E7CU, 0xDFB5D9U, 0xF4C002U, 0xA55BDFU, 0xEEE9ECU, 0x75B020U, 0x3C23D3U, - 0x06584AU, 0x4FCB15U, 0x1453A4U, 0x1F306BU, 0x42AB9AU, 0x09FA05U, 0x30415CU, 0x7A53ABU, 0x61AA22U, 0x2839D5U, - 0xF3228CU, 0xDAD032U, 0x89C9E3U, 0x820A2CU, 0xCAB91DU, 0x91A4C6U, 0x985673U, 0xE34DB8U, 0xA8DCE5U, 0xB52756U, - 0xFE358BU, 0xE6EE78U, 0x0DDF75U, 0x5654AFU, 0x5F075AU, 0x04BFC1U, 0x0D2CB4U, 0x56577FU, 0x34C6C2U, 0x2D9D11U, - 0x662F48U, 0x3FB4FFU, 0x34E536U, 0x4F4E89U, 0xC61C58U, 0x988107U, 0xD132A7U, 0xCA6978U, 0x81D881U, 0xB8C296U, - 0xF3114FU, 0xAA2AA8U, 0xA0FB31U, 0xF37142U, 0xDA429FU, 0x819B24U, 0x4888E1U, 0x5333FAU, 0x1AE30FU, 0x40D0D5U, - 0x6F0B68U, 0x36182BU, 0x3DA0F6U, 0x646345U, 0x2F7898U, 0x14CDF3U, 0x5C9666U, 0xC704BDU, 0x8E7F4CU, 0xDDEED3U, - 0xD655BAU, 0xAF062DU, 0xE49EF5U, 0xFDFD02U, 0xB7661BU, 0xA8F7F4U, 0xC18D25U, 0x9A1E9AU, 0x9305CBU, 0x48F414U, - 0x43EFB5U, 0x1B1D6AU, 0x708413U, 0x698780U, 0x2A7C4DU, 0x6168BFU, 0x78F3A2U, 0x130059U, 0x0B1BCCU, 0x40CA07U, - 0x1FF072U, 0x9663E9U, 0xCD9A14U, 0xE499C7U, 0xBF0AEAU, 0xF57239U, 0xECE1E4U, 0xA7BA5FU, 0xDE098FU, 0xD591E0U, - 0x86E271U, 0x8F79AEU, 0xD52817U, 0x1C8350U, 0x2711A9U, 0x684C3EU, 0x71FFE7U, 0x3AE490U, 0x633619U, 0x498FE6U, - 0x10DC37U, 0x1B670DU, 0x4066D8U, 0x09BC13U, 0x328FAEU, 0xFB16FDU, 0xA9C500U, 0xA2FF93U, 0xFB2C5EU, 0xF03565U, - 0x8D86B0U, 0xC65D4BU, 0xDD7DCEU, 0x95E615U, 0x8EB169U, 0xE708FAU, 0xBCDB03U, 0x37C1C4U, 0x6E72FDU, 0x25232AU, - 0x3DB8F3U, 0x5ECA4CU, 0x45430DU, 0x0CF0B2U, 0x57AB61U, 0x5E3ABCU, 0x210087U, 0x2BD343U, 0xF248B8U, 0xB9392DU, - 0xA0A376U, 0xEBB09FU, 0x905908U, 0x99CAF1U, 0xD3F5A6U, 0xCA251FU, 0x813ED0U, 0xF2CD01U, 0xFBD63EU, 0xA046EEU, - 0x29BD51U, 0x76AE98U, 0x3C274FU, 0x055476U, 0x4ECEA5U, 0x573F58U, 0x1C24DBU, 0x47B786U, 0x6ECC7DU, 0x345CE8U, - 0x7D0703U, 0x66B456U, 0xAF3DECU, 0xBC6F31U, 0xD7D0A2U, 0x8EC1CFU, 0x80321CU, 0xD9A9A1U, 0xD2FB7AU, 0xA9422BU, - 0xE05184U, 0xFB8A55U, 0xB22AAAU, 0xE831B3U, 0x63E264U, 0x1ADB8CU, 0x11081BU, 0x4832E2U, 0x0BA1BDU, 0x10781CU, - 0x784BC3U, 0x679052U, 0x2E902DU, 0x752BFCU, 0x7EFC57U, 0x27C58AU, 0xCC57D9U, 0xD40C64U, 0x9FBFB6U, 0x84665BU, - 0xCD7540U, 0xB6CF95U, 0xBF8E6EU, 0xE415FBU, 0xE62690U, 0xBFFE0DU, 0xF04DFEU, 0xC91623U, 0x028520U, 0x19BCD9U, - 0x506E06U, 0x0AEDB6U, 0x23D4E9U, 0x780728U, 0x331997U, 0x3AE84EU, 0x6173B9U, 0x6840A0U, 0x129B67U, 0x598B9EU, - 0xC87009U, 0x877370U, 0x9EEAEBU, 0xF5190EU, 0xAC03D4U, 0xA690C1U, 0xFDE93AU, 0xB47AF7U, 0xAF8044U, 0xC69119U, - 0xDD0ACAU, 0x166977U, 0x4EF0BCU, 0x45E2C9U, 0x3C1D52U, 0x3F8E87U, 0x64D73CU, 0x296574U, 0x327E83U, 0x7A8F1AU, - 0x0114EDU, 0x0A1734U, 0x53EF3BU, 0xD8FCCAU, 0x812715U, 0xEA94A4U, 0xF185EBU, 0xB95F3AU, 0xA26C85U, 0xEBB55CU, - 0xB0862AU, 0x930CA3U, 0xCEDD70U, 0x85E6CDU, 0x9D7196U, 0x562A63U, 0x6D9AE8U, 0x24411DU, 0x7F5246U, 0x76EBDBU, - 0x2DB928U, 0x2712E5U, 0x5E83D7U, 0x15D80AU, 0x0C6BD1U, 0x473170U, 0x54A02FU, 0xB99B9EU, 0xE34841U, 0xEAD090U, - 0xB1E33FU, 0xFA2866U, 0xE31991U, 0x88C208U, 0x8154FFU, 0xDB6FB7U, 0x92BE28U, 0x89A5D9U, 0xE25606U, 0x7BCE37U, - 0x30FDFCU, 0x693E21U, 0x6F2792U, 0x3495CFU, 0x5DCE6CU, 0x465DB1U, 0x0FA46AU, 0x14B75FU, 0x5F2D85U, 0x275C60U, - 0x2CC7FBU, 0xF56486U, 0xFE3C55U, 0xA5ABC8U, 0xECD02BU, 0xD743F2U, 0x9FDAC5U, 0xC0A81CU, 0xC33383U, 0x9A2262U, - 0xB1D93DU, 0xE8DA8DU, 0x232252U, 0x39B19BU, 0x70AAACU, 0x6B5975U, 0x024182U, 0x59921BU, 0x522974U, 0x0B38A5U, - 0x01F33EU, 0x78C1CBU, 0x3758D0U, 0x242F3DU, 0xEDB4EFU, 0xB66672U, 0xBF5701U, 0xC5CCDCU, 0xCE9F77U, 0x9726A2U, - 0xDCA4F9U, 0xC5FF4CU, 0xAE4E87U, 0xB51576U, 0xFDA7E9U, 0xA63C90U, 0x2F6D47U, 0x74D6CFU, 0x1BC538U, 0x0A1D21U, - 0x413EDEU, 0x58E50FU, 0x127480U, 0x6B4BF1U, 0x60992EU, 0x2BA297U, 0x327340U, 0x79E809U, 0xA0DABAU, 0x8A0367U, - 0xD1009DU, 0x98BB98U, 0x836A63U, 0xCE70F6U, 0xF5832DU, 0xB69850U, 0xEE29D3U, 0xE5732EU, 0xBCE0FDU, 0xB75962U, - 0x4C1A13U, 0x0589DCU, 0x1EF165U, 0x5666B7U, 0x4DFDEAU, 0x268E59U, 0x7F1794U, 0x74256FU, 0x29FE7AU, 0x626F81U, - 0x700404U, 0x1996DFU, 0x828FA2U, 0xCB7C31U, 0x9067CCU, 0x9B940EU, 0xE20C17U, 0xE81FE8U, 0xB1E439U, 0xFAF586U, - 0xE17FC7U, 0xA88C18U, 0xD397A1U, 0x5E4276U, 0x04794FU, 0x0FEB88U, 0x5E9271U, 0x3501E6U, 0x2C9A3EU, 0x67EA51U, - 0x7C61C0U, 0x34323BU, 0x6F89EEU, 0x4618F5U, 0x1D4218U, 0xD4F1CBU, 0xCFE876U, 0x841B25U, 0xB888F8U, 0xF3D053U, - 0xAA7386U, 0xA168BCU, 0xF2BB69U, 0xFB8792U, 0x80541FU, 0xC8CF4CU, 0xC3FEB5U, 0x182522U, 0x1117CBU, 0x6A9E9CU, - 0x234D05U, 0x3876FAU, 0x72A42BU, 0x2FBD84U, 0x240ED4U, 0x5DD54BU, 0x56C4B2U, 0x057E65U, 0x4C2D4CU, 0xD7849BU, - 0xBFD762U, 0xA44DF9U, 0xEFFEACU, 0xB6A347U, 0xBD30D2U, 0xC40B29U, 0x8FDB74U, 0x9540E6U, 0xDC330BU, 0xC3BAD8U, - 0x8A89E5U, 0x71533EU, 0x7AC0BBU, 0x2BB140U, 0x212A11U, 0x7838AEU, 0x13C17FU, 0x08D290U, 0x414989U, 0x1AA85EU, - 0x13B2A6U, 0x494131U, 0x625AD8U, 0xBBCF87U, 0xF43516U, 0xED26E9U, 0xA6BF78U, 0x9FCC17U, 0xDD57CEU, 0x86B75DU, - 0x8FACA0U, 0xD43FE3U, 0x9D445EU, 0xA6D584U, 0x6DCF71U, 0x753C6AU, 0x3EA5AFU, 0x67F654U, 0x4C4CC9U, 0x134DBAU, - 0x1AB667U, 0x4125E4U, 0x097E19U, 0x12CA0AU, 0x71D1F3U, 0x78022CU, 0xA33BACU, 0xEAA953U, 0xF17A02U, 0x9B53BDU, - 0xC28074U, 0xC9BB83U, 0x90299AU, 0x9BF04DU, 0xC4C3B4U, 0xAD583BU, 0xB7084AU, 0xFEB3D1U, 0x656004U, 0x2E69FEU, - 0x5FDAF3U, 0x548000U, 0x0D37DDU, 0x472E4EU, 0x5CFD33U, 0x1546F8U, 0x2E164DU, 0x678D96U, 0x3CBEE3U, 0x337768U, - 0xEBE5BDU, 0xC09E47U, 0x990D5EU, 0xD234A9U, 0xC9E720U, 0x887DF7U, 0xD34C0EU, 0xFB9711U, 0xA084E0U, 0xA96C2FU, - 0xF27FBEU, 0xB9E4C1U, 0x001318U, 0x4B02AFU, 0x56B867U, 0x1CEB30U, 0x477289U, 0x4E8152U, 0x358AF7U, 0x3C1AACU, - 0x676159U, 0x24F2C2U, 0x3C6917U, 0x57197CU, 0x8E82E1U, 0x85F112U, 0xDE68CFU, 0xD77BDDU, 0x8C9130U, 0xE400EBU, - 0xFB5B5EU, 0xB0E885U, 0xA9F6D4U, 0xE2277BU, 0x9B9CA2U, 0x108F15U, 0x5A764CU, 0x0B64ABU, 0x00AF32U, 0x599CEDU, - 0x72059DU, 0x29D702U, 0x60ECE3U, 0x7A7D3CU, 0x330625U, 0x0C95D6U, 0x474D0BU, 0x9E7EA8U, 0x95FDF5U, 0xCCA666U, - 0x86179BU, 0xBD8D40U, 0xFCDA65U, 0xE763BFU, 0xAE304AU, 0xF58AD1U, 0xDE9B9CU, 0x86406FU, 0x8DE3F2U, 0x54B801U, - 0x1B28D8U, 0x0213D7U, 0x69C026U, 0x7259B9U, 0x3A6B48U, 0x61B017U, 0x68819FU, 0x135A68U, 0x50D9B1U, 0x49E386U, - 0x02325FU, 0x9A29B0U, 0xD19E23U, 0xAAC77EU, 0xA3558DU, 0xFCAE04U, 0xF5BFF3U, 0xAE04AAU, 0xC44635U, 0xDDDDC5U, - 0x966C4AU, 0xCF373BU, 0xC4A4E4U, 0x1FD47DU, 0x3E4F8AU, 0x64DC43U, 0x2DA574U, 0x3637ADU, 0x7D5C56U, 0x44CFC3U, - 0x0BD688U, 0x52257DU, 0x59BBE7U, 0x03AA1AU, 0x4A5119U, 0xF142C4U, 0xB89A37U, 0xB329AAU, 0xE822D1U, 0xA9D114U, - 0x93C88FU, 0xDA5A7AU, 0xC1A121U, 0x8AB090U, 0xD36B5EU, 0xDC58A7U, 0xA5C0B0U, 0x2F8369U, 0x74389EU, 0x3DAB17U, - 0x26D368U, 0x4F40F9U, 0x141F26U, 0x1DAEC7U, 0x473558U, 0x446721U, 0x1DDEF6U, 0x769D6EU, 0xEF0E8DU, 0xA434D0U, - 0xBFE56BU, 0xF35EBEU, 0x884D45U, 0x819440U, 0xDAA69BU, 0x917D26U, 0x88ECF5U, 0xC3C788U, 0xFB150BU, 0xB02ED6U, - 0x63BF24U, 0x6A6439U, 0x3153D2U, 0x188B03U, 0x43989CU, 0x0923EDU, 0x147232U, 0x5FF99BU, 0x060B4CU, 0x2D10B5U, - 0x76A1A2U, 0x7FFA7BU, 0xA568D4U, 0xECD104U, 0xD7827BU, 0x9C19EAU, 0x8D6831U, 0xC6E2DCU, 0x9F71CFU, 0x950A32U, - 0xEE9BE1U, 0xA3A16CU, 0xB8761FU, 0xF16FC2U, 0x6A9C79U, 0x010FACU, 0x491786U, 0x52F453U, 0x1BEF88U, 0x007C35U, - 0x4B8566U, 0x32978FU, 0x316C18U, 0x697DC1U, 0x62E6BEU, 0x3B142FU, 0xD40DC0U, 0xCFCE11U, 0x86F58EU, 0xDD66F6U, - 0xD53E31U, 0x8E8988U, 0xA5125FU, 0xFC6366U, 0xB7F9B9U, 0xAEAA78U, 0xE513C3U, 0xD69096U, 0x1ECB6DU, 0x4579F8U, - 0x4C6033U, 0x13B34EU, 0x5888DCU, 0x615821U, 0x2AE3F2U, 0x32F0FFU, 0x792B04U, 0x220A91U, 0x0B906AU, 0xD0432BU, - 0xD97294U, 0x82AD4DU, 0xC8BE9AU, 0xD90623U, 0xB2D564U, 0xEBEE9CU, 0xE02D03U, 0xBF35D2U, 0xB686ADU, 0xCCDD2CU, - 0x854CD3U, 0x1EF70AU, 0x55A51DU, 0x4C1CE4U, 0x074F67U, 0x7ED49AU, 0x7476C9U, 0x2F2F75U, 0x26BCBEU, 0x75876BU, - 0x1C5650U, 0x07C885U, 0x48BB7EU, 0x9022F3U, 0x9B11A0U, 0xC2CA5DU, 0xE9C8CEU, 0xA07133U, 0xFBA238U, 0xF0B9E9U, - 0xA84917U, 0x835286U, 0xDAC179U, 0x913830U, 0x822B87U, 0x4BD95EU, 0x30D289U, 0x3C43A0U, 0x67B87FU, 0x6CAA8EU, - 0x353311U, 0x7E4440U, 0x47DFABU, 0x0C8E3FU, 0x1634C4U, 0x5FA7D9U, 0x04CC0AU, 0xAD5DE7U, 0xF64774U, 0xBDB409U, - 0xAC2DD2U, 0xE67E67U, 0xFBC5ACU, 0x90D5F9U, 0xCB0E42U, 0xC23D9FU, 0x99B67DU, 0x9047E4U, 0xEA5DB3U, 0x218E0AU, - 0x38B7D5U, 0x732034U, 0x6AFA2BU, 0x21CBFAU, 0x5A1005U, 0x5B039CU, 0x01A8FBU, 0x4C7822U, 0x574395U, 0x3CD04DU, - 0xA5811AU, 0xEE3BB3U, 0xB76868U, 0xBDF19DU, 0xE64286U, 0xCF1943U, 0x949BF8U, 0xDDA225U, 0xC67156U, 0x8FCACBU, - 0xF59B08U, 0xF605F5U, 0x2B36EFU, 0x20EF1AU, 0x797CC1U, 0x324664U, 0x1985BFU, 0x419CE4U, 0x4A6F51U, 0x13748AU, - 0x58C42FU, 0x631F74U, 0x2A0CA1U, 0x71F51AU, 0xF9E7D7U, 0xA27CA5U, 0xA99F38U, 0xD886EBU, 0x973516U, 0x8E6F1DU, - 0xC5FEECU, 0xDF0133U, 0xB61282U, 0xED8ADDU, 0xE4F954U, 0xBF7AA3U, 0x74617AU, 0x6D904DU, 0x070A95U, 0x1E795AU, - 0x55E0EBU, 0x0EF334U, 0x0F0845U, 0x7098CAU, 0x798313U, 0x2360E0U, 0x687BFDU, 0x71AB0EU, 0xBA10C3U, 0x830370U, - 0xC8FA2DU, 0x93EDB7U, 0x9B3742U, 0xC00689U, 0xA99DBCU, 0xB25E67U, 0xF964BAU, 0xE0F509U, 0xA7AE44U, 0xFF1DB7U, - 0x54C42EU, 0x0DF6F1U, 0x066D90U, 0x5D3C0EU, 0x1487FFU, 0x2F8460U, 0x675E19U, 0x3CEFDEU, 0x37B447U, 0x6E27B0U, - 0x651369U, 0x9CC856U, 0xD77B97U, 0xC9604CU, 0x88B1F9U, 0x939BA2U, 0xFA4856U, 0xB1D1DDU, 0xAAE200U, 0xE33873U, - 0xB829EEU, 0xB0D20DU, 0xCBC190U, 0x407AEBU, 0x19AA3EU, 0x52A1A5U, 0x4B1240U, 0x204B1BU, 0x3ED9A2U, 0x7F2274U, - 0x2437ADU, 0x2DAC8AU, 0x76DF53U, 0x5D45ACU, 0x04F43DU, 0xCEBFE2U, 0xD72CC3U, 0x9C551CU, 0xE7C7E5U, 0xEEDC72U, - 0xB52D1BU, 0xBCB6CCU, 0xE6A454U, 0xA95FA7U, 0x904EFAU, 0xD3A551U, 0xCA3684U, 0x01265FU, 0x5ADD6AU, 0x72CEB1U, - 0x29135CU, 0x60A1CFU, 0x7BBA92U, 0x304921U, 0x2950FCU, 0x42D316U, 0x1AA903U, 0x1138F8U, 0x48E329U, 0xC7D0A6U, - 0xBC48DFU, 0xFD1B08U, 0xE6A0B1U, 0xAE3366U, 0xF55AAFU, 0xFEC898U, 0x879341U, 0x8C22FEU, 0xD5392EU, 0x9EEA61U, - 0x8456D0U, 0x6D450BU, 0x769EF6U, 0x3FADE5U, 0x606508U, 0x6BD6DBU, 0x3ACD46U, 0x101C3DU, 0x5927F8U, 0x02F543U, - 0x096C96U, 0x505FCCU, 0xBB8C71U, 0xA296B2U, 0xE8370FU, 0xF36C5CU, 0xBADF85U, 0xE1063AU, 0xC814FBU, 0x97AF04U, - 0x9CFA15U, 0xC461EAU, 0x87D23BU, 0xBE88B4U, 0x7509CCU, 0x2E721BU, 0x27E1A2U, 0x7C5965U, 0x750A7CU, 0x0F9183U, - 0x44A052U, 0x5D7BE9U, 0x1669ACU, 0x0F9277U, 0x6013CAU, 0x3B0819U, 0xB3FA65U, 0xE0E3E6U, 0xA9103BU, 0xB28BC0U, - 0xDB9ED5U, 0xC0642EU, 0x8B77EBU, 0xD3EC50U, 0xD80D89U, 0xA1179EU, 0xAAC477U, 0xF1F5A0U, 0x386E19U, 0x271D4FU, - 0x6F8596U, 0x541639U, 0x1F6DE8U, 0x4EFE97U, 0x45B706U, 0x1C05D9U, 0x779E30U, 0x6DCF27U, 0x2474DEU, 0x3F664DU, - 0xF69BB0U, 0xAD08FBU, 0x86536FU, 0xDFE094U, 0xD1E841U, 0x883B6AU, 0xC300B7U, 0xE8D164U, 0xB16BD9U, 0xF2788AU, - 0xEBA167U, 0xA192FCU, 0x3A0929U, 0x53DBD2U, 0x08F2C3U, 0x01212DU, 0x5A3ABCU, 0x518B43U, 0x29D11AU, 0x62628DU, - 0x7FFD64U, 0x34ACB3U, 0x6F1E8AU, 0xE64555U, 0x95C494U, 0x9D7F2BU, 0xC62C7AU, 0x8DB485U, 0x94871DU, 0xFF5CDEU, - 0xE6EFE3U, 0xADB730U, 0xF524CFU, 0xFE0F56U, 0xA5DE31U, 0x48C5E8U, 0x53377FU, 0x1AAE86U, 0x01BD59U, 0x4B4678U, - 0x3A50A7U, 0x31E977U, 0x683ACCU, 0x633189U, 0x38C072U, 0x71DAEFU, 0x4B493CU, 0x82B001U, 0x99A3C2U, 0xD2383FU, - 0x8F4AA4U, 0xA4D3D1U, 0xFDA00AU, 0xB62B8FU, 0xACBB75U, 0xE5C028U, 0xF6539BU, 0x9F4242U, 0xC4B985U, 0x4F2FBCU, - 0x167463U, 0x1CC5D2U, 0x65DE1DU, 0x2E3C4CU, 0x35A5F3U, 0x78F622U, 0x234DDDU, 0x0A5C55U, 0x408622U, 0x5BB5FBU, - 0x122E6CU, 0xC1FF95U, 0xC8C4DEU, 0xB3066BU, 0xB83FB0U, 0xE0AC25U, 0xAB775EU, 0xB24793U, 0xD9DC20U, 0x828BFDU, - 0x8F30AFU, 0xD46102U, 0xDCDBD9U, 0x07582CU, 0x6E0137U, 0x75B2C6U, 0x3EE809U, 0x2F7990U, 0x64C2E7U, 0x1C913EU, - 0x170A89U, 0x4C3A40U, 0x45E9D6U, 0x1E42AFU, 0x571370U, 0xE889C1U, 0xA2BA0EU, 0xFB635FU, 0xF070E0U, 0xA9CF39U, - 0x821DDAU, 0xD904C7U, 0x90F734U, 0x82FCE9U, 0xCB4D72U, 0xD09716U, 0x3B848DU, 0x623D78U, 0x696EA3U, 0x30F4BEU, - 0x7A075DU, 0x451E80U, 0x0C8D33U, 0x17E66EU, 0x5E76B5U, 0x050D14U, 0x0E9ECBU, 0x7607BAU, 0xF57524U, 0xACEAC5U, - 0xE7F91AU, 0xFC0083U, 0x9583F4U, 0xCED96DU, 0xC6688AU, 0x9D7353U, 0x92804CU, 0xCB11BDU, 0xA00B62U, 0xA9F8C3U, - 0x72E398U, 0x783244U, 0x2118F7U, 0x4A8B2AU, 0x5B5249U, 0x1061D4U, 0x09FA2FU, 0x428ABAU, 0x1911F1U, 0x31C604U, - 0x6AFD9FU, 0x276D62U, 0xBC2631U, 0xF795B8U, 0xCE4C4EU, 0x855F97U, 0xDDE520U, 0xD6B479U, 0x8D0FB6U, 0x8C1C07U, - 0xF7C6D8U, 0xBE77A9U, 0xA53C36U, 0xEFAFDFU, 0x369648U, 0x1D4411U, 0x40DFE6U, 0x4BEE7EU, 0x103595U, 0x5902C0U, - 0x43D85BU, 0x2AC9AEU, 0x316265U, 0x7AB158U, 0x23A18BU, 0x201A56U, 0xD949E5U, 0x93F2A8U, 0x882313U, 0xC139C6U, - 0xDA8A3CU, 0x97D329U, 0xEC50E2U, 0xE7AA13U, 0xBFBB8CU, 0xB42075U, 0xED5322U, 0x06C8ABU, 0x1DF85CU, 0x542785U, - 0x0FB4BAU, 0x0FCD7BU, 0x544FA4U, 0x7F5414U, 0x26A54BU, 0x6D3EF2U, 0x702D31U, 0x3BD7CCU, 0x13C6DFU, 0xC83D02U, - 0x83AEF9U, 0x9AB77CU, 0xD15507U, 0xC84ED2U, 0xA3DF49U, 0xF9A4BDU, 0xF836F6U, 0xA3ED4BU, 0xEADC98U, 0xD14B05U, - 0x9A30E6U, 0x03A0BFU, 0x4D6B00U, 0x1458D1U, 0x1FC12EU, 0x64932FU, 0x6D28F0U, 0x36BB09U, 0x7FE29FU, 0x6551E6U, - 0x0E0B21U, 0x57AAB8U, 0x54B147U, 0x8D6216U, 0x86DBA9U, 0xDDC968U, 0xB412F3U, 0xAA218EU, 0xE3FC5DU, 0xF86EF0U, - 0xB35523U, 0xCA945FU, 0xC1AFCCU, 0x983C11U, 0xD264FAU, 0x49D7EFU, 0x000C14U, 0x3B1FC1U, 0x7AA75AU, 0x21F4B7U, - 0x2A6FA4U, 0x728E5DU, 0x5D958AU, 0x042713U, 0x4F767DU, 0x54EDACU, 0x1D5E13U, 0x8604C0U, 0xEE91ADU, 0xB5EA36U, - 0xBC79E3U, 0xE77018U, 0xAC820DU, 0x9D19E6U, 0xD6283FU, 0xCEF3A8U, 0x85E0D1U, 0xDA1A47U, 0x538BAEU, 0x389079U, - 0x216360U, 0x6A6B9FU, 0x30D84EU, 0x3903E1U, 0x421230U, 0x0BE94FU, 0x10FBD6U, 0x5B6011U, 0x4215E8U, 0x008EFBU, - 0xF95C07U, 0xF2759CU, 0xADE659U, 0xA49D22U, 0xFF0CB7U, 0x96964CU, 0x8CE591U, 0xC77E92U, 0x9E2F6FU, 0x959CBCU, - 0xCC0601U, 0xE7475AU, 0x3CFCBFU, 0x74EF25U, 0x6717F4U, 0x2E048BU, 0x15DF0AU, 0x5A6CF5U, 0x03716CU, 0x08A33BU, - 0x5098C2U, 0x5B1945U, 0x20C2BCU, 0x69F063U, 0xF22972U, 0xBB1A8DU, 0xE0814DU, 0xCA52F6U, 0x936AABU, 0x98B958U, - 0xC9A2C5U, 0x820306U, 0x9B593BU, 0xF4CAE0U, 0xEE7315U, 0xA7209EU, 0x7C9BCBU, 0x75C930U, 0x0E54A4U, 0x45E75FU, - 0x5CBC12U, 0x173D81U, 0x0F0778U, 0x44D4AFU, 0x3FC596U, 0x363E59U, 0x65ACE8U, 0x6C9737U, 0xA346E6U, 0xD95DD9U, - 0xD0FE10U, 0x8B26E6U, 0xC2357FU, 0xD9CE28U, 0x92DDC1U, 0xAB455EU, 0xE1B6AFU, 0xB8ADF4U, 0xB35861U, 0x68438AU, - 0x41C157U, 0x12B864U, 0x5B2BB9U, 0x45B00AU, 0x0EC3C6U, 0x175B95U, 0x7C2828U, 0x25B3F3U, 0x2E2206U, 0x75580DU, - 0x3DDBD8U, 0x86C223U, 0xCF31BAU, 0xD4AADDU, 0x9FF804U, 0xC64193U, 0xCD526AU, 0xBDA9F4U, 0xB2BD95U, 0xE92E4AU, - 0xA0C5FBU, 0xBBD424U, 0xD20F7DU, 0x093DDAU, 0x01A603U, 0x5A77F0U, 0x514CEDU, 0x089E36U, 0x63A7D3U, 0x7A3448U, - 0x31FF3CU, 0x2BCEE7U, 0x625462U, 0x150799U, 0x1CBC84U, 0xC7ED77U, 0x8C76AAU, 0x95C409U, 0xDF9954U, 0xE62A8FU, - 0xAD213EU, 0xF6F1E1U, 0xFF4A00U, 0xA4191EU, 0x8D82C7U, 0xD7B330U, 0x9C69A9U, 0x057ACEU, 0x42C357U, 0x2B1088U, - 0x303A79U, 0x7BEB76U, 0x63F087U, 0x284358U, 0x7198E1U, 0x5A88B2U, 0x017B7EU, 0x0860CDU, 0x53F510U, 0x9A0F63U, - 0xA00CFEU, 0xEBB535U, 0xF2E6C0U, 0xB97DDBU, 0xEC0F2EU, 0xE796B5U, 0x9C0578U, 0xD47E0BU, 0xCFEF92U, 0x86F564U, - 0x1D16ADU, 0x768F32U, 0x2FFC43U, 0x24669CU, 0x7C752DU, 0x778CE2U, 0x2E1F9BU, 0x45000CU, 0x5EF0D5U, 0x13FB62U, - 0x40282BU, 0x4811D4U, 0xB38344U, 0xB8789FU, 0xE16BEAU, 0xAAB261U, 0xB38194U, 0xF81B4FU, 0xC2CA52U, 0x8BE1B1U, - 0xD0726CU, 0xD903DFU, 0x829982U, 0xE94A79U, 0x7471FDU, 0x36E026U, 0x2FBA93U, 0x640DC8U, 0x3F1431U, 0x16D7B6U, - 0x4D6C6FU, 0x443C18U, 0x1E8781U, 0x55947EU, 0x6C4FBFU, 0x27FFA0U, 0xBEE451U, 0xF5378FU, 0xAE0E2EU, 0xA2CD71U, - 0xC9D7C8U, 0x98661FU, 0x93BDC6U, 0xC88EE5U, 0xC15438U, 0xBA45C3U, 0xF2FE56U, 0xE9290DU, 0x2230E8U, 0x3B9273U, - 0x70C98FU, 0x0958DCU, 0x02A343U, 0x58B0A2U, 0x150A7DU, 0x0E5BC4U, 0x6FC897U, 0x74F33AU, 0x3F23E9U, 0x66A834U, - 0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U, - 0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U + 0x42CC47U, 0x19D6FEU, 0x304729U, 0x6B2CD0U, 0x60BF47U, 0x39650EU, 0x7354F1U, 0xEACF60U, 0x819C9FU, 0xDE25CEU, + 0xD7B745U, 0x8CC8B8U, 0x8D592BU, 0xF71257U, 0xBCA084U, 0xA5B329U, 0xEE6AFAU, 0xF7D9A7U, 0xBCC21CU, 0x4712D9U, + 0x4F2922U, 0x14FA37U, 0x5D43ECU, 0x564115U, 0x299A92U, 0x20A9EBU, 0x7B707DU, 0x3BE3A4U, 0x20D95BU, 0x6B085AU, + 0x5233A5U, 0x99A474U, 0xC0EDCBU, 0xCB5F12U, 0x918455U, 0xF897ECU, 0xE32E3BU, 0xAA7CC2U, 0xB1E7C9U, 0xFC561DU, + 0xA70DE6U, 0x8DBE73U, 0xD4F608U, 0x57658DU, 0x0E5E56U, 0x458DABU, 0x7E15B8U, 0x376645U, 0x2DFD86U, 0x64EC3BU, + 0x3F1F60U, 0x3481B4U, 0x4DA00FU, 0x067BCEU, 0x1B68B1U, 0xD19328U, 0xCA03FFU, 0xA31856U, 0xF8EB81U, 0xF9F2F8U, + 0xA26067U, 0xA91BB6U, 0xF19A59U, 0x9A6148U, 0x8372B6U, 0xC8E86FU, 0x9399DCU, 0x1A0291U, 0x619142U, 0x6DE9FFU, + 0x367A2CU, 0x7D2511U, 0x6484DAU, 0x2F1F0FU, 0x1E6DB4U, 0x55F6E1U, 0x0EA70AU, 0x061C96U, 0xDD0E45U, 0xB4D738U, + 0xAF64ABU, 0xE47F42U, 0xFDBE9DU, 0xB684ACU, 0xFE5773U, 0xC1E4A2U, 0x8AFD0DU, 0x932ED4U, 0xD814E3U, 0x81853AU, + 0x225EECU, 0x7A6945U, 0x31A112U, 0x2AB2EBU, 0x630974U, 0x785AB5U, 0x11E3CEU, 0x4A715BU, 0x402AA0U, 0x199B7DU, + 0x16C05EU, 0x6F5283U, 0xA4FB10U, 0xBFA8ECU, 0xF633B7U, 0xEC4012U, 0xADD8C9U, 0xD6EB1CU, 0xDD3027U, 0x84A1FAU, + 0xCF9E19U, 0xD64C80U, 0xBC4557U, 0xA7B62EU, 0x6E2DA1U, 0x311F50U, 0x38C68EU, 0x63D5BFU, 0x486E60U, 0x10BFE1U, + 0x5BAD1EU, 0x4A4647U, 0x0157F0U, 0x7ACC29U, 0x73BEEAU, 0x2825D7U, 0xA0940CU, 0xFBCFF9U, 0xB05C62U, 0x892426U, + 0xC6B3DDU, 0xDF3840U, 0x9449B3U, 0xCED3BEU, 0xE7804DU, 0xBC3B90U, 0xF5AA0BU, 0xE6D17EU, 0x2D43B5U, 0x345A04U, + 0x5EA9DBU, 0x07A202U, 0x0C7134U, 0x45C9FDU, 0x5EDA0AU, 0x310193U, 0x6830C4U, 0x62AA3DU, 0x3B59B2U, 0xB04043U, + 0xEB975CU, 0x82BCADU, 0x912E62U, 0xD8F7FBU, 0x82C489U, 0x895F54U, 0xF00FE7U, 0xFBBC2AU, 0xA2E771U, 0xE956C4U, + 0xF6CD1FU, 0x3F8FEAU, 0x0534E1U, 0x4C653CU, 0x17FE8FU, 0x1C4C52U, 0x4515A1U, 0x2E86A9U, 0x3FBD56U, 0x756C87U, + 0x6ED218U, 0x279179U, 0x7C0AA6U, 0xD53B17U, 0x8EE0C8U, 0x85F291U, 0xD94B36U, 0x9298EFU, 0xAB8318U, 0xE07301U, + 0xBB68DFU, 0xB2CB7CU, 0xE910A5U, 0xE101D2U, 0x92BB4BU, 0x59E8B4U, 0x407175U, 0x0B026AU, 0x12989BU, 0x792944U, + 0x2376EDU, 0x2EF5BAU, 0x758663U, 0x7C1ED5U, 0x078D0CU, 0x4EF6ABU, 0x5567F2U, 0x9F7C29U, 0xC68E9CU, 0xC51747U, + 0xBC6422U, 0xB7EFB9U, 0xECFD44U, 0xA50497U, 0xAF178AU, 0xD68C69U, 0xD97DB5U, 0x82670EU, 0xCBB45BU, 0x508D90U, + 0x190A25U, 0x63F0FEU, 0x68E3C7U, 0x317A10U, 0x3A09D9U, 0x6B926EU, 0x004237U, 0x1B79C8U, 0x53EA59U, 0x48B3B7U, + 0x811166U, 0xDE4A79U, 0xF5F988U, 0xAC6057U, 0xE733FEU, 0xFF89ADU, 0xB49830U, 0x8F4BC3U, 0xC6F00EU, 0x9DA135U, + 0x942FE0U, 0xC71C3BU, 0x4DC78FU, 0x3476C4U, 0x7F6C39U, 0x66BFAAU, 0x298657U, 0x725504U, 0x5B4E89U, 0x01FE72U, + 0x0835A3U, 0x53269CU, 0x189D4DU, 0x01CDC2U, 0xEA763BU, 0xF3A56DU, 0xB0BCD4U, 0xE80F13U, 0xE355CAU, 0x98C47DU, + 0x91AB24U, 0xCE38DBU, 0x87A35AU, 0x9CD3A5U, 0xD648F4U, 0xAF7B6FU, 0x24A292U, 0x7D3011U, 0x764B6DU, 0x2DDABEU, + 0x44D123U, 0x5E22D8U, 0x1FB09DU, 0x04A926U, 0x4F5AF3U, 0x064128U, 0x3DB105U, 0x70AAD6U, 0xAA392FU, 0xA1C4B8U, + 0xF8C7C0U, 0xD35D0FU, 0x8A2E9EU, 0xC1B761U, 0xDA44F0U, 0x925E8FU, 0x89CF4EU, 0xE8B4D1U, 0xB32728U, 0xB8FE7FU, + 0x61DCC6U, 0x2A4701U, 0x1614D8U, 0x5DADE2U, 0x46BE37U, 0x0F44DCU, 0x54D549U, 0x5D8E32U, 0x263DAFU, 0x2C237CU, + 0x75E291U, 0xBE5982U, 0xA74A7FU, 0xC493A4U, 0xDFA131U, 0x967A5AU, 0xCCCB8EU, 0xC1D835U, 0x9A02ECU, 0xF331BBU, + 0xE8B812U, 0xA3EBC5U, 0xBA507CU, 0x7080ABU, 0x099BC2U, 0x02285DU, 0x59718CU, 0x50C273U, 0x0B1862U, 0x4A1F8CU, + 0x70A655U, 0x3BF5C2U, 0x666FBBU, 0x6DDE68U, 0x3485C5U, 0x9F161EU, 0xC46F4BU, 0x8CFDF0U, 0x97C625U, 0xDE058EU, + 0xC59CD3U, 0xAEAE20U, 0xF775BCU, 0xFC647FU, 0xBD9F02U, 0xE70C91U, 0xCC1468U, 0x11E7B7U, 0x1AFC36U, 0x435B49U, + 0x080398U, 0x139027U, 0x7B63FEU, 0x607AF9U, 0x29E900U, 0x7293D6U, 0x79026FU, 0x00D930U, 0x0BEAF1U, 0xD3614EU, + 0x90119FU, 0x8B8AE4U, 0xC61969U, 0xBD609AU, 0xB4F247U, 0xEFA954U, 0xE518A9U, 0xBC0362U, 0xD7D0D6U, 0xCE7E8DU, + 0x856F18U, 0x1C94E3U, 0x578726U, 0x0D5F1DU, 0x24ECC0U, 0x7FF713U, 0x3E26AAU, 0x251D6DU, 0x6A8F14U, 0x53648BU, + 0x19757AU, 0x40AEB4U, 0xCB9CA5U, 0x90055AU, 0x9956C3U, 0xE2ED34U, 0xAB3C7DU, 0xB126EAU, 0xFA9513U, 0xA3D2C8U, + 0x886BFDU, 0xD9F836U, 0xD2A2E3U, 0x8D1359U, 0x454804U, 0x5EDBF7U, 0x37637AU, 0x2C3089U, 0x67ABD4U, 0x3E8847U, + 0x3551BAU, 0x4D6331U, 0x46B8C4U, 0x1D299FU, 0x54120EU, 0x5FC0E1U, 0x86D93BU, 0xE56A0EU, 0xFBB1D5U, 0xB2B600U, + 0xA94EABU, 0xE05DF6U, 0x9BE605U, 0x90B798U, 0xC92C6BU, 0xC3DE66U, 0x9AC7BDU, 0xD15448U, 0x6A3FD3U, 0x23ADA3U, + 0x78346CU, 0x7147F5U, 0x2BDC02U, 0x0EAD5BU, 0x553FFCU, 0x1EA425U, 0x07D5F2U, 0x4C4ECBU, 0x554C14U, 0x3EB3F5U, + 0xE4A26AU, 0xED799BU, 0xB6CA85U, 0xFFD25CU, 0xC421BFU, 0x8F3A22U, 0x96AB51U, 0xDC518CU, 0x895217U, 0x8289F2U, + 0xF9B8A9U, 0xF0231CU, 0x2BF1C7U, 0x62C80AU, 0x781B39U, 0x1320E5U, 0x4AB156U, 0x41EB8FU, 0x1848E0U, 0x13D771U, + 0x4886AEU, 0x203C5FU, 0x3B6F40U, 0x76F6A1U, 0xE5457EU, 0xAE1EE7U, 0xD7AC10U, 0xDCB549U, 0x8476EFU, 0x8FC536U, + 0xD49DE9U, 0x9D0ED8U, 0xA63513U, 0xEFE4A6U, 0xB4DF7DU, 0x3E0D00U, 0x779693U, 0x4CA75EU, 0x0568ADU, 0x527BB0U, + 0x59C34BU, 0x00109FU, 0x0A0B14U, 0x73FA61U, 0x38E0BAU, 0x23530FU, 0x6A88D4U, 0xB199DDU, 0x98322AU, 0xC260F3U, + 0xCBF944U, 0x908A0DU, 0xDB11F2U, 0xC28163U, 0xADFABDU, 0xBC694CU, 0xF65243U, 0xAD83BAU, 0xA40D6DU, 0x5F7EF4U, + 0x16E787U, 0x0DF44AU, 0x460EF1U, 0x5E1F24U, 0x15CC3FU, 0x6C77CAU, 0x676401U, 0x3C9CBDU, 0x359FEEU, 0x6A0413U, + 0x02F590U, 0x91EE4DU, 0xDA3C3EU, 0xC305A3U, 0x889658U, 0xF14D99U, 0xFA7F86U, 0xA1E677U, 0xE981E8U, 0xF21A10U, + 0xBB4BD7U, 0x80F1CEU, 0xCB6239U, 0x123BE0U, 0x1D885FU, 0x45921EU, 0x6641E1U, 0x3DE870U, 0x74BBAFU, 0x6F00C6U, + 0x261055U, 0x7DCBA8U, 0x57787AU, 0x0E2167U, 0x05B28CU, 0xCC8819U, 0x975BE2U, 0xBC52B7U, 0xE5E52CU, 0xEB37C9U, + 0xB20E12U, 0xF9DD2FU, 0xE8C6FCU, 0x837701U, 0xD8AD82U, 0xD1BE5AU, 0x0B0525U, 0x0244B4U, 0x79FE5BU, 0x322DCAU, + 0x2B3495U, 0x60876CU, 0x79DCFBU, 0x334C12U, 0x4C7745U, 0x45A4DCU, 0x1E3F23U, 0x175FF2U, 0xC4C0D8U, 0xAFF30DU, + 0xB72AF6U, 0xFCB96BU, 0xA5C338U, 0xAE5295U, 0xF54946U, 0xDCBABBU, 0x87A1A8U, 0xCF2165U, 0xD4DA9EU, 0x9FC90BU, + 0x223070U, 0x6922A4U, 0x30B92FU, 0x3348D6U, 0x695B01U, 0x20C038U, 0x1BB2EFU, 0x523B06U, 0x49EC99U, 0x02D7C8U, + 0x5B4777U, 0x713CA6U, 0xA8AF49U, 0xA3B650U, 0xF84586U, 0xB5DF7FU, 0xAE8CF8U, 0xC72581U, 0x9D3652U, 0x9EEDCFU, + 0xC75D34U, 0xCC0671U, 0xB5B5CAU, 0xFEAC1FU, 0x677EA4U, 0x2DC5F9U, 0x26D63AU, 0x7F1F86U, 0x142855U, 0x0DF2A8U, + 0x42E3B3U, 0x195872U, 0x108B8DU, 0x6AB31CU, 0x632063U, 0x307BAAU, 0xFBC83DU, 0xE201C4U, 0xA91393U, 0x90A82AU, + 0xDAF9E4U, 0x816A55U, 0x88D00AU, 0xD383DBU, 0xFA3A64U, 0xA569A5U, 0xEEE2DEU, 0x76D243U, 0x3D0D90U, 0x649E6DU, + 0x47E76EU, 0x1C7491U, 0x156E49U, 0x4E9DDEU, 0x0604B7U, 0x3D3720U, 0x76FDD9U, 0x6FEC06U, 0x2417B7U, 0xFD04F8U, + 0xF29D29U, 0x886F92U, 0xC1744FU, 0xDAC73CU, 0x939EB1U, 0x880C63U, 0xEBE79EU, 0xB2F285U, 0xB86970U, 0xE11ABBU, + 0xEA822EU, 0x311155U, 0x586AC0U, 0x43F92BU, 0x0A81F6U, 0x5412C5U, 0x5D111CU, 0x26E8CBU, 0x2D7B63U, 0x74213CU, + 0x3F90CDU, 0x2E8B52U, 0x645883U, 0xDFE36CU, 0x96F375U, 0xDD0882U, 0xC40B1BU, 0x8FD6CCU, 0xB464A5U, 0xFC7F3EU, + 0xA7AECBU, 0xAA9511U, 0xF10634U, 0xBA5CEFU, 0x83ED32U, 0x483681U, 0x5015DCU, 0x138D3FU, 0x48DEA2U, 0x616571U, + 0x3AF40CU, 0x33AF97U, 0x681D72U, 0x2246E9U, 0x3BD7B9U, 0x506C46U, 0x0D2FDFU, 0x869338U, 0xDDC061U, 0xD45BD6U, + 0xAF6A0FU, 0xE7B8C0U, 0xFC2371U, 0xBF102EU, 0xA6C9DFU, 0xEDDA40U, 0x943089U, 0x9FA1BFU, 0x459A66U, 0x0C4995U, + 0x175108U, 0x7AE243U, 0x6139B6U, 0x2A2A2DU, 0x73D3D8U, 0x79C183U, 0x204A26U, 0x0B3FFDU, 0x5AA420U, 0x111613U, + 0x8A4FDFU, 0xC3DC2CU, 0xF9A7B5U, 0xB034EAU, 0xEBAC5BU, 0xE0CF94U, 0xBD5465U, 0xF605FAU, 0xCFBEA3U, 0x85AC54U, + 0x9E55DDU, 0xD7C62AU, 0x0CDD73U, 0x252FCDU, 0x76361CU, 0x7DF5D3U, 0x3546E2U, 0x6E5B39U, 0x67A98CU, 0x1CB247U, + 0x57231AU, 0x4AD8A9U, 0x01CA74U, 0x191187U, 0xF2208AU, 0xA9AB50U, 0xA0F8A5U, 0xFB403EU, 0xF2D34BU, 0xA9A880U, + 0xCB393DU, 0xD262EEU, 0x99D0B7U, 0xC04B00U, 0xCB1AC9U, 0xB0B176U, 0x39E3A7U, 0x677EF8U, 0x2ECD58U, 0x359687U, + 0x7E277EU, 0x473D69U, 0x0CEEB0U, 0x55D557U, 0x5F04CEU, 0x0C8EBDU, 0x25BD60U, 0x7E64DBU, 0xB7771EU, 0xACCC05U, + 0xE51CF0U, 0xBF2F2AU, 0x90F497U, 0xC9E7D4U, 0xC25F09U, 0x9B9CBAU, 0xD08767U, 0xEB320CU, 0xA36999U, 0x38FB42U, + 0x7180B3U, 0x22112CU, 0x29AA45U, 0x50F9D2U, 0x1B610AU, 0x0202FDU, 0x4899E4U, 0x57080BU, 0x3E72DAU, 0x65E165U, + 0x6CFA34U, 0xB70BEBU, 0xBC104AU, 0xE4E295U, 0x8F7BECU, 0x96787FU, 0xD583B2U, 0x9E9740U, 0x870C5DU, 0xECFFA6U, + 0xF4E433U, 0xBF35F8U, 0xE00F8DU, 0x699C16U, 0x3265EBU, 0x1B6638U, 0x40F515U, 0x0A8DC6U, 0x131E1BU, 0x5845A0U, + 0x21F670U, 0x2A6E1FU, 0x791D8EU, 0x708651U, 0x2AD7E8U, 0xE37CAFU, 0xD8EE56U, 0x97B3C1U, 0x8E0018U, 0xC51B6FU, + 0x9CC9E6U, 0xB67019U, 0xEF23C8U, 0xE498F2U, 0xBF9927U, 0xF643ECU, 0xCD7051U, 0x04E902U, 0x563AFFU, 0x5D006CU, + 0x04D3A1U, 0x0FCA9AU, 0x72794FU, 0x39A2B4U, 0x228231U, 0x6A19EAU, 0x714E96U, 0x18F705U, 0x4324FCU, 0xC83E3BU, + 0x918D02U, 0xDADCD5U, 0xC2470CU, 0xA135B3U, 0xBABCF2U, 0xF30F4DU, 0xA8549EU, 0xA1C543U, 0xDEFF78U, 0xD42CBCU, + 0x0DB747U, 0x46C6D2U, 0x5F5C89U, 0x144F60U, 0x6FA6F7U, 0x66350EU, 0x2C0A59U, 0x35DAE0U, 0x7EC12FU, 0x0D32FEU, + 0x0429C1U, 0x5FB911U, 0xD642AEU, 0x895167U, 0xC3D8B0U, 0xFAAB89U, 0xB1315AU, 0xA8C0A7U, 0xE3DB24U, 0xB84879U, + 0x913382U, 0xCBA317U, 0x82F8FCU, 0x994BA9U, 0x50C213U, 0x4390CEU, 0x282F5DU, 0x713E30U, 0x7FCDE3U, 0x26565EU, + 0x2D0485U, 0x56BDD4U, 0x1FAE7BU, 0x0475AAU, 0x4DD555U, 0x17CE4CU, 0x9C1D9BU, 0xE52473U, 0xEEF7E4U, 0xB7CD1DU, + 0xF45E42U, 0xEF87E3U, 0x87B43CU, 0x986FADU, 0xD16FD2U, 0x8AD403U, 0x8103A8U, 0xD83A75U, 0x33A826U, 0x2BF39BU, + 0x604049U, 0x7B99A4U, 0x328ABFU, 0x49306AU, 0x407191U, 0x1BEA04U, 0x19D96FU, 0x4001F2U, 0x0FB201U, 0x36E9DCU, + 0xFD7ADFU, 0xE64326U, 0xAF91F9U, 0xF51249U, 0xDC2B16U, 0x87F8D7U, 0xCCE668U, 0xC517B1U, 0x9E8C46U, 0x97BF5FU, + 0xED6498U, 0xA67461U, 0x378FF6U, 0x788C8FU, 0x611514U, 0x0AE6F1U, 0x53FC2BU, 0x596F3EU, 0x0216C5U, 0x4B8508U, + 0x507FBBU, 0x396EE6U, 0x22F535U, 0xE99688U, 0xB10F43U, 0xBA1D36U, 0xC3E2ADU, 0xC07178U, 0x9B28C3U, 0xD69A8BU, + 0xCD817CU, 0x8570E5U, 0xFEEB12U, 0xF5E8CBU, 0xAC10C4U, 0x270335U, 0x7ED8EAU, 0x156B5BU, 0x0E7A14U, 0x46A0C5U, + 0x5D937AU, 0x144AA3U, 0x4F79D5U, 0x6CF35CU, 0x31228FU, 0x7A1932U, 0x628E69U, 0xA9D59CU, 0x926517U, 0xDBBEE2U, + 0x80ADB9U, 0x891424U, 0xD246D7U, 0xD8ED1AU, 0xA17C28U, 0xEA27F5U, 0xF3942EU, 0xB8CE8FU, 0xAB5FD0U, 0x466461U, + 0x1CB7BEU, 0x152F6FU, 0x4E1CC0U, 0x05D799U, 0x1CE66EU, 0x773DF7U, 0x7EAB00U, 0x249048U, 0x6D41D7U, 0x765A26U, + 0x1DA9F9U, 0x8431C8U, 0xCF0203U, 0x96C1DEU, 0x90D86DU, 0xCB6A30U, 0xA23193U, 0xB9A24EU, 0xF05B95U, 0xEB48A0U, + 0xA0D27AU, 0xD8A39FU, 0xD33804U, 0x0A9B79U, 0x01C3AAU, 0x5A5437U, 0x132FD4U, 0x28BC0DU, 0x60253AU, 0x3F57E3U, + 0x3CCC7CU, 0x65DD9DU, 0x4E26C2U, 0x172572U, 0xDCDDADU, 0xC64E64U, 0x8F5553U, 0x94A68AU, 0xFDBE7DU, 0xA66DE4U, + 0xADD68BU, 0xF4C75AU, 0xFE0CC1U, 0x873E34U, 0xC8A72FU, 0xDBD0C2U, 0x124B10U, 0x49998DU, 0x40A8FEU, 0x3A3323U, + 0x316088U, 0x68D95DU, 0x235B06U, 0x3A00B3U, 0x51B178U, 0x4AEA89U, 0x025816U, 0x59C36FU, 0xD092B8U, 0x8B2930U, + 0xE43AC7U, 0xF5E2DEU, 0xBEC121U, 0xA71AF0U, 0xED8B7FU, 0x94B40EU, 0x9F66D1U, 0xD45D68U, 0xCD8CBFU, 0x8617F6U, + 0x5F2545U, 0x75FC98U, 0x2EFF62U, 0x674467U, 0x7C959CU, 0x318F09U, 0x0A7CD2U, 0x4967AFU, 0x11D62CU, 0x1A8CD1U, + 0x431F02U, 0x48A69DU, 0xB3E5ECU, 0xFA7623U, 0xE10E9AU, 0xA99948U, 0xB20215U, 0xD971A6U, 0x80E86BU, 0x8BDA90U, + 0xD60185U, 0x9D907EU, 0x8FFBFBU, 0xE66920U, 0x7D705DU, 0x3483CEU, 0x6F9833U, 0x646BF1U, 0x1DF3E8U, 0x17E017U, + 0x4E1BC6U, 0x050A79U, 0x1E8038U, 0x5773E7U, 0x2C685EU, 0xA1BD89U, 0xFB86B0U, 0xF01477U, 0xA16D8EU, 0xCAFE19U, + 0xD365C1U, 0x9815AEU, 0x839E3FU, 0xCBCDC4U, 0x907611U, 0xB9E70AU, 0xE2BDE7U, 0x2B0E34U, 0x301789U, 0x7BE4DAU, + 0x477707U, 0x0C2FACU, 0x558C79U, 0x5E9743U, 0x0D4496U, 0x04786DU, 0x7FABE0U, 0x3730B3U, 0x3C014AU, 0xE7DADDU, + 0xEEE834U, 0x956163U, 0xDCB2FAU, 0xC78905U, 0x8D5BD4U, 0xD0427BU, 0xDBF12BU, 0xA22AB4U, 0xA93B4DU, 0xFA819AU, + 0xB3D2B3U, 0x287B64U, 0x40289DU, 0x5BB206U, 0x100153U, 0x495CB8U, 0x42CF2DU, 0x3BF4D6U, 0x70248BU, 0x6ABF19U, + 0x23CCF4U, 0x3C4527U, 0x75761AU, 0x8EACC1U, 0x853F44U, 0xD44EBFU, 0xDED5EEU, 0x87C751U, 0xEC3E80U, 0xF72D6FU, + 0xBEB676U, 0xE557A1U, 0xEC4D59U, 0xB6BECEU, 0x9DA527U, 0x443078U, 0x0BCAE9U, 0x12D916U, 0x594087U, 0x6033E8U, + 0x22A831U, 0x7948A2U, 0x70535FU, 0x2BC01CU, 0x62BBA1U, 0x592A7BU, 0x92308EU, 0x8AC395U, 0xC15A50U, 0x9809ABU, + 0xB3B336U, 0xECB245U, 0xE54998U, 0xBEDA1BU, 0xF681E6U, 0xED35F5U, 0x8E2E0CU, 0x87FDD3U, 0x5CC453U, 0x1556ACU, + 0x0E85FDU, 0x64AC42U, 0x3D7F8BU, 0x36447CU, 0x6FD665U, 0x640FB2U, 0x3B3C4BU, 0x52A7C4U, 0x48F7B5U, 0x014C2EU, + 0x9A9FFBU, 0xD19601U, 0xA0250CU, 0xAB7FFFU, 0xF2C822U, 0xB8D1B1U, 0xA302CCU, 0xEAB907U, 0xD1E9B2U, 0x987269U, + 0xC3411CU, 0xCC8897U, 0x141A42U, 0x3F61B8U, 0x66F2A1U, 0x2DCB56U, 0x3618DFU, 0x778208U, 0x2CB3F1U, 0x0468EEU, + 0x5F7B1FU, 0x5693D0U, 0x0D8041U, 0x461B3EU, 0xFFECE7U, 0xB4FD50U, 0xA94798U, 0xE314CFU, 0xB88D76U, 0xB17EADU, + 0xCA7508U, 0xC3E553U, 0x989EA6U, 0xDB0D3DU, 0xC396E8U, 0xA8E683U, 0x717D1EU, 0x7A0EEDU, 0x219730U, 0x288422U, + 0x736ECFU, 0x1BFF14U, 0x04A4A1U, 0x4F177AU, 0x56092BU, 0x1DD884U, 0x64635DU, 0xEF70EAU, 0xA589B3U, 0xF49B54U, + 0xFF50CDU, 0xA66312U, 0x8DFA62U, 0xD628FDU, 0x9F131CU, 0x8582C3U, 0xCCF9DAU, 0xF36A29U, 0xB8B2F4U, 0x618157U, + 0x6A020AU, 0x335999U, 0x79E864U, 0x4272BFU, 0x03259AU, 0x189C40U, 0x51CFB5U, 0x0A752EU, 0x216463U, 0x79BF90U, + 0x721C0DU, 0xAB47FEU, 0xE4D727U, 0xFDEC28U, 0x963FD9U, 0x8DA646U, 0xC594B7U, 0x9E4FE8U, 0x977E60U, 0xECA597U, + 0xAF264EU, 0xB61C79U, 0xFDCDA0U, 0x65D64FU, 0x2E61DCU, 0x553881U, 0x5CAA72U, 0x0351FBU, 0x0A400CU, 0x51FB55U, + 0x3BB9CAU, 0x22223AU, 0x6993B5U, 0x30C8C4U, 0x3B5B1BU, 0xE02B82U, 0xC1B075U, 0x9B23BCU, 0xD25A8BU, 0xC9C852U, + 0x82A3A9U, 0xBB303CU, 0xF42977U, 0xADDA82U, 0xA64418U, 0xFC55E5U, 0xB5AEE6U, 0x0EBD3BU, 0x4765C8U, 0x4CD655U, + 0x17DD2EU, 0x562EEBU, 0x6C3770U, 0x25A585U, 0x3E5EDEU, 0x754F6FU, 0x2C94A1U, 0x23A758U, 0x5A3F4FU, 0xD07C96U, + 0x8BC761U, 0xC254E8U, 0xD92C97U, 0xB0BF06U, 0xEBE0D9U, 0xE25138U, 0xB8CAA7U, 0xBB98DEU, 0xE22109U, 0x896291U, + 0x10F172U, 0x5BCB2FU, 0x401A94U, 0x0CA141U, 0x77B2BAU, 0x7E6BBFU, 0x255964U, 0x6E82D9U, 0x77130AU, 0x3C3877U, + 0x04EAF4U, 0x4FD129U, 0x9C40DBU, 0x959BC6U, 0xCEAC2DU, 0xE774FCU, 0xBC6763U, 0xF6DC12U, 0xEB8DCDU, 0xA00664U, + 0xF9F4B3U, 0xD2EF4AU, 0x895E5DU, 0x800584U, 0x5A972BU, 0x132EFBU, 0x287D84U, 0x63E615U, 0x7297CEU, 0x391D23U, + 0x608E30U, 0x6AF5CDU, 0x11641EU, 0x5C5E93U, 0x4789E0U, 0x0E903DU, 0x956386U, 0xFEF053U, 0xB6E879U, 0xAD0BACU, + 0xE41077U, 0xFF83CAU, 0xB47A99U, 0xCD6870U, 0xCE93E7U, 0x96823EU, 0x9D1941U, 0xC4EBD0U, 0x2BF23FU, 0x3031EEU, + 0x790A71U, 0x229909U, 0x2AC1CEU, 0x717677U, 0x5AEDA0U, 0x039C99U, 0x480646U, 0x515587U, 0x1AEC3CU, 0x296F69U, + 0xE13492U, 0xBA8607U, 0xB39FCCU, 0xEC4CB1U, 0xA77723U, 0x9EA7DEU, 0xD51C0DU, 0xCD0F00U, 0x86D4FBU, 0xDDF56EU, + 0xF46F95U, 0x2FBCD4U, 0x268D6BU, 0x7D52B2U, 0x374165U, 0x26F9DCU, 0x4D2A9BU, 0x141163U, 0x1FD2FCU, 0x40CA2DU, + 0x497952U, 0x3322D3U, 0x7AB32CU, 0xE108F5U, 0xAA5AE2U, 0xB3E31BU, 0xF8B098U, 0x812B65U, 0x8B8936U, 0xD0D08AU, + 0xD94341U, 0x8A7894U, 0xE3A9AFU, 0xF8377AU, 0xB74481U, 0x6FDD0CU, 0x64EE5FU, 0x3D35A2U, 0x163731U, 0x5F8ECCU, + 0x045DC7U, 0x0F4616U, 0x57B6E8U, 0x7CAD79U, 0x253E86U, 0x6EC7CFU, 0x7DD478U, 0xB426A1U, 0xCF2D76U, 0xC3BC5FU, + 0x984780U, 0x935571U, 0xCACCEEU, 0x81BBBFU, 0xB82054U, 0xF371C0U, 0xE9CB3BU, 0xA05826U, 0xFB33F5U, 0x52A218U, + 0x09B88BU, 0x424BF6U, 0x53D22DU, 0x198198U, 0x043A53U, 0x6F2A06U, 0x34F1BDU, 0x3DC260U, 0x664982U, 0x6FB81BU, + 0x15A24CU, 0xDE71F5U, 0xC7482AU, 0x8CDFCBU, 0x9505D4U, 0xDE3405U, 0xA5EFFAU, 0xA4FC63U, 0xFE5704U, 0xB387DDU, + 0xA8BC6AU, 0xC32FB2U, 0x5A7EE5U, 0x11C44CU, 0x489797U, 0x420E62U, 0x19BD79U, 0x30E6BCU, 0x6B6407U, 0x225DDAU, + 0x398EA9U, 0x703534U, 0x0A64F7U, 0x09FA0AU, 0xD4C910U, 0xDF10E5U, 0x86833EU, 0xCDB99BU, 0xE67A40U, 0xBE631BU, + 0xB590AEU, 0xEC8B75U, 0xA73BD0U, 0x9CE08BU, 0xD5F35EU, 0x8E0AE5U, 0x061828U, 0x5D835AU, 0x5660C7U, 0x277914U, + 0x68CAE9U, 0x7190E2U, 0x3A0113U, 0x20FECCU, 0x49ED7DU, 0x127522U, 0x1B06ABU, 0x40855CU, 0x8B9E85U, 0x926FB2U, + 0xF8F56AU, 0xE186A5U, 0xAA1F14U, 0xF10CCBU, 0xF0F7BAU, 0x8F6735U, 0x867CECU, 0xDC9F1FU, 0x978402U, 0x8E54F1U, + 0x45EF3CU, 0x7CFC8FU, 0x3705D2U, 0x6C1248U, 0x64C8BDU, 0x3FF976U, 0x566243U, 0x4DA198U, 0x069B45U, 0x1F0AF6U, + 0x5851BBU, 0x00E248U, 0xAB3BD1U, 0xF2090EU, 0xF9926FU, 0xA2C3F1U, 0xEB7800U, 0xD07B9FU, 0x98A1E6U, 0xC31021U, + 0xC84BB8U, 0x91D84FU, 0x9AEC96U, 0x6337A9U, 0x288468U, 0x369FB3U, 0x774E06U, 0x6C645DU, 0x05B7A9U, 0x4E2E22U, + 0x551DFFU, 0x1CC78CU, 0x47D611U, 0x4F2DF2U, 0x343E6FU, 0xBF8514U, 0xE655C1U, 0xAD5E5AU, 0xB4EDBFU, 0xDFB4E4U, + 0xC1265DU, 0x80DD8BU, 0xDBC852U, 0xD25375U, 0x8920ACU, 0xA2BA53U, 0xFB0BC2U, 0x31401DU, 0x28D33CU, 0x63AAE3U, + 0x18381AU, 0x11238DU, 0x4AD2E4U, 0x434933U, 0x195BABU, 0x56A058U, 0x6FB105U, 0x2C5AAEU, 0x35C97BU, 0xFED9A0U, + 0xA52295U, 0x8D314EU, 0xD6ECA3U, 0x9F5E30U, 0x84456DU, 0xCFB6DEU, 0xD6AF03U, 0xBD2CE9U, 0xE556FCU, 0xEEC707U, + 0xB71CD6U, 0x382F59U, 0x43B720U, 0x02E4F7U, 0x195F4EU, 0x51CC99U, 0x0AA550U, 0x013767U, 0x786CBEU, 0x73DD01U, + 0x2AC6D1U, 0x61159EU, 0x7BA92FU, 0x92BAF4U, 0x896109U, 0xC0521AU, 0x9F9AF7U, 0x942924U, 0xC532B9U, 0xEFE3C2U, + 0xA6D807U, 0xFD0ABCU, 0xF69369U, 0xAFA033U, 0x44738EU, 0x5D694DU, 0x17C8F0U, 0x0C93A3U, 0x45207AU, 0x1EF9C5U, + 0x37EB04U, 0x6850FBU, 0x6305EAU, 0x3B9E15U, 0x782DC4U, 0x41774BU, 0x8AF633U, 0xD18DE4U, 0xD81E5DU, 0x83A69AU, + 0x8AF583U, 0xF06E7CU, 0xBB5FADU, 0xA28416U, 0xE99653U, 0xF06D88U, 0x9FEC35U, 0xC4F7E6U, 0x4C059AU, 0x1F1C19U, + 0x56EFC4U, 0x4D743FU, 0x24612AU, 0x3F9BD1U, 0x748814U, 0x2C13AFU, 0x27F276U, 0x5EE861U, 0x553B88U, 0x0E0A5FU, + 0xC791E6U, 0xD8E2B0U, 0x907A69U, 0xABE9C6U, 0xE09217U, 0xB10168U, 0xBA48F9U, 0xE3FA26U, 0x8861CFU, 0x9230D8U, + 0xDB8B21U, 0xC099B2U, 0x09644FU, 0x52F704U, 0x79AC90U, 0x201F6BU, 0x2E17BEU, 0x77C495U, 0x3CFF48U, 0x172E9BU, + 0x4E9426U, 0x0D8775U, 0x145E98U, 0x5E6D03U, 0xC5F6D6U, 0xAC242DU, 0xF70D3CU, 0xFEDED2U, 0xA5C543U, 0xAE74BCU, + 0xD62EE5U, 0x9D9D72U, 0x80029BU, 0xCB534CU, 0x90E175U, 0x19BAAAU, 0x6A3B6BU, 0x6280D4U, 0x39D385U, 0x724B7AU, + 0x6B78E2U, 0x00A321U, 0x19101CU, 0x5248CFU, 0x0ADB30U, 0x01F0A9U, 0x5A21CEU, 0xB73A17U, 0xACC880U, 0xE55179U, + 0xFE42A6U, 0xB4B987U, 0xC5AF58U, 0xCE1688U, 0x97C533U, 0x9CCE76U, 0xC73F8DU, 0x8E2510U, 0xB4B6C3U, 0x7D4FFEU, + 0x665C3DU, 0x2DC7C0U, 0x70B55BU, 0x5B2C2EU, 0x025FF5U, 0x49D470U, 0x53448AU, 0x1A3FD7U, 0x09AC64U, 0x60BDBDU, + 0x3B467AU, 0xB0D043U, 0xE98B9CU, 0xE33A2DU, 0x9A21E2U, 0xD1C3B3U, 0xCA5A0CU, 0x8709DDU, 0xDCB222U, 0xF5A3AAU, + 0xBF79DDU, 0xA44A04U, 0xEDD193U, 0x3E006AU, 0x373B21U, 0x4CF994U, 0x47C04FU, 0x1F53DAU, 0x5488A1U, 0x4DB86CU, + 0x2623DFU, 0x7D7402U, 0x70CF50U, 0x2B9EFDU, 0x232426U, 0xF8A7D3U, 0x91FEC8U, 0x8A4D39U, 0xC117F6U, 0xD0866FU, + 0x9B3D18U, 0xE36EC1U, 0xE8F576U, 0xB3C5BFU, 0xBA1629U, 0xE1BD50U, 0xA8EC8FU, 0x17763EU, 0x5D45F1U, 0x049CA0U, + 0x0F8F1FU, 0x5630C6U, 0x7DE225U, 0x26FB38U, 0x6F08CBU, 0x7D0316U, 0x34B28DU, 0x2F68E9U, 0xC47B72U, 0x9DC287U, + 0x96915CU, 0xCF0B41U, 0x85F8A2U, 0xBAE17FU, 0xF372CCU, 0xE81991U, 0xA1894AU, 0xFAF2EBU, 0xF16134U, 0x89F845U, + 0x0A8ADBU, 0x53153AU, 0x1806E5U, 0x03FF7CU, 0x6A7C0BU, 0x312692U, 0x399775U, 0x628CACU, 0x6D7FB3U, 0x34EE42U, + 0x5FF49DU, 0x56073CU, 0x8D1C67U, 0x87CDBBU, 0xDEE708U, 0xB574D5U, 0xA4ADB6U, 0xEF9E2BU, 0xF605D0U, 0xBD7545U, + 0xE6EE0EU, 0xCE39FBU, 0x950260U, 0xD8929DU, 0x43D9CEU, 0x086A47U, 0x31B3B1U, 0x7AA068U, 0x221ADFU, 0x294B86U, + 0x72F049U, 0x73E3F8U, 0x083927U, 0x418856U, 0x5AC3C9U, 0x105020U, 0xC969B7U, 0xE2BBEEU, 0xBF2019U, 0xB41181U, + 0xEFCA6AU, 0xA6FD3FU, 0xBC27A4U, 0xD53651U, 0xCE9D9AU, 0x854EA7U, 0xDC5E74U, 0xDFE5A9U, 0x26B61AU, 0x6C0D57U, + 0x77DCECU, 0x3EC639U, 0x2575C3U, 0x682CD6U, 0x13AF1DU, 0x1855ECU, 0x404473U, 0x4BDF8AU, 0x12ACDDU, 0xF93754U, + 0xE207A3U, 0xABD87AU, 0xF04B45U, 0xF03284U, 0xABB05BU, 0x80ABEBU, 0xD95AB4U, 0x92C10DU, 0x8FD2CEU, 0xC42833U, + 0xEC3920U, 0x37C2FDU, 0x7C5106U, 0x654883U, 0x2EAAF8U, 0x37B12DU, 0x5C20B6U, 0x065B42U, 0x07C909U, 0x5C12B4U, + 0x152367U, 0x2EB4FAU, 0x65CF19U, 0xFC5F40U, 0xB294FFU, 0xEBA72EU, 0xE03ED1U, 0x9B6CD0U, 0x92D70FU, 0xC944F6U, + 0x801D60U, 0x9AAE19U, 0xF1F4DEU, 0xA85547U, 0xAB4EB8U, 0x729DE9U, 0x792456U, 0x223697U, 0x4BED0CU, 0x55DE71U, + 0x1C03A2U, 0x07910FU, 0x4CAADCU, 0x356BA0U, 0x3E5033U, 0x67C3EEU, 0x2D9B05U, 0xB62810U, 0xFFF3EBU, 0xC4E03EU, + 0x8558A5U, 0xDE0B48U, 0xD5905BU, 0x8D71A2U, 0xA26A75U, 0xFBD8ECU, 0xB08982U, 0xAB1253U, 0xE2A1ECU, 0x79FB3FU, + 0x116E52U, 0x4A15C9U, 0x43861CU, 0x188FE7U, 0x537DF2U, 0x62E619U, 0x29D7C0U, 0x310C57U, 0x7A1F2EU, 0x25E5B8U, + 0xAC7451U, 0xC76F86U, 0xDE9C9FU, 0x959460U, 0xCF27B1U, 0xC6FC1EU, 0xBDEDCFU, 0xF416B0U, 0xEF0429U, 0xA49FEEU, + 0xBDEA17U, 0xFF7104U, 0x06A3F8U, 0x0D8A63U, 0x5219A6U, 0x5B62DDU, 0x00F348U, 0x6969B3U, 0x731A6EU, 0x38816DU, + 0x61D090U, 0x6A6343U, 0x33F9FEU, 0x18B8A5U, 0xC30340U, 0x8B10DAU, 0x98E80BU, 0xD1FB74U, 0xEA20F5U, 0xA5930AU, + 0xFC8E93U, 0xF75CC4U, 0xAF673DU, 0xA4E6BAU, 0xDF3D43U, 0x960F9CU, 0x0DD68DU, 0x44E572U, 0x1F7EB2U, 0x35AD09U, + 0x6C9554U, 0x6746A7U, 0x365D3AU, 0x7DFCF9U, 0x64A6C4U, 0x0B351FU, 0x118CEAU, 0x58DF61U, 0x836434U, 0x8A36CFU, + 0xF1AB5BU, 0xBA18A0U, 0xA343EDU, 0xE8C27EU, 0xF0F887U, 0xBB2B50U, 0xC03A69U, 0xC9C1A6U, 0x9A5317U, 0x9368C8U, + 0x5CB919U, 0x26A226U, 0x2F01EFU, 0x74D919U, 0x3DCA80U, 0x2631D7U, 0x6D223EU, 0x54BAA1U, 0x1E4950U, 0x47520BU, + 0x4CA79EU, 0x97BC75U, 0xBE3EA8U, 0xED479BU, 0xA4D446U, 0xBA4FF5U, 0xF13C39U, 0xE8A46AU, 0x83D7D7U, 0xDA4C0CU, + 0xD1DDF9U, 0x8AA7F2U, 0xC22427U, 0x793DDCU, 0x30CE45U, 0x2B5522U, 0x6007FBU, 0x39BE6CU, 0x32AD95U, 0x42560BU, + 0x4D426AU, 0x16D1B5U, 0x5F3A04U, 0x442BDBU, 0x2DF082U, 0xF6C225U, 0xFE59FCU, 0xA5880FU, 0xAEB312U, 0xF761C9U, + 0x9C582CU, 0x85CBB7U, 0xCE00C3U, 0xD43118U, 0x9DAB9DU, 0xEAF866U, 0xE3437BU, 0x381288U, 0x738955U, 0x6A3BF6U, + 0x2066ABU, 0x19D570U, 0x52DEC1U, 0x090E1EU, 0x00B5FFU, 0x5BE6E1U, 0x727D38U, 0x284CCFU, 0x639656U, 0xFA8531U, + 0xBD3CA8U, 0xD4EF77U, 0xCFC586U, 0x841489U, 0x9C0F78U, 0xD7BCA7U, 0x8E671EU, 0xA5774DU, 0xFE8481U, 0xF79F32U, + 0xAC0AEFU, 0x65F09CU, 0x5FF301U, 0x144ACAU, 0x0D193FU, 0x468224U, 0x13F0D1U, 0x18694AU, 0x63FA87U, 0x2B81F4U, + 0x30106DU, 0x790A9BU, 0xE2E952U, 0x8970CDU, 0xD003BCU, 0xDB9963U, 0x838AD2U, 0x88731DU, 0xD1E064U, 0xBAFFF3U, + 0xA10F2AU, 0xEC049DU, 0xBFD7D4U, 0xB7EE2BU, 0x4C7CBBU, 0x478760U, 0x1E9415U, 0x554D9EU, 0x4C7E6BU, 0x07E4B0U, + 0x3D35ADU, 0x741E4EU, 0x2F8D93U, 0x26FC20U, 0x7D667DU, 0x16B586U, 0x8B8E02U, 0xC91FD9U, 0xD0456CU, 0x9BF237U, + 0xC0EBCEU, 0xE92849U, 0xB29390U, 0xBBC3E7U, 0xE1787EU, 0xAA6B81U, 0x93B040U, 0xD8005FU, 0x411BAEU, 0x0AC870U, + 0x51F1D1U, 0x5D328EU, 0x362837U, 0x6799E0U, 0x6C4239U, 0x37711AU, 0x3EABC7U, 0x45BA3CU, 0x0D01A9U, 0x16D6F2U, + 0xDDCF17U, 0xC46D8CU, 0x8F3670U, 0xF6A723U, 0xFD5CBCU, 0xA74F5DU, 0xEAF582U, 0xF1A43BU, 0x903768U, 0x8B0CC5U, + 0xC0DC16U, 0x9957CBU, 0x1324F0U, 0x4ABD25U, 0x61AECEU, 0x38545AU, 0x73C701U, 0x68FEF4U, 0x212D6FU, 0x5B3382U, + 0x52C2D1U, 0x09494CU, 0x065ABFU, 0xDFA126U, 0x9CB149U, 0xA56A98U, 0xEE5927U, 0xF4C0F6U, 0xBD33B8U, 0xE62901U, + 0xCFB8D6U, 0x94D32FU, 0x9F40B8U, 0xC69AF1U, 0x8CAB0EU, 0x15309FU, 0x7E6360U, 0x21DA31U, 0x2848BAU, 0x733747U, + 0x72A6D4U, 0x08EDA8U, 0x435F7BU, 0x5A4CD6U, 0x119505U, 0x082658U, 0x433DE3U, 0xB8ED26U, 0xB0D6DDU, 0xEB05C8U, + 0xA2BC13U, 0xA9BEEAU, 0xD6656DU, 0xDF5614U, 0x848F82U, 0xC41C5BU, 0xDF26A4U, 0x94F7A5U, 0xADCC5AU, 0x665B8BU, + 0x3F1234U, 0x34A0EDU, 0x6E7BAAU, 0x076813U, 0x1CD1C4U, 0x55833DU, 0x4E1836U, 0x03A9E2U, 0x58F219U, 0x72418CU, + 0x2B09F7U, 0xA89A72U, 0xF1A1A9U, 0xBA7254U, 0x81EA47U, 0xC899BAU, 0xD20279U, 0x9B13C4U, 0xC0E09FU, 0xCB7E4BU, + 0xB25FF0U, 0xF98431U, 0xE4974EU, 0x2E6CD7U, 0x35FC00U, 0x5CE7A9U, 0x07147EU, 0x060D07U, 0x5D9F98U, 0x56E449U, + 0x0E65A6U, 0x659EB7U, 0x7C8D49U, 0x371790U, 0x6C6623U, 0xE5FD6EU, 0x9E6EBDU, 0x921600U, 0xC985D3U, 0x82DAEEU, + 0x9B7B25U, 0xD0E0F0U, 0xE1924BU, 0xAA091EU, 0xF158F5U, 0xF9E369U, 0x22F1BAU, 0x4B28C7U, 0x509B54U, 0x1B80BDU, + 0x024162U, 0x497B53U, 0x01A88CU, 0x3E1B5DU, 0x7502F2U, 0x6CD12BU, 0x27EB1CU, 0x7E7AC5U, 0xDDA113U, 0x8596BAU, + 0xCE5EEDU, 0xD54D14U, 0x9CF68BU, 0x87A54AU, 0xEE1C31U, 0xB58EA4U, 0xBFD55FU, 0xE66482U, 0xE93FA1U, 0x90AD7CU, + 0x5B04EFU, 0x405713U, 0x09CC48U, 0x13BFEDU, 0x522736U, 0x2914E3U, 0x22CFD8U, 0x7B5E05U, 0x3061E6U, 0x29B37FU, + 0x43BAA8U, 0x5849D1U, 0x91D25EU, 0xCEE0AFU, 0xC73971U, 0x9C2A40U, 0xB7919FU, 0xEF401EU, 0xA452E1U, 0xB5B9B8U, + 0xFEA80FU, 0x8533D6U, 0x8C4115U, 0xD7DA28U, 0x5F6BF3U, 0x043006U, 0x4FA39DU, 0x76DBD9U, 0x394C22U, 0x20C7BFU, + 0x6BB64CU, 0x312C41U, 0x187FB2U, 0x43C46FU, 0x0A55F4U, 0x192E81U, 0xD2BC4AU, 0xCBA5FBU, 0xA15624U, 0xF85DFDU, + 0xF38ECBU, 0xBA3602U, 0xA125F5U, 0xCEFE6CU, 0x97CF3BU, 0x9D55C2U, 0xC4A64DU, 0x4FBFBCU, 0x1468A3U, 0x7D4352U, + 0x6ED19DU, 0x270804U, 0x7D3B76U, 0x76A0ABU, 0x0FF018U, 0x0443D5U, 0x5D188EU, 0x16A93BU, 0x0932E0U, 0xC07015U, + 0xFACB1EU, 0xB39AC3U, 0xE80170U, 0xE3B3ADU, 0xBAEA5EU, 0xD17956U, 0xC042A9U, 0x8A9378U, 0x912DE7U, 0xD86E86U, + 0x83F559U, 0x2AC4E8U, 0x711F37U, 0x7A0D6EU, 0x26B4C9U, 0x6D6710U, 0x547CE7U, 0x1F8CFEU, 0x449720U, 0x4D3483U, + 0x16EF5AU, 0x1EFE2DU, 0x6D44B4U, 0xA6174BU, 0xBF8E8AU, 0xF4FD95U, 0xED6764U, 0x86D6BBU, 0xDC8912U, 0xD10A45U, + 0x8A799CU, 0x83E12AU, 0xF872F3U, 0xB10954U, 0xAA980DU, 0x6083D6U, 0x397163U, 0x3AE8B8U, 0x439BDDU, 0x481046U, + 0x1302BBU, 0x5AFB68U, 0x50E875U, 0x297396U, 0x26824AU, 0x7D98F1U, 0x344BA4U, 0xAF726FU, 0xE6F5DAU, 0x9C0F01U, + 0x971C38U, 0xCE85EFU, 0xC5F626U, 0x946D91U, 0xFFBDC8U, 0xE48637U, 0xAC15A6U, 0xB74C48U, 0x7EEE99U, 0x21B586U, + 0x0A0677U, 0x539FA8U, 0x18CC01U, 0x007652U, 0x4B67CFU, 0x70B43CU, 0x390FF1U, 0x625ECAU, 0x6BD01FU, 0x38E3C4U, + 0xB23870U, 0xCB893BU, 0x8093C6U, 0x994055U, 0xD679A8U, 0x8DAAFBU, 0xA4B176U, 0xFE018DU, 0xF7CA5CU, 0xACD963U, + 0xE762B2U, 0xFE323DU, 0x1589C4U, 0x0C5A92U, 0x4F432BU, 0x17F0ECU, 0x1CAA35U, 0x673B82U, 0x6E54DBU, 0x31C724U, + 0x785CA5U, 0x632C5AU, 0x29B70BU, 0x508490U, 0xDB5D6DU, 0x82CFEEU, 0x89B492U, 0xD22541U, 0xBB2EDCU, 0xA1DD27U, + 0xE04F62U, 0xFB56D9U, 0xB0A50CU, 0xF9BED7U, 0xC24EFAU, 0x8F5529U, 0x55C6D0U, 0x5E3B47U, 0x07383FU, 0x2CA2F0U, + 0x75D161U, 0x3E489EU, 0x25BB0FU, 0x6DA170U, 0x7630B1U, 0x174B2EU, 0x4CD8D7U, 0x470180U, 0x9E2339U, 0xD5B8FEU, + 0xE9EB27U, 0xA2521DU, 0xB941C8U, 0xF0BB23U, 0xAB2AB6U, 0xA271CDU, 0xD9C250U, 0xD3DC83U, 0x8A1D6EU, 0x41A67DU, + 0x58B580U, 0x3B6C5BU, 0x205ECEU, 0x6985A5U, 0x333471U, 0x3E27CAU, 0x65FD13U, 0x0CCE44U, 0x1747EDU, 0x5C143AU, + 0x45AF83U, 0x8F7F54U, 0xF6643DU, 0xFDD7A2U, 0xA68E73U, 0xAF3D8CU, 0xF4E79DU, 0xB5E073U, 0x8F59AAU, 0xC40A3DU, + 0x999044U, 0x922197U, 0xCB7A3AU, 0x60E9E1U, 0x3B90B4U, 0x73020FU, 0x6839DAU, 0x21FA71U, 0x3A632CU, 0x5151DFU, + 0x088A43U, 0x039B80U, 0x4260FDU, 0x18F36EU, 0x33EB97U, 0xEE1848U, 0xE503C9U, 0xBCA4B6U, 0xF7FC67U, 0xEC6FD8U, + 0x849C01U, 0x9F8506U, 0xD616FFU, 0x8D6C29U, 0x86FD90U, 0xFF26CFU, 0xF4150EU, 0x2C9EB1U, 0x6FEE60U, 0x74751BU, + 0x39E696U, 0x429F65U, 0x4B0DB8U, 0x1056ABU, 0x1AE756U, 0x43FC9DU, 0x282F29U, 0x318172U, 0x7A90E7U, 0xE36B1CU, + 0xA878D9U, 0xF2A0E2U, 0xDB133FU, 0x8008ECU, 0xC1D955U, 0xDAE292U, 0x9570EBU, 0xAC9B74U, 0xE68A85U, 0xBF514BU, + 0x34635AU, 0x6FFAA5U, 0x66A93CU, 0x1D12CBU, 0x54C382U, 0x4ED915U, 0x056AECU, 0x5C2D37U, 0x779402U, 0x2607C9U, + 0x2D5D1CU, 0x72ECA6U, 0xBAB7FBU, 0xA12408U, 0xC89C85U, 0xD3CF76U, 0x98542BU, 0xC177B8U, 0xCAAE45U, 0xB29CCEU, + 0xB9473BU, 0xE2D660U, 0xABEDF1U, 0xA03F1EU, 0x7926C4U, 0x1A95F1U, 0x044E2AU, 0x4D49FFU, 0x56B154U, 0x1FA209U, + 0x6419FAU, 0x6F4867U, 0x36D394U, 0x3C2199U, 0x653842U, 0x2EABB7U, 0x95C02CU, 0xDC525CU, 0x87CB93U, 0x8EB80AU, + 0xD423FDU, 0xF152A4U, 0xAAC003U, 0xE15BDAU, 0xF82A0DU, 0xB3B134U, 0xAAB3EBU, 0xC14C0AU, 0x1B5D95U, 0x128664U, + 0x49357AU, 0x002DA3U, 0x3BDE40U, 0x70C5DDU, 0x6954AEU, 0x23AE73U, 0x76ADE8U, 0x7D760DU, 0x064756U, 0x0FDCE3U, + 0xD40E38U, 0x9D37F5U, 0x87E4C6U, 0xECDF1AU, 0xB54EA9U, 0xBE1470U, 0xE7B71FU, 0xEC288EU, 0xB77951U, 0xDFC3A0U, + 0xC490BFU, 0x89095EU, 0x1ABA81U, 0x51E118U, 0x2853EFU, 0x234AB6U, 0x7B8910U, 0x703AC9U, 0x2B6216U, 0x62F127U, + 0x59CAECU, 0x101B59U, 0x4B2082U, 0xC1F2FFU, 0x88696CU, 0xB358A1U, 0xFA9752U, 0xAD844FU, 0xA63CB4U, 0xFFEF60U, + 0xF5F4EBU, 0x8C059EU, 0xC71F45U, 0xDCACF0U, 0x95772BU, 0x4E6622U, 0x67CDD5U, 0x3D9F0CU, 0x3406BBU, 0x6F75F2U, + 0x24EE0DU, 0x3D7E9CU, 0x520542U, 0x4396B3U, 0x09ADBCU, 0x527C45U, 0x5BF292U, 0xA0810BU, 0xE91878U, 0xF20BB5U, + 0xB9F10EU, 0xA1E0DBU, 0xEA33C0U, 0x938835U, 0x989BFEU, 0xC36342U, 0xCA6011U, 0x95FBECU, 0xFD0A6FU, 0x6E11B2U, + 0x25C3C1U, 0x3CFA5CU, 0x7769A7U, 0x0EB266U, 0x058079U, 0x5E1988U, 0x167E17U, 0x0DE5EFU, 0x44B428U, 0x7F0E31U, + 0x349DC6U, 0xEDC41FU, 0xE277A0U, 0xBA6DE1U, 0x99BE1EU, 0xC2178FU, 0x8B4450U, 0x90FF39U, 0xD9EFAAU, 0x823457U, + 0xA88785U, 0xF1DE98U, 0xFA4D73U, 0x3377E6U, 0x68A41DU, 0x43AD48U, 0x1A1AD3U, 0x14C836U, 0x4DF1EDU, 0x0622D0U, + 0x173903U, 0x7C88FEU, 0x27527DU, 0x2E41A5U, 0xF4FADAU, 0xFDBB4BU, 0x8601A4U, 0xCDD235U, 0xD4CB6AU, 0x9F7893U, + 0x862304U, 0xCCB3EDU, 0xB388BAU, 0xBA5B23U, 0xE1C0DCU, 0xE8A00DU, 0x3B3F27U, 0x500CF2U, 0x48D509U, 0x034694U, + 0x5A3CC7U, 0x51AD6AU, 0x0AB6B9U, 0x234544U, 0x785E57U, 0x30DE9AU, 0x2B2561U, 0x6036F4U, 0xDDCF8FU, 0x96DD5BU, + 0xCF46D0U, 0xCCB729U, 0x96A4FEU, 0xDF3FC7U, 0xE44D10U, 0xADC4F9U, 0xB61366U, 0xFD2837U, 0xA4B888U, 0x8EC359U, + 0x5750B6U, 0x5C49AFU, 0x07BA79U, 0x4A2080U, 0x517307U, 0x38DA7EU, 0x62C9ADU, 0x611230U, 0x38A2CBU, 0x33F98EU, + 0x4A4A35U, 0x0153E0U, 0x98815BU, 0xD23A06U, 0xD929C5U, 0x80E079U, 0xEBD7AAU, 0xF20D57U, 0xBD1C4CU, 0xE6A78DU, + 0xEF7472U, 0x954CE3U, 0x9CDF9CU, 0xCF8455U, 0x0437C2U, 0x1DFE3BU, 0x56EC6CU, 0x6F57D5U, 0x25061BU, 0x7E95AAU, + 0x772FF5U, 0x2C7C24U, 0x05C59BU, 0x5A965AU, 0x111D21U, 0x892DBCU, 0xC2F26FU, 0x9B6192U, 0xB81891U, 0xE38B6EU, + 0xEA91B6U, 0xB16221U, 0xF9FB48U, 0xC2C8DFU, 0x890226U, 0x9013F9U, 0xDBE848U, 0x02FB07U, 0x0D62D6U, 0x77906DU, + 0x3E8BB0U, 0x2538C3U, 0x6C614EU, 0x77F39CU, 0x141861U, 0x4D0D7AU, 0x47968FU, 0x1EE544U, 0x157DD1U, 0xCEEEAAU, + 0xA7953FU, 0xBC06D4U, 0xF57E09U, 0xABED3AU, 0xA2EEE3U, 0xD91734U, 0xD2849CU, 0x8BDEC3U, 0xC06F32U, 0xD174ADU, + 0x9BA77CU, 0x201C93U, 0x690C8AU, 0x22F77DU, 0x3BF4E4U, 0x702933U, 0x4B9B5AU, 0x0380C1U, 0x585134U, 0x556AEEU, + 0x0EF9CBU, 0x45A310U, 0x7C12CDU, 0xB7C97EU, 0xAFEA23U, 0xEC72C0U, 0xB7215DU, 0x9E9A8EU, 0xC50BF3U, 0xCC5068U, + 0x97E28DU, 0xDDB916U, 0xC42846U, 0xAF93B9U, 0xF2D020U, 0x796CC7U, 0x223F9EU, 0x2BA429U, 0x5095F0U, 0x18473FU, + 0x03DC8EU, 0x40EFD1U, 0x593620U, 0x1225BFU, 0x6BCF76U, 0x605E40U, 0xBA6599U, 0xF3B66AU, 0xE8AEF7U, 0x851DBCU, + 0x9EC649U, 0xD5D5D2U, 0x8C2C27U, 0x863E7CU, 0xDFB5D9U, 0xF4C002U, 0xA55BDFU, 0xEEE9ECU, 0x75B020U, 0x3C23D3U, + 0x06584AU, 0x4FCB15U, 0x1453A4U, 0x1F306BU, 0x42AB9AU, 0x09FA05U, 0x30415CU, 0x7A53ABU, 0x61AA22U, 0x2839D5U, + 0xF3228CU, 0xDAD032U, 0x89C9E3U, 0x820A2CU, 0xCAB91DU, 0x91A4C6U, 0x985673U, 0xE34DB8U, 0xA8DCE5U, 0xB52756U, + 0xFE358BU, 0xE6EE78U, 0x0DDF75U, 0x5654AFU, 0x5F075AU, 0x04BFC1U, 0x0D2CB4U, 0x56577FU, 0x34C6C2U, 0x2D9D11U, + 0x662F48U, 0x3FB4FFU, 0x34E536U, 0x4F4E89U, 0xC61C58U, 0x988107U, 0xD132A7U, 0xCA6978U, 0x81D881U, 0xB8C296U, + 0xF3114FU, 0xAA2AA8U, 0xA0FB31U, 0xF37142U, 0xDA429FU, 0x819B24U, 0x4888E1U, 0x5333FAU, 0x1AE30FU, 0x40D0D5U, + 0x6F0B68U, 0x36182BU, 0x3DA0F6U, 0x646345U, 0x2F7898U, 0x14CDF3U, 0x5C9666U, 0xC704BDU, 0x8E7F4CU, 0xDDEED3U, + 0xD655BAU, 0xAF062DU, 0xE49EF5U, 0xFDFD02U, 0xB7661BU, 0xA8F7F4U, 0xC18D25U, 0x9A1E9AU, 0x9305CBU, 0x48F414U, + 0x43EFB5U, 0x1B1D6AU, 0x708413U, 0x698780U, 0x2A7C4DU, 0x6168BFU, 0x78F3A2U, 0x130059U, 0x0B1BCCU, 0x40CA07U, + 0x1FF072U, 0x9663E9U, 0xCD9A14U, 0xE499C7U, 0xBF0AEAU, 0xF57239U, 0xECE1E4U, 0xA7BA5FU, 0xDE098FU, 0xD591E0U, + 0x86E271U, 0x8F79AEU, 0xD52817U, 0x1C8350U, 0x2711A9U, 0x684C3EU, 0x71FFE7U, 0x3AE490U, 0x633619U, 0x498FE6U, + 0x10DC37U, 0x1B670DU, 0x4066D8U, 0x09BC13U, 0x328FAEU, 0xFB16FDU, 0xA9C500U, 0xA2FF93U, 0xFB2C5EU, 0xF03565U, + 0x8D86B0U, 0xC65D4BU, 0xDD7DCEU, 0x95E615U, 0x8EB169U, 0xE708FAU, 0xBCDB03U, 0x37C1C4U, 0x6E72FDU, 0x25232AU, + 0x3DB8F3U, 0x5ECA4CU, 0x45430DU, 0x0CF0B2U, 0x57AB61U, 0x5E3ABCU, 0x210087U, 0x2BD343U, 0xF248B8U, 0xB9392DU, + 0xA0A376U, 0xEBB09FU, 0x905908U, 0x99CAF1U, 0xD3F5A6U, 0xCA251FU, 0x813ED0U, 0xF2CD01U, 0xFBD63EU, 0xA046EEU, + 0x29BD51U, 0x76AE98U, 0x3C274FU, 0x055476U, 0x4ECEA5U, 0x573F58U, 0x1C24DBU, 0x47B786U, 0x6ECC7DU, 0x345CE8U, + 0x7D0703U, 0x66B456U, 0xAF3DECU, 0xBC6F31U, 0xD7D0A2U, 0x8EC1CFU, 0x80321CU, 0xD9A9A1U, 0xD2FB7AU, 0xA9422BU, + 0xE05184U, 0xFB8A55U, 0xB22AAAU, 0xE831B3U, 0x63E264U, 0x1ADB8CU, 0x11081BU, 0x4832E2U, 0x0BA1BDU, 0x10781CU, + 0x784BC3U, 0x679052U, 0x2E902DU, 0x752BFCU, 0x7EFC57U, 0x27C58AU, 0xCC57D9U, 0xD40C64U, 0x9FBFB6U, 0x84665BU, + 0xCD7540U, 0xB6CF95U, 0xBF8E6EU, 0xE415FBU, 0xE62690U, 0xBFFE0DU, 0xF04DFEU, 0xC91623U, 0x028520U, 0x19BCD9U, + 0x506E06U, 0x0AEDB6U, 0x23D4E9U, 0x780728U, 0x331997U, 0x3AE84EU, 0x6173B9U, 0x6840A0U, 0x129B67U, 0x598B9EU, + 0xC87009U, 0x877370U, 0x9EEAEBU, 0xF5190EU, 0xAC03D4U, 0xA690C1U, 0xFDE93AU, 0xB47AF7U, 0xAF8044U, 0xC69119U, + 0xDD0ACAU, 0x166977U, 0x4EF0BCU, 0x45E2C9U, 0x3C1D52U, 0x3F8E87U, 0x64D73CU, 0x296574U, 0x327E83U, 0x7A8F1AU, + 0x0114EDU, 0x0A1734U, 0x53EF3BU, 0xD8FCCAU, 0x812715U, 0xEA94A4U, 0xF185EBU, 0xB95F3AU, 0xA26C85U, 0xEBB55CU, + 0xB0862AU, 0x930CA3U, 0xCEDD70U, 0x85E6CDU, 0x9D7196U, 0x562A63U, 0x6D9AE8U, 0x24411DU, 0x7F5246U, 0x76EBDBU, + 0x2DB928U, 0x2712E5U, 0x5E83D7U, 0x15D80AU, 0x0C6BD1U, 0x473170U, 0x54A02FU, 0xB99B9EU, 0xE34841U, 0xEAD090U, + 0xB1E33FU, 0xFA2866U, 0xE31991U, 0x88C208U, 0x8154FFU, 0xDB6FB7U, 0x92BE28U, 0x89A5D9U, 0xE25606U, 0x7BCE37U, + 0x30FDFCU, 0x693E21U, 0x6F2792U, 0x3495CFU, 0x5DCE6CU, 0x465DB1U, 0x0FA46AU, 0x14B75FU, 0x5F2D85U, 0x275C60U, + 0x2CC7FBU, 0xF56486U, 0xFE3C55U, 0xA5ABC8U, 0xECD02BU, 0xD743F2U, 0x9FDAC5U, 0xC0A81CU, 0xC33383U, 0x9A2262U, + 0xB1D93DU, 0xE8DA8DU, 0x232252U, 0x39B19BU, 0x70AAACU, 0x6B5975U, 0x024182U, 0x59921BU, 0x522974U, 0x0B38A5U, + 0x01F33EU, 0x78C1CBU, 0x3758D0U, 0x242F3DU, 0xEDB4EFU, 0xB66672U, 0xBF5701U, 0xC5CCDCU, 0xCE9F77U, 0x9726A2U, + 0xDCA4F9U, 0xC5FF4CU, 0xAE4E87U, 0xB51576U, 0xFDA7E9U, 0xA63C90U, 0x2F6D47U, 0x74D6CFU, 0x1BC538U, 0x0A1D21U, + 0x413EDEU, 0x58E50FU, 0x127480U, 0x6B4BF1U, 0x60992EU, 0x2BA297U, 0x327340U, 0x79E809U, 0xA0DABAU, 0x8A0367U, + 0xD1009DU, 0x98BB98U, 0x836A63U, 0xCE70F6U, 0xF5832DU, 0xB69850U, 0xEE29D3U, 0xE5732EU, 0xBCE0FDU, 0xB75962U, + 0x4C1A13U, 0x0589DCU, 0x1EF165U, 0x5666B7U, 0x4DFDEAU, 0x268E59U, 0x7F1794U, 0x74256FU, 0x29FE7AU, 0x626F81U, + 0x700404U, 0x1996DFU, 0x828FA2U, 0xCB7C31U, 0x9067CCU, 0x9B940EU, 0xE20C17U, 0xE81FE8U, 0xB1E439U, 0xFAF586U, + 0xE17FC7U, 0xA88C18U, 0xD397A1U, 0x5E4276U, 0x04794FU, 0x0FEB88U, 0x5E9271U, 0x3501E6U, 0x2C9A3EU, 0x67EA51U, + 0x7C61C0U, 0x34323BU, 0x6F89EEU, 0x4618F5U, 0x1D4218U, 0xD4F1CBU, 0xCFE876U, 0x841B25U, 0xB888F8U, 0xF3D053U, + 0xAA7386U, 0xA168BCU, 0xF2BB69U, 0xFB8792U, 0x80541FU, 0xC8CF4CU, 0xC3FEB5U, 0x182522U, 0x1117CBU, 0x6A9E9CU, + 0x234D05U, 0x3876FAU, 0x72A42BU, 0x2FBD84U, 0x240ED4U, 0x5DD54BU, 0x56C4B2U, 0x057E65U, 0x4C2D4CU, 0xD7849BU, + 0xBFD762U, 0xA44DF9U, 0xEFFEACU, 0xB6A347U, 0xBD30D2U, 0xC40B29U, 0x8FDB74U, 0x9540E6U, 0xDC330BU, 0xC3BAD8U, + 0x8A89E5U, 0x71533EU, 0x7AC0BBU, 0x2BB140U, 0x212A11U, 0x7838AEU, 0x13C17FU, 0x08D290U, 0x414989U, 0x1AA85EU, + 0x13B2A6U, 0x494131U, 0x625AD8U, 0xBBCF87U, 0xF43516U, 0xED26E9U, 0xA6BF78U, 0x9FCC17U, 0xDD57CEU, 0x86B75DU, + 0x8FACA0U, 0xD43FE3U, 0x9D445EU, 0xA6D584U, 0x6DCF71U, 0x753C6AU, 0x3EA5AFU, 0x67F654U, 0x4C4CC9U, 0x134DBAU, + 0x1AB667U, 0x4125E4U, 0x097E19U, 0x12CA0AU, 0x71D1F3U, 0x78022CU, 0xA33BACU, 0xEAA953U, 0xF17A02U, 0x9B53BDU, + 0xC28074U, 0xC9BB83U, 0x90299AU, 0x9BF04DU, 0xC4C3B4U, 0xAD583BU, 0xB7084AU, 0xFEB3D1U, 0x656004U, 0x2E69FEU, + 0x5FDAF3U, 0x548000U, 0x0D37DDU, 0x472E4EU, 0x5CFD33U, 0x1546F8U, 0x2E164DU, 0x678D96U, 0x3CBEE3U, 0x337768U, + 0xEBE5BDU, 0xC09E47U, 0x990D5EU, 0xD234A9U, 0xC9E720U, 0x887DF7U, 0xD34C0EU, 0xFB9711U, 0xA084E0U, 0xA96C2FU, + 0xF27FBEU, 0xB9E4C1U, 0x001318U, 0x4B02AFU, 0x56B867U, 0x1CEB30U, 0x477289U, 0x4E8152U, 0x358AF7U, 0x3C1AACU, + 0x676159U, 0x24F2C2U, 0x3C6917U, 0x57197CU, 0x8E82E1U, 0x85F112U, 0xDE68CFU, 0xD77BDDU, 0x8C9130U, 0xE400EBU, + 0xFB5B5EU, 0xB0E885U, 0xA9F6D4U, 0xE2277BU, 0x9B9CA2U, 0x108F15U, 0x5A764CU, 0x0B64ABU, 0x00AF32U, 0x599CEDU, + 0x72059DU, 0x29D702U, 0x60ECE3U, 0x7A7D3CU, 0x330625U, 0x0C95D6U, 0x474D0BU, 0x9E7EA8U, 0x95FDF5U, 0xCCA666U, + 0x86179BU, 0xBD8D40U, 0xFCDA65U, 0xE763BFU, 0xAE304AU, 0xF58AD1U, 0xDE9B9CU, 0x86406FU, 0x8DE3F2U, 0x54B801U, + 0x1B28D8U, 0x0213D7U, 0x69C026U, 0x7259B9U, 0x3A6B48U, 0x61B017U, 0x68819FU, 0x135A68U, 0x50D9B1U, 0x49E386U, + 0x02325FU, 0x9A29B0U, 0xD19E23U, 0xAAC77EU, 0xA3558DU, 0xFCAE04U, 0xF5BFF3U, 0xAE04AAU, 0xC44635U, 0xDDDDC5U, + 0x966C4AU, 0xCF373BU, 0xC4A4E4U, 0x1FD47DU, 0x3E4F8AU, 0x64DC43U, 0x2DA574U, 0x3637ADU, 0x7D5C56U, 0x44CFC3U, + 0x0BD688U, 0x52257DU, 0x59BBE7U, 0x03AA1AU, 0x4A5119U, 0xF142C4U, 0xB89A37U, 0xB329AAU, 0xE822D1U, 0xA9D114U, + 0x93C88FU, 0xDA5A7AU, 0xC1A121U, 0x8AB090U, 0xD36B5EU, 0xDC58A7U, 0xA5C0B0U, 0x2F8369U, 0x74389EU, 0x3DAB17U, + 0x26D368U, 0x4F40F9U, 0x141F26U, 0x1DAEC7U, 0x473558U, 0x446721U, 0x1DDEF6U, 0x769D6EU, 0xEF0E8DU, 0xA434D0U, + 0xBFE56BU, 0xF35EBEU, 0x884D45U, 0x819440U, 0xDAA69BU, 0x917D26U, 0x88ECF5U, 0xC3C788U, 0xFB150BU, 0xB02ED6U, + 0x63BF24U, 0x6A6439U, 0x3153D2U, 0x188B03U, 0x43989CU, 0x0923EDU, 0x147232U, 0x5FF99BU, 0x060B4CU, 0x2D10B5U, + 0x76A1A2U, 0x7FFA7BU, 0xA568D4U, 0xECD104U, 0xD7827BU, 0x9C19EAU, 0x8D6831U, 0xC6E2DCU, 0x9F71CFU, 0x950A32U, + 0xEE9BE1U, 0xA3A16CU, 0xB8761FU, 0xF16FC2U, 0x6A9C79U, 0x010FACU, 0x491786U, 0x52F453U, 0x1BEF88U, 0x007C35U, + 0x4B8566U, 0x32978FU, 0x316C18U, 0x697DC1U, 0x62E6BEU, 0x3B142FU, 0xD40DC0U, 0xCFCE11U, 0x86F58EU, 0xDD66F6U, + 0xD53E31U, 0x8E8988U, 0xA5125FU, 0xFC6366U, 0xB7F9B9U, 0xAEAA78U, 0xE513C3U, 0xD69096U, 0x1ECB6DU, 0x4579F8U, + 0x4C6033U, 0x13B34EU, 0x5888DCU, 0x615821U, 0x2AE3F2U, 0x32F0FFU, 0x792B04U, 0x220A91U, 0x0B906AU, 0xD0432BU, + 0xD97294U, 0x82AD4DU, 0xC8BE9AU, 0xD90623U, 0xB2D564U, 0xEBEE9CU, 0xE02D03U, 0xBF35D2U, 0xB686ADU, 0xCCDD2CU, + 0x854CD3U, 0x1EF70AU, 0x55A51DU, 0x4C1CE4U, 0x074F67U, 0x7ED49AU, 0x7476C9U, 0x2F2F75U, 0x26BCBEU, 0x75876BU, + 0x1C5650U, 0x07C885U, 0x48BB7EU, 0x9022F3U, 0x9B11A0U, 0xC2CA5DU, 0xE9C8CEU, 0xA07133U, 0xFBA238U, 0xF0B9E9U, + 0xA84917U, 0x835286U, 0xDAC179U, 0x913830U, 0x822B87U, 0x4BD95EU, 0x30D289U, 0x3C43A0U, 0x67B87FU, 0x6CAA8EU, + 0x353311U, 0x7E4440U, 0x47DFABU, 0x0C8E3FU, 0x1634C4U, 0x5FA7D9U, 0x04CC0AU, 0xAD5DE7U, 0xF64774U, 0xBDB409U, + 0xAC2DD2U, 0xE67E67U, 0xFBC5ACU, 0x90D5F9U, 0xCB0E42U, 0xC23D9FU, 0x99B67DU, 0x9047E4U, 0xEA5DB3U, 0x218E0AU, + 0x38B7D5U, 0x732034U, 0x6AFA2BU, 0x21CBFAU, 0x5A1005U, 0x5B039CU, 0x01A8FBU, 0x4C7822U, 0x574395U, 0x3CD04DU, + 0xA5811AU, 0xEE3BB3U, 0xB76868U, 0xBDF19DU, 0xE64286U, 0xCF1943U, 0x949BF8U, 0xDDA225U, 0xC67156U, 0x8FCACBU, + 0xF59B08U, 0xF605F5U, 0x2B36EFU, 0x20EF1AU, 0x797CC1U, 0x324664U, 0x1985BFU, 0x419CE4U, 0x4A6F51U, 0x13748AU, + 0x58C42FU, 0x631F74U, 0x2A0CA1U, 0x71F51AU, 0xF9E7D7U, 0xA27CA5U, 0xA99F38U, 0xD886EBU, 0x973516U, 0x8E6F1DU, + 0xC5FEECU, 0xDF0133U, 0xB61282U, 0xED8ADDU, 0xE4F954U, 0xBF7AA3U, 0x74617AU, 0x6D904DU, 0x070A95U, 0x1E795AU, + 0x55E0EBU, 0x0EF334U, 0x0F0845U, 0x7098CAU, 0x798313U, 0x2360E0U, 0x687BFDU, 0x71AB0EU, 0xBA10C3U, 0x830370U, + 0xC8FA2DU, 0x93EDB7U, 0x9B3742U, 0xC00689U, 0xA99DBCU, 0xB25E67U, 0xF964BAU, 0xE0F509U, 0xA7AE44U, 0xFF1DB7U, + 0x54C42EU, 0x0DF6F1U, 0x066D90U, 0x5D3C0EU, 0x1487FFU, 0x2F8460U, 0x675E19U, 0x3CEFDEU, 0x37B447U, 0x6E27B0U, + 0x651369U, 0x9CC856U, 0xD77B97U, 0xC9604CU, 0x88B1F9U, 0x939BA2U, 0xFA4856U, 0xB1D1DDU, 0xAAE200U, 0xE33873U, + 0xB829EEU, 0xB0D20DU, 0xCBC190U, 0x407AEBU, 0x19AA3EU, 0x52A1A5U, 0x4B1240U, 0x204B1BU, 0x3ED9A2U, 0x7F2274U, + 0x2437ADU, 0x2DAC8AU, 0x76DF53U, 0x5D45ACU, 0x04F43DU, 0xCEBFE2U, 0xD72CC3U, 0x9C551CU, 0xE7C7E5U, 0xEEDC72U, + 0xB52D1BU, 0xBCB6CCU, 0xE6A454U, 0xA95FA7U, 0x904EFAU, 0xD3A551U, 0xCA3684U, 0x01265FU, 0x5ADD6AU, 0x72CEB1U, + 0x29135CU, 0x60A1CFU, 0x7BBA92U, 0x304921U, 0x2950FCU, 0x42D316U, 0x1AA903U, 0x1138F8U, 0x48E329U, 0xC7D0A6U, + 0xBC48DFU, 0xFD1B08U, 0xE6A0B1U, 0xAE3366U, 0xF55AAFU, 0xFEC898U, 0x879341U, 0x8C22FEU, 0xD5392EU, 0x9EEA61U, + 0x8456D0U, 0x6D450BU, 0x769EF6U, 0x3FADE5U, 0x606508U, 0x6BD6DBU, 0x3ACD46U, 0x101C3DU, 0x5927F8U, 0x02F543U, + 0x096C96U, 0x505FCCU, 0xBB8C71U, 0xA296B2U, 0xE8370FU, 0xF36C5CU, 0xBADF85U, 0xE1063AU, 0xC814FBU, 0x97AF04U, + 0x9CFA15U, 0xC461EAU, 0x87D23BU, 0xBE88B4U, 0x7509CCU, 0x2E721BU, 0x27E1A2U, 0x7C5965U, 0x750A7CU, 0x0F9183U, + 0x44A052U, 0x5D7BE9U, 0x1669ACU, 0x0F9277U, 0x6013CAU, 0x3B0819U, 0xB3FA65U, 0xE0E3E6U, 0xA9103BU, 0xB28BC0U, + 0xDB9ED5U, 0xC0642EU, 0x8B77EBU, 0xD3EC50U, 0xD80D89U, 0xA1179EU, 0xAAC477U, 0xF1F5A0U, 0x386E19U, 0x271D4FU, + 0x6F8596U, 0x541639U, 0x1F6DE8U, 0x4EFE97U, 0x45B706U, 0x1C05D9U, 0x779E30U, 0x6DCF27U, 0x2474DEU, 0x3F664DU, + 0xF69BB0U, 0xAD08FBU, 0x86536FU, 0xDFE094U, 0xD1E841U, 0x883B6AU, 0xC300B7U, 0xE8D164U, 0xB16BD9U, 0xF2788AU, + 0xEBA167U, 0xA192FCU, 0x3A0929U, 0x53DBD2U, 0x08F2C3U, 0x01212DU, 0x5A3ABCU, 0x518B43U, 0x29D11AU, 0x62628DU, + 0x7FFD64U, 0x34ACB3U, 0x6F1E8AU, 0xE64555U, 0x95C494U, 0x9D7F2BU, 0xC62C7AU, 0x8DB485U, 0x94871DU, 0xFF5CDEU, + 0xE6EFE3U, 0xADB730U, 0xF524CFU, 0xFE0F56U, 0xA5DE31U, 0x48C5E8U, 0x53377FU, 0x1AAE86U, 0x01BD59U, 0x4B4678U, + 0x3A50A7U, 0x31E977U, 0x683ACCU, 0x633189U, 0x38C072U, 0x71DAEFU, 0x4B493CU, 0x82B001U, 0x99A3C2U, 0xD2383FU, + 0x8F4AA4U, 0xA4D3D1U, 0xFDA00AU, 0xB62B8FU, 0xACBB75U, 0xE5C028U, 0xF6539BU, 0x9F4242U, 0xC4B985U, 0x4F2FBCU, + 0x167463U, 0x1CC5D2U, 0x65DE1DU, 0x2E3C4CU, 0x35A5F3U, 0x78F622U, 0x234DDDU, 0x0A5C55U, 0x408622U, 0x5BB5FBU, + 0x122E6CU, 0xC1FF95U, 0xC8C4DEU, 0xB3066BU, 0xB83FB0U, 0xE0AC25U, 0xAB775EU, 0xB24793U, 0xD9DC20U, 0x828BFDU, + 0x8F30AFU, 0xD46102U, 0xDCDBD9U, 0x07582CU, 0x6E0137U, 0x75B2C6U, 0x3EE809U, 0x2F7990U, 0x64C2E7U, 0x1C913EU, + 0x170A89U, 0x4C3A40U, 0x45E9D6U, 0x1E42AFU, 0x571370U, 0xE889C1U, 0xA2BA0EU, 0xFB635FU, 0xF070E0U, 0xA9CF39U, + 0x821DDAU, 0xD904C7U, 0x90F734U, 0x82FCE9U, 0xCB4D72U, 0xD09716U, 0x3B848DU, 0x623D78U, 0x696EA3U, 0x30F4BEU, + 0x7A075DU, 0x451E80U, 0x0C8D33U, 0x17E66EU, 0x5E76B5U, 0x050D14U, 0x0E9ECBU, 0x7607BAU, 0xF57524U, 0xACEAC5U, + 0xE7F91AU, 0xFC0083U, 0x9583F4U, 0xCED96DU, 0xC6688AU, 0x9D7353U, 0x92804CU, 0xCB11BDU, 0xA00B62U, 0xA9F8C3U, + 0x72E398U, 0x783244U, 0x2118F7U, 0x4A8B2AU, 0x5B5249U, 0x1061D4U, 0x09FA2FU, 0x428ABAU, 0x1911F1U, 0x31C604U, + 0x6AFD9FU, 0x276D62U, 0xBC2631U, 0xF795B8U, 0xCE4C4EU, 0x855F97U, 0xDDE520U, 0xD6B479U, 0x8D0FB6U, 0x8C1C07U, + 0xF7C6D8U, 0xBE77A9U, 0xA53C36U, 0xEFAFDFU, 0x369648U, 0x1D4411U, 0x40DFE6U, 0x4BEE7EU, 0x103595U, 0x5902C0U, + 0x43D85BU, 0x2AC9AEU, 0x316265U, 0x7AB158U, 0x23A18BU, 0x201A56U, 0xD949E5U, 0x93F2A8U, 0x882313U, 0xC139C6U, + 0xDA8A3CU, 0x97D329U, 0xEC50E2U, 0xE7AA13U, 0xBFBB8CU, 0xB42075U, 0xED5322U, 0x06C8ABU, 0x1DF85CU, 0x542785U, + 0x0FB4BAU, 0x0FCD7BU, 0x544FA4U, 0x7F5414U, 0x26A54BU, 0x6D3EF2U, 0x702D31U, 0x3BD7CCU, 0x13C6DFU, 0xC83D02U, + 0x83AEF9U, 0x9AB77CU, 0xD15507U, 0xC84ED2U, 0xA3DF49U, 0xF9A4BDU, 0xF836F6U, 0xA3ED4BU, 0xEADC98U, 0xD14B05U, + 0x9A30E6U, 0x03A0BFU, 0x4D6B00U, 0x1458D1U, 0x1FC12EU, 0x64932FU, 0x6D28F0U, 0x36BB09U, 0x7FE29FU, 0x6551E6U, + 0x0E0B21U, 0x57AAB8U, 0x54B147U, 0x8D6216U, 0x86DBA9U, 0xDDC968U, 0xB412F3U, 0xAA218EU, 0xE3FC5DU, 0xF86EF0U, + 0xB35523U, 0xCA945FU, 0xC1AFCCU, 0x983C11U, 0xD264FAU, 0x49D7EFU, 0x000C14U, 0x3B1FC1U, 0x7AA75AU, 0x21F4B7U, + 0x2A6FA4U, 0x728E5DU, 0x5D958AU, 0x042713U, 0x4F767DU, 0x54EDACU, 0x1D5E13U, 0x8604C0U, 0xEE91ADU, 0xB5EA36U, + 0xBC79E3U, 0xE77018U, 0xAC820DU, 0x9D19E6U, 0xD6283FU, 0xCEF3A8U, 0x85E0D1U, 0xDA1A47U, 0x538BAEU, 0x389079U, + 0x216360U, 0x6A6B9FU, 0x30D84EU, 0x3903E1U, 0x421230U, 0x0BE94FU, 0x10FBD6U, 0x5B6011U, 0x4215E8U, 0x008EFBU, + 0xF95C07U, 0xF2759CU, 0xADE659U, 0xA49D22U, 0xFF0CB7U, 0x96964CU, 0x8CE591U, 0xC77E92U, 0x9E2F6FU, 0x959CBCU, + 0xCC0601U, 0xE7475AU, 0x3CFCBFU, 0x74EF25U, 0x6717F4U, 0x2E048BU, 0x15DF0AU, 0x5A6CF5U, 0x03716CU, 0x08A33BU, + 0x5098C2U, 0x5B1945U, 0x20C2BCU, 0x69F063U, 0xF22972U, 0xBB1A8DU, 0xE0814DU, 0xCA52F6U, 0x936AABU, 0x98B958U, + 0xC9A2C5U, 0x820306U, 0x9B593BU, 0xF4CAE0U, 0xEE7315U, 0xA7209EU, 0x7C9BCBU, 0x75C930U, 0x0E54A4U, 0x45E75FU, + 0x5CBC12U, 0x173D81U, 0x0F0778U, 0x44D4AFU, 0x3FC596U, 0x363E59U, 0x65ACE8U, 0x6C9737U, 0xA346E6U, 0xD95DD9U, + 0xD0FE10U, 0x8B26E6U, 0xC2357FU, 0xD9CE28U, 0x92DDC1U, 0xAB455EU, 0xE1B6AFU, 0xB8ADF4U, 0xB35861U, 0x68438AU, + 0x41C157U, 0x12B864U, 0x5B2BB9U, 0x45B00AU, 0x0EC3C6U, 0x175B95U, 0x7C2828U, 0x25B3F3U, 0x2E2206U, 0x75580DU, + 0x3DDBD8U, 0x86C223U, 0xCF31BAU, 0xD4AADDU, 0x9FF804U, 0xC64193U, 0xCD526AU, 0xBDA9F4U, 0xB2BD95U, 0xE92E4AU, + 0xA0C5FBU, 0xBBD424U, 0xD20F7DU, 0x093DDAU, 0x01A603U, 0x5A77F0U, 0x514CEDU, 0x089E36U, 0x63A7D3U, 0x7A3448U, + 0x31FF3CU, 0x2BCEE7U, 0x625462U, 0x150799U, 0x1CBC84U, 0xC7ED77U, 0x8C76AAU, 0x95C409U, 0xDF9954U, 0xE62A8FU, + 0xAD213EU, 0xF6F1E1U, 0xFF4A00U, 0xA4191EU, 0x8D82C7U, 0xD7B330U, 0x9C69A9U, 0x057ACEU, 0x42C357U, 0x2B1088U, + 0x303A79U, 0x7BEB76U, 0x63F087U, 0x284358U, 0x7198E1U, 0x5A88B2U, 0x017B7EU, 0x0860CDU, 0x53F510U, 0x9A0F63U, + 0xA00CFEU, 0xEBB535U, 0xF2E6C0U, 0xB97DDBU, 0xEC0F2EU, 0xE796B5U, 0x9C0578U, 0xD47E0BU, 0xCFEF92U, 0x86F564U, + 0x1D16ADU, 0x768F32U, 0x2FFC43U, 0x24669CU, 0x7C752DU, 0x778CE2U, 0x2E1F9BU, 0x45000CU, 0x5EF0D5U, 0x13FB62U, + 0x40282BU, 0x4811D4U, 0xB38344U, 0xB8789FU, 0xE16BEAU, 0xAAB261U, 0xB38194U, 0xF81B4FU, 0xC2CA52U, 0x8BE1B1U, + 0xD0726CU, 0xD903DFU, 0x829982U, 0xE94A79U, 0x7471FDU, 0x36E026U, 0x2FBA93U, 0x640DC8U, 0x3F1431U, 0x16D7B6U, + 0x4D6C6FU, 0x443C18U, 0x1E8781U, 0x55947EU, 0x6C4FBFU, 0x27FFA0U, 0xBEE451U, 0xF5378FU, 0xAE0E2EU, 0xA2CD71U, + 0xC9D7C8U, 0x98661FU, 0x93BDC6U, 0xC88EE5U, 0xC15438U, 0xBA45C3U, 0xF2FE56U, 0xE9290DU, 0x2230E8U, 0x3B9273U, + 0x70C98FU, 0x0958DCU, 0x02A343U, 0x58B0A2U, 0x150A7DU, 0x0E5BC4U, 0x6FC897U, 0x74F33AU, 0x3F23E9U, 0x66A834U, + 0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U, + 0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U }; @@ -1682,1776 +1674,1589 @@ typedef unsigned char tambevoice[6]; #define interleaveambe12(bp) { bp+=12; if (bp>71) bp -= 71; } -static void ambefec_deinterleave(tambevoicefec result, const tambevoicefec voice) +static void ambefec_deinterleave(tambevoicefec result, const tambevoicefec voice) { - U32 bitpos, bytcnt; - memset(result, 0, sizeof(tambevoicefec)); // init result - bitpos = 0; - for (bytcnt = 0; bytcnt < sizeof(tambevoicefec); bytcnt++) - { - char voice_dsr = voice[bytcnt]; - if (voice_dsr & 0x80) result[bitpos>>3] |= (0x80 >> (bitpos&7)); - interleaveambe12(bitpos); - if (voice_dsr & 0x40) result[bitpos>>3] |= (0x80 >> (bitpos&7)); - interleaveambe12(bitpos); - if (voice_dsr & 0x20) result[bitpos>>3] |= (0x80 >> (bitpos&7)); - interleaveambe12(bitpos); - if (voice_dsr & 0x10) result[bitpos>>3] |= (0x80 >> (bitpos&7)); - interleaveambe12(bitpos); - if (voice_dsr & 0x08) result[bitpos>>3] |= (0x80 >> (bitpos&7)); - interleaveambe12(bitpos); - if (voice_dsr & 0x04) result[bitpos>>3] |= (0x80 >> (bitpos&7)); - interleaveambe12(bitpos); - if (voice_dsr & 0x02) result[bitpos>>3] |= (0x80 >> (bitpos&7)); - interleaveambe12(bitpos); - if (voice_dsr & 0x01) result[bitpos>>3] |= (0x80 >> (bitpos&7)); - interleaveambe12(bitpos); - } // rof + U32 bitpos, bytcnt; + memset(result, 0, sizeof(tambevoicefec)); // init result + bitpos = 0; + for (bytcnt = 0; bytcnt < sizeof(tambevoicefec); bytcnt++) { + char voice_dsr = voice[bytcnt]; + if (voice_dsr & 0x80) result[bitpos>>3] |= (0x80 >> (bitpos&7)); + interleaveambe12(bitpos); + if (voice_dsr & 0x40) result[bitpos>>3] |= (0x80 >> (bitpos&7)); + interleaveambe12(bitpos); + if (voice_dsr & 0x20) result[bitpos>>3] |= (0x80 >> (bitpos&7)); + interleaveambe12(bitpos); + if (voice_dsr & 0x10) result[bitpos>>3] |= (0x80 >> (bitpos&7)); + interleaveambe12(bitpos); + if (voice_dsr & 0x08) result[bitpos>>3] |= (0x80 >> (bitpos&7)); + interleaveambe12(bitpos); + if (voice_dsr & 0x04) result[bitpos>>3] |= (0x80 >> (bitpos&7)); + interleaveambe12(bitpos); + if (voice_dsr & 0x02) result[bitpos>>3] |= (0x80 >> (bitpos&7)); + interleaveambe12(bitpos); + if (voice_dsr & 0x01) result[bitpos>>3] |= (0x80 >> (bitpos&7)); + interleaveambe12(bitpos); + } // rof } -static void ambefec_interleave(tambevoicefec result, const tambevoicefec raw_voice) +static void ambefec_interleave(tambevoicefec result, const tambevoicefec raw_voice) { - U32 bitpos, bytcnt; - bitpos = 0; - for (bytcnt = 0; bytcnt < sizeof(tambevoicefec); bytcnt++) - { - char voice_dsr = (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7)))?0x80:0x00; - interleaveambe12(bitpos); - if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x40; - interleaveambe12(bitpos); - if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x20; - interleaveambe12(bitpos); - if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x10; - interleaveambe12(bitpos); - if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x08; - interleaveambe12(bitpos); - if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x04; - interleaveambe12(bitpos); - if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x02; - interleaveambe12(bitpos); - if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x01; - interleaveambe12(bitpos); - result[bytcnt] = voice_dsr; - } // rof + U32 bitpos, bytcnt; + bitpos = 0; + for (bytcnt = 0; bytcnt < sizeof(tambevoicefec); bytcnt++) { + char voice_dsr = (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7)))?0x80:0x00; + interleaveambe12(bitpos); + if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x40; + interleaveambe12(bitpos); + if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x20; + interleaveambe12(bitpos); + if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x10; + interleaveambe12(bitpos); + if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x08; + interleaveambe12(bitpos); + if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x04; + interleaveambe12(bitpos); + if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x02; + interleaveambe12(bitpos); + if (raw_voice[bitpos>>3] & (0x80 >> (bitpos&7))) voice_dsr |= 0x01; + interleaveambe12(bitpos); + result[bytcnt] = voice_dsr; + } // rof } -void ambefec_regenerate(tambevoicefec voice) +void ambefec_regenerate(tambevoicefec voice) { - tambevoicefec decoded; - U32 data, datb, encoded_dat; - ambefec_deinterleave(decoded, voice); - data = gorlay_decode24128((decoded[0]<<16) | (decoded[1]<<8) | decoded[2]); - encoded_dat = gorlay_encode24128(data); - decoded[0] = (encoded_dat>>16) & 0xff; - decoded[1] = (encoded_dat>>8) & 0xff; - decoded[2] = encoded_dat & 0xff; - data = PRNG_TABLE[data]; - datb = gorlay_decode24128(((decoded[3]<<16) | (decoded[4]<<8) | decoded[5])^data); - encoded_dat = gorlay_encode24128(datb)^data; - decoded[3] = (encoded_dat>>16) & 0xff; - decoded[4] = (encoded_dat>>8) & 0xff; - decoded[5] = encoded_dat & 0xff; - ambefec_interleave(voice, decoded); + tambevoicefec decoded; + U32 data, datb, encoded_dat; + ambefec_deinterleave(decoded, voice); + data = gorlay_decode24128((decoded[0]<<16) | (decoded[1]<<8) | decoded[2]); + encoded_dat = gorlay_encode24128(data); + decoded[0] = (encoded_dat>>16) & 0xff; + decoded[1] = (encoded_dat>>8) & 0xff; + decoded[2] = encoded_dat & 0xff; + data = PRNG_TABLE[data]; + datb = gorlay_decode24128(((decoded[3]<<16) | (decoded[4]<<8) | decoded[5])^data); + encoded_dat = gorlay_encode24128(datb)^data; + decoded[3] = (encoded_dat>>16) & 0xff; + decoded[4] = (encoded_dat>>8) & 0xff; + decoded[5] = encoded_dat & 0xff; + ambefec_interleave(voice, decoded); } -static char silence[12] = -{ - 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8, - 0x70,0x4f,0x93 -}; - -static unsigned short crc_tabccitt[256] = -{ - 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, - 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, - 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, - 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, - 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, - 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, - 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, - 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, - 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, - 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, - 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, - 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, - 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, - 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, - 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, - 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, - 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, - 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, - 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, - 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, - 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, - 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, - 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, - 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, - 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, - 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, - 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, - 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, - 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, - 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, - 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, - 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 +static unsigned char silence[12] = { 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8,0x70,0x4f,0x93 }; + +static unsigned short crc_tabccitt[256] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 }; static void calcPFCS(unsigned char packet[58])//Netzwerk CRC { - unsigned short crc_dstar_ffff = 0xffff; - unsigned short tmp, short_c; - int i; - - for (i = 17; i < 56 ; i++) - { - short_c = 0x00ff & (unsigned short)packet[i]; - tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; - crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; - } - crc_dstar_ffff = ~crc_dstar_ffff; - tmp = crc_dstar_ffff; - - packet[56] = (unsigned char)(crc_dstar_ffff & 0xff); - packet[57] = (unsigned char)((tmp >> 8) & 0xff); - - return; + unsigned short crc_dstar_ffff = 0xffff; + unsigned short tmp, short_c; + int i; + + for (i = 17; i < 56 ; i++) { + short_c = 0x00ff & (unsigned short)packet[i]; + tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; + crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; + } + crc_dstar_ffff = ~crc_dstar_ffff; + tmp = crc_dstar_ffff; + + packet[56] = (unsigned char)(crc_dstar_ffff & 0xff); + packet[57] = (unsigned char)((tmp >> 8) & 0xff); + + return; } static int read_config(const char *cfgFile) { - short int valid_params = 21; - short int params = 0; - - FILE *cnf = NULL; - char inbuf[1024]; - char *p = NULL; - char *ptr; - unsigned short i; - - cnf = fopen(cfgFile, "r"); - if (!cnf) - { - logdata("Failed to open file %s\n", cfgFile); - return 1; - } - - logdata("Reading file %s\n", cfgFile); - while (fgets(inbuf, 1020, cnf) != NULL) - { - if (strchr(inbuf, '#')) - continue; - - p = strchr(inbuf, '\r'); - if (p) - *p = '\0'; - p = strchr(inbuf, '\n'); - if (p) - *p = '\0'; - - p = strchr(inbuf, '='); - if (!p) - continue; - *p = '\0'; - - if (strcmp(inbuf,"DVCALL") == 0) - { - memset(DVCALL,' ', sizeof(DVCALL)); - DVCALL[RPTR_SIZE] = '\0'; - - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if ((strlen(p + 1) < 1) || (strlen(p + 1) > (RPTR_SIZE - 2))) - logdata("DVCALL value [%s] invalid\n", p + 1); - else - { - memcpy(DVCALL, p + 1, strlen(p + 1)); - logdata("DVCALL=[%s]\n",DVCALL); - params ++; - } - } - else - if (strcmp(inbuf,"RPTR") == 0) - { - memset(RPTR,' ', sizeof(RPTR)); - RPTR[RPTR_SIZE] = '\0'; - - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if ((strlen(p + 1) < 1) || (strlen(p + 1) > (RPTR_SIZE - 2))) - logdata("RPTR value [%s] invalid\n", p + 1); - else - { - memcpy(RPTR, p + 1, strlen(p + 1)); - logdata("RPTR=[%s]\n",RPTR); - params ++; - } - } - else - if (strcmp(inbuf,"DVRPTR_SERIAL") == 0) - { - memset(DVRPTR_SERIAL, 0, sizeof(DVRPTR_SERIAL)); - strncpy(DVRPTR_SERIAL, p + 1, 11); - DVRPTR_SERIAL[11] = '\0'; - logdata("DVRPTR_SERIAL=[%s]\n",DVRPTR_SERIAL); - params ++; - } - else - if (strcmp(inbuf,"GATEWAY_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - logdata("GATEWAY_IP value [%s] invalid\n", p + 1); - else - { - strncpy(GATEWAY_IP, p + 1, IP_SIZE); - GATEWAY_IP[IP_SIZE] = '\0'; - logdata("GATEWAY_IP=[%s]\n", GATEWAY_IP); - params ++; - } - } - else - if (strcmp(inbuf,"DVRPTR_INTERNAL_PORT") == 0) - { - DVRPTR_INTERNAL_PORT = atoi(p + 1); - logdata("DVRPTR_INTERNAL_PORT=[%d]\n",DVRPTR_INTERNAL_PORT); - params ++; - } - else - if (strcmp(inbuf,"DVRPTR_INTERNAL_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - logdata("DVRPTR_INTERNAL_IP value [%s] invalid\n", p + 1); - else - { - strncpy(DVRPTR_INTERNAL_IP, p + 1, IP_SIZE); - DVRPTR_INTERNAL_IP[IP_SIZE] = '\0'; - logdata("DVRPTR_INTERNAL_IP=[%s]\n", DVRPTR_INTERNAL_IP); - params ++; - } - } - else - if (strcmp(inbuf,"GATEWAY_PORT") == 0) - { - GATEWAY_PORT = atoi(p + 1); - logdata("GATEWAY_PORT=[%d]\n",GATEWAY_PORT); - params ++; - } - else - if (strcmp(inbuf,"DVRPTR_MOD") == 0) - { - DVRPTR_MOD = *(p + 1); - - logdata("DVRPTR_MOD=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"INVALID_YRCALL_KEY") == 0) - { - memset(INVALID_YRCALL_KEY, 0, sizeof(INVALID_YRCALL_KEY)); - - if ( (strlen(p + 1) < 1) || (strlen(p + 1) > CALL_SIZE) ) - logdata("INVALID_YRCALL_KEY value [%s] invalid\n", p + 1); - else - { - memcpy(INVALID_YRCALL_KEY, p + 1, strlen(p + 1)); - - for (i = 0; i < strlen(INVALID_YRCALL_KEY); i++) - INVALID_YRCALL_KEY[i] = toupper(INVALID_YRCALL_KEY[i]); - - logdata("INVALID_YRCALL_KEY=[%s]\n",INVALID_YRCALL_KEY); - params ++; - } - } - else - if (strcmp(inbuf,"RF_AUDIO_Level") == 0) - { - RF_AUDIO_Level = atoi(p + 1); - if (RF_AUDIO_Level < 0) - RF_AUDIO_Level = 1; + short int valid_params = 21; + short int params = 0; + + FILE *cnf = NULL; + char inbuf[1024]; + char *p = NULL; + char *ptr; + unsigned short i; + + cnf = fopen(cfgFile, "r"); + if (!cnf) { + logdata("Failed to open file %s\n", cfgFile); + return 1; + } + + logdata("Reading file %s\n", cfgFile); + while (fgets(inbuf, 1020, cnf) != NULL) { + if (strchr(inbuf, '#')) + continue; + + p = strchr(inbuf, '\r'); + if (p) + *p = '\0'; + p = strchr(inbuf, '\n'); + if (p) + *p = '\0'; + + p = strchr(inbuf, '='); + if (!p) + continue; + *p = '\0'; + + if (strcmp(inbuf,"DVCALL") == 0) { + memset(DVCALL,' ', sizeof(DVCALL)); + DVCALL[RPTR_SIZE] = '\0'; + + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if ((strlen(p + 1) < 1) || (strlen(p + 1) > (RPTR_SIZE - 2))) + logdata("DVCALL value [%s] invalid\n", p + 1); + else { + memcpy(DVCALL, p + 1, strlen(p + 1)); + logdata("DVCALL=[%s]\n",DVCALL); + params ++; + } + } else if (strcmp(inbuf,"RPTR") == 0) { + memset(RPTR,' ', sizeof(RPTR)); + RPTR[RPTR_SIZE] = '\0'; + + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if ((strlen(p + 1) < 1) || (strlen(p + 1) > (RPTR_SIZE - 2))) + logdata("RPTR value [%s] invalid\n", p + 1); + else { + memcpy(RPTR, p + 1, strlen(p + 1)); + logdata("RPTR=[%s]\n",RPTR); + params ++; + } + } else if (strcmp(inbuf,"DVRPTR_SERIAL") == 0) { + memset(DVRPTR_SERIAL, 0, sizeof(DVRPTR_SERIAL)); + strncpy(DVRPTR_SERIAL, p + 1, 11); + DVRPTR_SERIAL[11] = '\0'; + logdata("DVRPTR_SERIAL=[%s]\n",DVRPTR_SERIAL); + params ++; + } else if (strcmp(inbuf,"GATEWAY_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + logdata("GATEWAY_IP value [%s] invalid\n", p + 1); + else { + strncpy(GATEWAY_IP, p + 1, IP_SIZE); + GATEWAY_IP[IP_SIZE] = '\0'; + logdata("GATEWAY_IP=[%s]\n", GATEWAY_IP); + params ++; + } + } else if (strcmp(inbuf,"DVRPTR_INTERNAL_PORT") == 0) { + DVRPTR_INTERNAL_PORT = atoi(p + 1); + logdata("DVRPTR_INTERNAL_PORT=[%d]\n",DVRPTR_INTERNAL_PORT); + params ++; + } else if (strcmp(inbuf,"DVRPTR_INTERNAL_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + logdata("DVRPTR_INTERNAL_IP value [%s] invalid\n", p + 1); + else { + strncpy(DVRPTR_INTERNAL_IP, p + 1, IP_SIZE); + DVRPTR_INTERNAL_IP[IP_SIZE] = '\0'; + logdata("DVRPTR_INTERNAL_IP=[%s]\n", DVRPTR_INTERNAL_IP); + params ++; + } + } else if (strcmp(inbuf,"GATEWAY_PORT") == 0) { + GATEWAY_PORT = atoi(p + 1); + logdata("GATEWAY_PORT=[%d]\n",GATEWAY_PORT); + params ++; + } else if (strcmp(inbuf,"DVRPTR_MOD") == 0) { + DVRPTR_MOD = *(p + 1); + + logdata("DVRPTR_MOD=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"INVALID_YRCALL_KEY") == 0) { + memset(INVALID_YRCALL_KEY, 0, sizeof(INVALID_YRCALL_KEY)); + + if ( (strlen(p + 1) < 1) || (strlen(p + 1) > CALL_SIZE) ) + logdata("INVALID_YRCALL_KEY value [%s] invalid\n", p + 1); + else { + memcpy(INVALID_YRCALL_KEY, p + 1, strlen(p + 1)); + + for (i = 0; i < strlen(INVALID_YRCALL_KEY); i++) + INVALID_YRCALL_KEY[i] = toupper(INVALID_YRCALL_KEY[i]); + + logdata("INVALID_YRCALL_KEY=[%s]\n",INVALID_YRCALL_KEY); + params ++; + } + } else if (strcmp(inbuf,"RF_AUDIO_Level") == 0) { + RF_AUDIO_Level = atoi(p + 1); + if (RF_AUDIO_Level < 0) + RF_AUDIO_Level = 1; Modem_Init2[7] = RF_AUDIO_Level; - logdata("RF_AUDIO_Level=[%d]\n",RF_AUDIO_Level); - params ++; - } - else - if (strcmp(inbuf,"DUPLEX") == 0) - { - if (*(p + 1) == 'Y') - DUPLEX = true; - else - DUPLEX = false; - logdata("DUPLEX=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"RPTR_ACK") == 0) - { - if (*(p + 1) == 'Y') - RPTR_ACK = true; - else - RPTR_ACK = false; - logdata("RPTR_ACK=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"ACK_DELAY") == 0) - { - ACK_DELAY = atol(p + 1); - if ((ACK_DELAY < 1) || (ACK_DELAY > 999)) - ACK_DELAY = 250; - logdata("ACK_DELAY=[%ld]\n", ACK_DELAY); - ACK_DELAY = ACK_DELAY * 1000; - params ++; - } - else - if (strcmp(inbuf,"DELAY_BETWEEN") == 0) - { - DELAY_BETWEEN = atoi(p + 1); - if (DELAY_BETWEEN < 10) - DELAY_BETWEEN = 16; - logdata("DELAY_BETWEEN=[%d]\n", DELAY_BETWEEN); - DELAY_BETWEEN = DELAY_BETWEEN * 1000; - params ++; - } - else - if (strcmp(inbuf,"RQST_COUNT") == 0) - { - RQST_COUNT = atoi(p + 1); - if (RQST_COUNT < 6) - RQST_COUNT = 6; - logdata("RQST_COUNT=[%d]\n",RQST_COUNT); - params ++; - } - else - if (strcmp(inbuf,"ENABLE_RF") == 0) - { - memset(ENABLE_RF,' ', sizeof(ENABLE_RF)); - ENABLE_RF[RPTR_SIZE] = '\0'; - - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) > RPTR_SIZE) - logdata("ENABLE_RF value [%s] invalid\n", p + 1); - else - { - memcpy(ENABLE_RF, p + 1, strlen(p + 1)); - logdata("ENABLE_RF=[%s]\n",ENABLE_RF); - params ++; - } - } - else - if (strcmp(inbuf,"DISABLE_RF") == 0) - { - memset(DISABLE_RF,' ', sizeof(DISABLE_RF)); - DISABLE_RF[RPTR_SIZE] = '\0'; - - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) > RPTR_SIZE) - logdata("DISABLE_RF value [%s] invalid\n", p + 1); - else - { - memcpy(DISABLE_RF, p + 1, strlen(p + 1)); - logdata("DISABLE_RF=[%s]\n",DISABLE_RF); - params ++; - } - } - else - if (strcmp(inbuf,"REMOTE_TIMEOUT") == 0) - { - REMOTE_TIMEOUT = atoi(p + 1); - if (REMOTE_TIMEOUT < 1) - REMOTE_TIMEOUT = 1; - logdata("REMOTE_TIMEOUT=[%d]\n",REMOTE_TIMEOUT); - params ++; - } - else - if (strcmp(inbuf,"RX_Inverse") == 0) - { - if (*(p + 1) == '1') - RX_Inverse = 1; - - else - RX_Inverse = 0; - logdata("RX_Inverse=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"TX_Inverse") == 0) - { - if (*(p + 1) == '1') - TX_Inverse = 1; - - else - TX_Inverse = 0; - logdata("TX_Inverse=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"TX_DELAY") == 0) - { - TX_DELAY = atoi(p + 1); - if (TX_DELAY < 0) - { - TX_DELAY = 250; - logdata("TX-delay can not be below 0, setting it back to 250"); - } - if (TX_DELAY > 6000) - { - TX_DELAY = 250; - logdata("TX-delay exceeds maximum of 6000, setting it back to 250"); - } - Modem_Init2[8] = TX_DELAY & 0xFF; - Modem_Init2[9] = TX_DELAY >> 8; - logdata("TX_DELAY=[%d]\n",TX_DELAY); - params ++; - } - } - fclose(cnf); - - if (params != valid_params) - { - logdata("Configuration file %s invalid\n",cfgFile); - return 1; - } - - inactiveMax = (REMOTE_TIMEOUT * 1000000) / 400; - logdata("... computed max number of loops %d, each loop is 400 microseconds\n", inactiveMax); - - return 0; + logdata("RF_AUDIO_Level=[%d]\n",RF_AUDIO_Level); + params ++; + } else if (strcmp(inbuf,"DUPLEX") == 0) { + if (*(p + 1) == 'Y') + DUPLEX = true; + else + DUPLEX = false; + logdata("DUPLEX=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"RPTR_ACK") == 0) { + if (*(p + 1) == 'Y') + RPTR_ACK = true; + else + RPTR_ACK = false; + logdata("RPTR_ACK=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"ACK_DELAY") == 0) { + ACK_DELAY = atol(p + 1); + if ((ACK_DELAY < 1) || (ACK_DELAY > 999)) + ACK_DELAY = 250; + logdata("ACK_DELAY=[%ld]\n", ACK_DELAY); + ACK_DELAY = ACK_DELAY * 1000; + params ++; + } else if (strcmp(inbuf,"DELAY_BETWEEN") == 0) { + DELAY_BETWEEN = atoi(p + 1); + if (DELAY_BETWEEN < 10) + DELAY_BETWEEN = 16; + logdata("DELAY_BETWEEN=[%d]\n", DELAY_BETWEEN); + DELAY_BETWEEN = DELAY_BETWEEN * 1000; + params ++; + } else if (strcmp(inbuf,"RQST_COUNT") == 0) { + RQST_COUNT = atoi(p + 1); + if (RQST_COUNT < 6) + RQST_COUNT = 6; + logdata("RQST_COUNT=[%d]\n",RQST_COUNT); + params ++; + } else if (strcmp(inbuf,"ENABLE_RF") == 0) { + memset(ENABLE_RF,' ', sizeof(ENABLE_RF)); + ENABLE_RF[RPTR_SIZE] = '\0'; + + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) > RPTR_SIZE) + logdata("ENABLE_RF value [%s] invalid\n", p + 1); + else { + memcpy(ENABLE_RF, p + 1, strlen(p + 1)); + logdata("ENABLE_RF=[%s]\n",ENABLE_RF); + params ++; + } + } else if (strcmp(inbuf,"DISABLE_RF") == 0) { + memset(DISABLE_RF,' ', sizeof(DISABLE_RF)); + DISABLE_RF[RPTR_SIZE] = '\0'; + + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) > RPTR_SIZE) + logdata("DISABLE_RF value [%s] invalid\n", p + 1); + else { + memcpy(DISABLE_RF, p + 1, strlen(p + 1)); + logdata("DISABLE_RF=[%s]\n",DISABLE_RF); + params ++; + } + } else if (strcmp(inbuf,"REMOTE_TIMEOUT") == 0) { + REMOTE_TIMEOUT = atoi(p + 1); + if (REMOTE_TIMEOUT < 1) + REMOTE_TIMEOUT = 1; + logdata("REMOTE_TIMEOUT=[%d]\n",REMOTE_TIMEOUT); + params ++; + } else if (strcmp(inbuf,"RX_Inverse") == 0) { + if (*(p + 1) == '1') + RX_Inverse = 1; + + else + RX_Inverse = 0; + logdata("RX_Inverse=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"TX_Inverse") == 0) { + if (*(p + 1) == '1') + TX_Inverse = 1; + + else + TX_Inverse = 0; + logdata("TX_Inverse=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"TX_DELAY") == 0) { + TX_DELAY = atoi(p + 1); + if (TX_DELAY < 0) { + TX_DELAY = 250; + logdata("TX-delay can not be below 0, setting it back to 250"); + } + if (TX_DELAY > 6000) { + TX_DELAY = 250; + logdata("TX-delay exceeds maximum of 6000, setting it back to 250"); + } + Modem_Init2[8] = TX_DELAY & 0xFF; + Modem_Init2[9] = TX_DELAY >> 8; + logdata("TX_DELAY=[%d]\n",TX_DELAY); + params ++; + } + } + fclose(cnf); + + if (params != valid_params) { + logdata("Configuration file %s invalid\n",cfgFile); + return 1; + } + + inactiveMax = (REMOTE_TIMEOUT * 1000000) / 400; + logdata("... computed max number of loops %d, each loop is 400 microseconds\n", inactiveMax); + + return 0; } static void logdata(const char *fmt,...) { - time_t ltime; - struct tm mytm; + time_t ltime; + struct tm mytm; - time(<ime); - localtime_r(<ime,&mytm); + time(<ime); + localtime_r(<ime,&mytm); - snprintf(trace_buf,TRACE_BFSZ - 1,"%02d%02d%02d at %02d:%02d:%02d:", - mytm.tm_mon+1,mytm.tm_mday,mytm.tm_year % 100, - mytm.tm_hour,mytm.tm_min,mytm.tm_sec); - trace_buf[TRACE_BFSZ - 1] = '\0'; + snprintf(trace_buf,TRACE_BFSZ - 1,"%02d%02d%02d at %02d:%02d:%02d:", + mytm.tm_mon+1,mytm.tm_mday,mytm.tm_year % 100, + mytm.tm_hour,mytm.tm_min,mytm.tm_sec); + trace_buf[TRACE_BFSZ - 1] = '\0'; - va_list args; - va_start(args,fmt); - vsnprintf(trace_buf + strlen(trace_buf), TRACE_BFSZ - strlen(trace_buf) - 1, fmt, args); - va_end(args); + va_list args; + va_start(args,fmt); + vsnprintf(trace_buf + strlen(trace_buf), TRACE_BFSZ - strlen(trace_buf) - 1, fmt, args); + va_end(args); - fprintf(stdout, "%s", trace_buf); - return; + fprintf(stdout, "%s", trace_buf); + return; } - + char *cleanstr (char *Text) { -unsigned int x = 0; -strcpy (Ergebnis,""); - -for (x = 0; x < strlen (Text); x++) - { - if ((Text[x] > 0x1F) && (Text[x] < 0x7F)) - { - if (Text[x] == 0x27) - { - strncat (Ergebnis,"\\",1); - } - strncat (Ergebnis,&Text[x],1); - } - } - - for (x = 0; x < strlen(Ergebnis); x++) - { - if (!isdigit(Ergebnis[x]) && - !isupper(Ergebnis[x]) && - (Ergebnis[x] != '/')) - Ergebnis[x] = ' '; - } - -return (Ergebnis); + unsigned int x = 0; + strcpy (Ergebnis,""); + + for (x = 0; x < strlen (Text); x++) { + if ((Text[x] > 0x1F) && (Text[x] < 0x7F)) { + if (Text[x] == 0x27) { + strncat (Ergebnis,"\\",1); + } + strncat (Ergebnis,&Text[x],1); + } + } + + for (x = 0; x < strlen(Ergebnis); x++) { + if (!isdigit(Ergebnis[x]) && + !isupper(Ergebnis[x]) && + (Ergebnis[x] != '/')) + Ergebnis[x] = ' '; + } + + return (Ergebnis); } int open_port(char *dvrptr_device) { - int fd_ser = -1; - struct termios terminal; - - fd_ser = open(dvrptr_device, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); - if (fd_ser < 0) - { - logdata("Can not open the serial port %s, error=%d(%s)\n", - dvrptr_device, errno, strerror(errno)); - return -1; - } - logdata("Success in opening device %s\n", dvrptr_device); - - fcntl(fd_ser, F_SETFL,FNDELAY); - terminal.c_cflag = BAUD | CS8 | CLOCAL | CREAD; - terminal.c_iflag = IGNPAR; - terminal.c_oflag = 0; - terminal.c_lflag =0; - terminal.c_cc[VMIN] = 1; /* blocking read until 1 chars received */ - tcsetattr(fd_ser,TCSANOW,&terminal); - tcflush(fd_ser,TCIFLUSH); - ioctl(fd_ser,TIOCMSET, TIOCM_DTR); - return fd_ser; + int fd_ser = -1; + struct termios terminal; + + fd_ser = open(dvrptr_device, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); + if (fd_ser < 0) { + logdata("Can not open the serial port %s, error=%d(%s)\n", + dvrptr_device, errno, strerror(errno)); + return -1; + } + logdata("Success in opening device %s\n", dvrptr_device); + + fcntl(fd_ser, F_SETFL,FNDELAY); + terminal.c_cflag = BAUD | CS8 | CLOCAL | CREAD; + terminal.c_iflag = IGNPAR; + terminal.c_oflag = 0; + terminal.c_lflag =0; + terminal.c_cc[VMIN] = 1; /* blocking read until 1 chars received */ + tcsetattr(fd_ser,TCSANOW,&terminal); + tcflush(fd_ser,TCIFLUSH); + ioctl(fd_ser,TIOCMSET, TIOCM_DTR); + return fd_ser; } -int read_port(int *fd_ser,unsigned char* buffera) +int read_port(int *fd_ser,unsigned char* buffera) { - int a; - fd_set rfds; - struct timeval tva; - - FD_ZERO(&rfds); - FD_SET(*fd_ser,&rfds); - tva.tv_sec = 0; - tva.tv_usec = 50; - - select(*fd_ser + 1,&rfds,NULL,NULL,&tva); - if (FD_ISSET(*fd_ser, &rfds)) - { - a = read(*fd_ser,buffera,200); - return a; - } - else - return 0; + int a; + fd_set rfds; + struct timeval tva; + + FD_ZERO(&rfds); + FD_SET(*fd_ser,&rfds); + tva.tv_sec = 0; + tva.tv_usec = 50; + + select(*fd_ser + 1,&rfds,NULL,NULL,&tva); + if (FD_ISSET(*fd_ser, &rfds)) { + a = read(*fd_ser,buffera,200); + return a; + } else + return 0; } static void send_ack(char *a_call, float ber) { - int i; - - char RADIO_ID[21]; - - sprintf(RADIO_ID, "%20.2f", ber); - memcpy(RADIO_ID, "BER%", 4); - - ptt_off[4] =seq_no1; - start_Header[4]=seq_no1; - seq_no3 = 0; - - usleep(ACK_DELAY); - - Send_Modem_Header[0] =0xd0; - Send_Modem_Header[1] =0x2f; - Send_Modem_Header[2] =0x00; - Send_Modem_Header[3] =0x17; - Send_Modem_Header[4] =seq_no1; - Send_Modem_Header[5] =0x00; - Send_Modem_Header[6] =0x00; - Send_Modem_Header[7] =0x00; - - Send_Modem_Header[8] = 0x01; - Send_Modem_Header[9] = 0x00; - Send_Modem_Header[10] = 0x00; - - memcpy(Send_Modem_Header + 11, DVCALL_and_MOD, 8); - memcpy(Send_Modem_Header + 19, DVCALL_and_G, 8); - memcpy(Send_Modem_Header + 27, a_call, 8); - memcpy(Send_Modem_Header + 35, DVCALL_and_MOD, 8); - memcpy(Send_Modem_Header + 43, "RPTR", 4); - - if (memcmp(RPTR, DVCALL, RPTR_SIZE) != 0) - { - memcpy(Send_Modem_Header + 11, RPTR, 7); - memcpy(Send_Modem_Header + 19, RPTR, 7); - - memcpy(Send_Modem_Header + 35, RPTR, 7); - } - - Send_Modem_Header[47] =0xE1; - Send_Modem_Header[48] =0x00; - Send_Modem_Header[49] =0x00; - Send_Modem_Header[50] =0x00; - Send_Modem_Header[51] =0x00; - - write(fd_ser, start_Header, sizeof (start_Header)); - write(fd_ser, Send_Modem_Header, sizeof (Send_Modem_Header)); - - for (i = 0; i < 16; i++) - { - usleep(DELAY_BETWEEN); - if (i == 0) - { - writevoice[0] =0xD0; - writevoice[1] =0x13; - writevoice[2] =0x00; - writevoice[3] =0x19; - writevoice[4] =seq_no1; - writevoice[5] =seq_no3; - writevoice[6] =0x00; - writevoice[7] =0x00; - memcpy(writevoice + 8, silence, 9); - writevoice[17] =0x55; - writevoice[18] =0x2d; - writevoice[19] =0x16; - writevoice[20] =0x00; - writevoice[21] =0x00; - writevoice[22] =0x00; - writevoice[23] =0x00; - - seq_no3 ++; - if (seq_no3 == 252) - seq_no3 = 0; - write(fd_ser, writevoice, sizeof (writevoice)); - } - - if ((i < 9) && ( i > 0 )) - { - writevoice[0] =0xD0; - writevoice[1] =0x13; - writevoice[2] =0x00; - writevoice[3] =0x19; - writevoice[5] =seq_no3; - writevoice[4] =seq_no1; - writevoice[6] =0x00; - writevoice[7] =0x00; - memcpy(writevoice + 8, silence, 9); - - if (i == 1) - { - writevoice[17] = '@' ^ 0x70; - writevoice[18] = RADIO_ID[0] ^ 0x4f; - writevoice[19] = RADIO_ID[1] ^ 0x93; - } - else - if (i == 2) - { - writevoice[17] = RADIO_ID[2] ^ 0x70; - writevoice[18] = RADIO_ID[3] ^ 0x4f; - writevoice[19] = RADIO_ID[4] ^ 0x93; - } - else - if (i == 3) - { - writevoice[17] = 'A' ^ 0x70; - writevoice[18] = RADIO_ID[5] ^ 0x4f; - writevoice[19] = RADIO_ID[6] ^ 0x93; - } - else - if (i == 4) - { - writevoice[17] = RADIO_ID[7] ^ 0x70; - writevoice[18] = RADIO_ID[8] ^ 0x4f; - writevoice[19] = RADIO_ID[9] ^ 0x93; - } - else - if (i == 5) - { - writevoice[17] = 'B' ^ 0x70; - writevoice[18] = RADIO_ID[10] ^ 0x4f; - writevoice[19] = RADIO_ID[11] ^ 0x93; - } - else - if (i == 6) - { - writevoice[17] = RADIO_ID[12] ^ 0x70; - writevoice[18] = RADIO_ID[13] ^ 0x4f; - writevoice[19] = RADIO_ID[14] ^ 0x93; - } - else - if (i == 7) - { - writevoice[17] = 'C' ^ 0x70; - writevoice[18] = RADIO_ID[15] ^ 0x4f; - writevoice[19] = RADIO_ID[16] ^ 0x93; - } - else - if (i == 8) - { - writevoice[17] = RADIO_ID[17] ^ 0x70; - writevoice[18] = RADIO_ID[18] ^ 0x4f; - writevoice[19] = RADIO_ID[19] ^ 0x93; - } - - writevoice[20] =0x00; - writevoice[21] =0x00; - writevoice[22] =0x00; - writevoice[23] =0x00; - - seq_no3 ++; - if (seq_no3 == 252) - seq_no3 = 0; - write(fd_ser, writevoice, sizeof (writevoice)); - } - - if (i == 9) - { - writevoice[0] =0xD0; - writevoice[1] =0x13; - writevoice[2] =0x00; - writevoice[3] =0x19; - writevoice[5] =seq_no3; - writevoice[4] =seq_no1; - writevoice[6] =0x00; - writevoice[7] =0x00; - memcpy(writevoice + 8, silence, 9); - writevoice[17] =0x70; - writevoice[18] =0x4f; - writevoice[19] =0x93; - writevoice[20] =0x00; - writevoice[21] =0x00; - writevoice[22] =0x00; - writevoice[23] =0x00; - - seq_no3 ++; - if (seq_no3 == 252) - seq_no3 = 0; - - write(fd_ser, writevoice, sizeof (writevoice)); - } - - if (i == 15) - { - write(fd_ser, ptt_off, sizeof(ptt_off)); - seq_no1 ++; - if (seq_no1 == 250) - seq_no1 = 1; - } - } - - return; + int i; + + char RADIO_ID[21]; + + sprintf(RADIO_ID, "%20.2f", ber); + memcpy(RADIO_ID, "BER%", 4); + + ptt_off[4] =seq_no1; + start_Header[4]=seq_no1; + seq_no3 = 0; + + usleep(ACK_DELAY); + + Send_Modem_Header[0] =0xd0; + Send_Modem_Header[1] =0x2f; + Send_Modem_Header[2] =0x00; + Send_Modem_Header[3] =0x17; + Send_Modem_Header[4] =seq_no1; + Send_Modem_Header[5] =0x00; + Send_Modem_Header[6] =0x00; + Send_Modem_Header[7] =0x00; + + Send_Modem_Header[8] = 0x01; + Send_Modem_Header[9] = 0x00; + Send_Modem_Header[10] = 0x00; + + memcpy(Send_Modem_Header + 11, DVCALL_and_MOD, 8); + memcpy(Send_Modem_Header + 19, DVCALL_and_G, 8); + memcpy(Send_Modem_Header + 27, a_call, 8); + memcpy(Send_Modem_Header + 35, DVCALL_and_MOD, 8); + memcpy(Send_Modem_Header + 43, "RPTR", 4); + + if (memcmp(RPTR, DVCALL, RPTR_SIZE) != 0) { + memcpy(Send_Modem_Header + 11, RPTR, 7); + memcpy(Send_Modem_Header + 19, RPTR, 7); + + memcpy(Send_Modem_Header + 35, RPTR, 7); + } + + Send_Modem_Header[47] =0xE1; + Send_Modem_Header[48] =0x00; + Send_Modem_Header[49] =0x00; + Send_Modem_Header[50] =0x00; + Send_Modem_Header[51] =0x00; + + write(fd_ser, start_Header, sizeof (start_Header)); + write(fd_ser, Send_Modem_Header, sizeof (Send_Modem_Header)); + + for (i = 0; i < 16; i++) { + usleep(DELAY_BETWEEN); + if (i == 0) { + writevoice[0] =0xD0; + writevoice[1] =0x13; + writevoice[2] =0x00; + writevoice[3] =0x19; + writevoice[4] =seq_no1; + writevoice[5] =seq_no3; + writevoice[6] =0x00; + writevoice[7] =0x00; + memcpy(writevoice + 8, silence, 9); + writevoice[17] =0x55; + writevoice[18] =0x2d; + writevoice[19] =0x16; + writevoice[20] =0x00; + writevoice[21] =0x00; + writevoice[22] =0x00; + writevoice[23] =0x00; + + seq_no3 ++; + if (seq_no3 == 252) + seq_no3 = 0; + write(fd_ser, writevoice, sizeof (writevoice)); + } + + if ((i < 9) && ( i > 0 )) { + writevoice[0] =0xD0; + writevoice[1] =0x13; + writevoice[2] =0x00; + writevoice[3] =0x19; + writevoice[5] =seq_no3; + writevoice[4] =seq_no1; + writevoice[6] =0x00; + writevoice[7] =0x00; + memcpy(writevoice + 8, silence, 9); + + if (i == 1) { + writevoice[17] = '@' ^ 0x70; + writevoice[18] = RADIO_ID[0] ^ 0x4f; + writevoice[19] = RADIO_ID[1] ^ 0x93; + } else if (i == 2) { + writevoice[17] = RADIO_ID[2] ^ 0x70; + writevoice[18] = RADIO_ID[3] ^ 0x4f; + writevoice[19] = RADIO_ID[4] ^ 0x93; + } else if (i == 3) { + writevoice[17] = 'A' ^ 0x70; + writevoice[18] = RADIO_ID[5] ^ 0x4f; + writevoice[19] = RADIO_ID[6] ^ 0x93; + } else if (i == 4) { + writevoice[17] = RADIO_ID[7] ^ 0x70; + writevoice[18] = RADIO_ID[8] ^ 0x4f; + writevoice[19] = RADIO_ID[9] ^ 0x93; + } else if (i == 5) { + writevoice[17] = 'B' ^ 0x70; + writevoice[18] = RADIO_ID[10] ^ 0x4f; + writevoice[19] = RADIO_ID[11] ^ 0x93; + } else if (i == 6) { + writevoice[17] = RADIO_ID[12] ^ 0x70; + writevoice[18] = RADIO_ID[13] ^ 0x4f; + writevoice[19] = RADIO_ID[14] ^ 0x93; + } else if (i == 7) { + writevoice[17] = 'C' ^ 0x70; + writevoice[18] = RADIO_ID[15] ^ 0x4f; + writevoice[19] = RADIO_ID[16] ^ 0x93; + } else if (i == 8) { + writevoice[17] = RADIO_ID[17] ^ 0x70; + writevoice[18] = RADIO_ID[18] ^ 0x4f; + writevoice[19] = RADIO_ID[19] ^ 0x93; + } + + writevoice[20] =0x00; + writevoice[21] =0x00; + writevoice[22] =0x00; + writevoice[23] =0x00; + + seq_no3 ++; + if (seq_no3 == 252) + seq_no3 = 0; + write(fd_ser, writevoice, sizeof (writevoice)); + } + + if (i == 9) { + writevoice[0] =0xD0; + writevoice[1] =0x13; + writevoice[2] =0x00; + writevoice[3] =0x19; + writevoice[5] =seq_no3; + writevoice[4] =seq_no1; + writevoice[6] =0x00; + writevoice[7] =0x00; + memcpy(writevoice + 8, silence, 9); + writevoice[17] =0x70; + writevoice[18] =0x4f; + writevoice[19] =0x93; + writevoice[20] =0x00; + writevoice[21] =0x00; + writevoice[22] =0x00; + writevoice[23] =0x00; + + seq_no3 ++; + if (seq_no3 == 252) + seq_no3 = 0; + + write(fd_ser, writevoice, sizeof (writevoice)); + } + + if (i == 15) { + write(fd_ser, ptt_off, sizeof(ptt_off)); + seq_no1 ++; + if (seq_no1 == 250) + seq_no1 = 1; + } + } + + return; } static void readFrom20000() { - struct sockaddr_in from; - socklen_t fromlen; - int len; - fd_set readfd; - struct timeval tv; - int inactive = 0; - short seq_no = 0; - - unsigned char ctrl_in = 0x80; - bool written_to_q = false; - - while (true) - { - written_to_q = false; - - tv.tv_sec = 0; - tv.tv_usec = 400; // If you change that, then change the inactiveMax computation - fromlen = sizeof(struct sockaddr); - FD_ZERO (&readfd); - FD_SET (insock, &readfd); - select(insock + 1, &readfd, NULL, NULL, &tv); - if (FD_ISSET(insock, &readfd)) - { - len = recvfrom (insock, (char *)&recv_buf, 58, 0, (struct sockaddr *)&from, &fromlen); - if (len == 58) - { - if (busy20000) - { - FD_CLR (insock, &readfd); - continue; - } - - /* check the module and gateway */ - if (recv_buf.rf_hdr.rpt2[7] != DVRPTR_MOD) - { - FD_CLR (insock, &readfd); - break; - } - memcpy(recv_buf.rf_hdr.rpt1, DVCALL_and_G, 8); - - if (memcmp(RPTR, DVCALL, RPTR_SIZE) != 0) - { - memcpy(recv_buf.rf_hdr.rpt1, RPTR, 7); - memcpy(recv_buf.rf_hdr.rpt2, RPTR, 7); - - /* - Do not change the user callsign if it is NOT an ack back from g2, - because we want to know who is talking on remote net - */ - if (memcmp(recv_buf.rf_hdr.mycall, DVCALL, 7) == 0) - memcpy(recv_buf.rf_hdr.mycall, RPTR, 7); - } - - if ((recv_buf.rf_hdr.flags[0] != 0x00) && - (recv_buf.rf_hdr.flags[0] != 0x01) && - (recv_buf.rf_hdr.flags[0] != 0x08) && - (recv_buf.rf_hdr.flags[0] != 0x20) && - (recv_buf.rf_hdr.flags[0] != 0x28) && - (recv_buf.rf_hdr.flags[0] != 0x40)) - { - FD_CLR (insock, &readfd); - break; - } - - if ((memcmp(recv_buf.pkt_id, "DSTR", 4) != 0) || - (recv_buf.flags[0] != 0x73) || - (recv_buf.flags[1] != 0x12) || - (recv_buf.myicm.icm_id != 0x20)) - { - FD_CLR (insock, &readfd); - break; - } - - busy20000 = true; - - ctrl_in = 0x80; - written_to_q = true; - - streamid[0] = recv_buf.myicm.streamid[0]; - streamid[1] = recv_buf.myicm.streamid[1]; - - Send_Modem_Header[0] =0xd0; - Send_Modem_Header[1] =0x2f; - Send_Modem_Header[2] =0x00; - Send_Modem_Header[3] =0x17; - Send_Modem_Header[4] =seq_no2; - Send_Modem_Header[5] =0x40; - Send_Modem_Header[6] =0x00; - Send_Modem_Header[7] =0x00; - - if (recv_buf.rf_hdr.flags[0] != 0x01) - { - if (recv_buf.rf_hdr.flags[0] == 0x00) - recv_buf.rf_hdr.flags[0] = 0x40; - else - if (recv_buf.rf_hdr.flags[0] == 0x08) - recv_buf.rf_hdr.flags[0] = 0x48; - else - if (recv_buf.rf_hdr.flags[0] == 0x20) - recv_buf.rf_hdr.flags[0] = 0x60; - else - if (recv_buf.rf_hdr.flags[0] == 0x28) - recv_buf.rf_hdr.flags[0] = 0x68; - else - recv_buf.rf_hdr.flags[0] = 0x40; - } - recv_buf.rf_hdr.flags[1] = 0x00; - recv_buf.rf_hdr.flags[2] = 0x00; - - memcpy(Send_Modem_Header + 8, recv_buf.rf_hdr.flags, 3); - memcpy(Send_Modem_Header + 11, recv_buf.rf_hdr.rpt1, 8); - memcpy(Send_Modem_Header + 19, recv_buf.rf_hdr.rpt2, 8); - memcpy(Send_Modem_Header + 27, recv_buf.rf_hdr.urcall, 8); - memcpy(Send_Modem_Header + 35, recv_buf.rf_hdr.mycall, 8); - memcpy(Send_Modem_Header + 43, recv_buf.rf_hdr.sfx, 4); - Send_Modem_Header[47] =0xE1; - Send_Modem_Header[48] =0x00; - Send_Modem_Header[49] =0x00; - Send_Modem_Header[50] =0x00; - Send_Modem_Header[51] =0x00; - // printf("\nNetwork Header ID: %2.2x\n",seq_no2); - block = 0; - - logdata("From G2: streamid=%d,%d, flags=%02x:%02x:%02x, myCall=%.8s/%.4s, yrCall=%.8s, rpt1=%.8s, rpt2=%.8s\n", - recv_buf.myicm.streamid[0], recv_buf.myicm.streamid[1], - recv_buf.rf_hdr.flags[0], recv_buf.rf_hdr.flags[1], recv_buf.rf_hdr.flags[2], - recv_buf.rf_hdr.mycall, recv_buf.rf_hdr.sfx, recv_buf.rf_hdr.urcall, - recv_buf.rf_hdr.rpt2, recv_buf.rf_hdr.rpt1); - - ptt_off[4] = seq_no2; - start_Header[4]=seq_no2; - write(fd_ser, start_Header, sizeof (start_Header)); - seq_no2 ++; - if (seq_no2 == 250) - seq_no2 = 1; - - write(fd_ser, Send_Modem_Header, sizeof (Send_Modem_Header)); - inactive = 0; - seq_no = 0; - } - else - if (len == 29) - { - seq_no = recv_buf.myicm.ctrl & 0x1f; - if ((seq_no < 3) && (old_seq_no > 17)) - { - block ++; - if (block >= 12) - block = 0; - } - old_seq_no = seq_no; - seq_no = block * 21 + seq_no; - - if (busy20000) - { - if ((recv_buf.myicm.streamid[0] == streamid[0]) && - (recv_buf.myicm.streamid[1] == streamid[1])) - { - if ((recv_buf.myicm.ctrl <= ctrl_in) && (ctrl_in != 0x80)) - { - /* do not update written_to_q, ctrl_in */ - ; // logdata("dup\n"); - } - else - { - ctrl_in = recv_buf.myicm.ctrl; - if (ctrl_in == 0x14) - ctrl_in = 0x80; - - written_to_q = true; - - writevoice[0] =0xD0; - writevoice[1] =0x13; - writevoice[2] =0x00; - writevoice[3] =0x19; - writevoice[4] =Send_Modem_Header[4]; - writevoice[5] =seq_no; - writevoice[6] =0x00; - writevoice[7] =0x00; - ambefec_regenerate((recv_buf.rf_audio.buff)); - memcpy(writevoice + 8, recv_buf.rf_audio.buff, 12); - writevoice[20] =0x00; - writevoice[21] =0x00; - writevoice[22] =0x00; - writevoice[23] =0x00; - --inactive; - - write(fd_ser, writevoice, sizeof (writevoice)); - inactive = 1; - - if ((recv_buf.myicm.ctrl & 0x40) != 0) - { - logdata("End G2: streamid=%d,%d\n",recv_buf.myicm.streamid[0], recv_buf.myicm.streamid[1]); - - ptt_off[4] = Send_Modem_Header[4]; - write(fd_ser, ptt_off, 8); - busy20000 = false; - - streamid[0] = 0x00; - streamid[1] = 0x00; - - inactive = 0; - FD_CLR (insock, &readfd); - break; - } - } - } - } - else - { - FD_CLR (insock, &readfd); - break; - } - } - else - { - if (!busy20000) - { - FD_CLR (insock, &readfd); - break; - } - } - FD_CLR (insock, &readfd); - } - - /* - If we received a dup or select() timed out or streamids dont match, - then written_to_q is false - */ - if (!written_to_q) /* nothing was written to the adapter */ - { - if (busy20000) - { - if (++inactive == inactiveMax) - { - logdata("G2 Timeout...\n"); - ptt_off[4] = Send_Modem_Header[4]; - write(fd_ser, ptt_off, 8); - busy20000 = false; - - streamid[0] = 0x00; - streamid[1] = 0x00; - - inactive = 0; - break; - } - } - else - break; - } - } - return; + struct sockaddr_in from; + socklen_t fromlen; + int len; + fd_set readfd; + struct timeval tv; + int inactive = 0; + short seq_no = 0; + + unsigned char ctrl_in = 0x80; + bool written_to_q = false; + + while (true) { + written_to_q = false; + + tv.tv_sec = 0; + tv.tv_usec = 400; // If you change that, then change the inactiveMax computation + fromlen = sizeof(struct sockaddr); + FD_ZERO (&readfd); + FD_SET (insock, &readfd); + select(insock + 1, &readfd, NULL, NULL, &tv); + if (FD_ISSET(insock, &readfd)) { + len = recvfrom (insock, (char *)&recv_buf, 58, 0, (struct sockaddr *)&from, &fromlen); + if (len == 58) { + if (busy20000) { + FD_CLR (insock, &readfd); + continue; + } + + /* check the module and gateway */ + if (recv_buf.rf_hdr.rpt2[7] != DVRPTR_MOD) { + FD_CLR (insock, &readfd); + break; + } + memcpy(recv_buf.rf_hdr.rpt1, DVCALL_and_G, 8); + + if (memcmp(RPTR, DVCALL, RPTR_SIZE) != 0) { + memcpy(recv_buf.rf_hdr.rpt1, RPTR, 7); + memcpy(recv_buf.rf_hdr.rpt2, RPTR, 7); + + /* + Do not change the user callsign if it is NOT an ack back from g2, + because we want to know who is talking on remote net + */ + if (memcmp(recv_buf.rf_hdr.mycall, DVCALL, 7) == 0) + memcpy(recv_buf.rf_hdr.mycall, RPTR, 7); + } + + if ((recv_buf.rf_hdr.flags[0] != 0x00) && + (recv_buf.rf_hdr.flags[0] != 0x01) && + (recv_buf.rf_hdr.flags[0] != 0x08) && + (recv_buf.rf_hdr.flags[0] != 0x20) && + (recv_buf.rf_hdr.flags[0] != 0x28) && + (recv_buf.rf_hdr.flags[0] != 0x40)) { + FD_CLR (insock, &readfd); + break; + } + + if ((memcmp(recv_buf.pkt_id, "DSTR", 4) != 0) || + (recv_buf.flags[0] != 0x73) || + (recv_buf.flags[1] != 0x12) || + (recv_buf.myicm.icm_id != 0x20)) { + FD_CLR (insock, &readfd); + break; + } + + busy20000 = true; + + ctrl_in = 0x80; + written_to_q = true; + + streamid[0] = recv_buf.myicm.streamid[0]; + streamid[1] = recv_buf.myicm.streamid[1]; + + Send_Modem_Header[0] =0xd0; + Send_Modem_Header[1] =0x2f; + Send_Modem_Header[2] =0x00; + Send_Modem_Header[3] =0x17; + Send_Modem_Header[4] =seq_no2; + Send_Modem_Header[5] =0x40; + Send_Modem_Header[6] =0x00; + Send_Modem_Header[7] =0x00; + + if (recv_buf.rf_hdr.flags[0] != 0x01) { + if (recv_buf.rf_hdr.flags[0] == 0x00) + recv_buf.rf_hdr.flags[0] = 0x40; + else if (recv_buf.rf_hdr.flags[0] == 0x08) + recv_buf.rf_hdr.flags[0] = 0x48; + else if (recv_buf.rf_hdr.flags[0] == 0x20) + recv_buf.rf_hdr.flags[0] = 0x60; + else if (recv_buf.rf_hdr.flags[0] == 0x28) + recv_buf.rf_hdr.flags[0] = 0x68; + else + recv_buf.rf_hdr.flags[0] = 0x40; + } + recv_buf.rf_hdr.flags[1] = 0x00; + recv_buf.rf_hdr.flags[2] = 0x00; + + memcpy(Send_Modem_Header + 8, recv_buf.rf_hdr.flags, 3); + memcpy(Send_Modem_Header + 11, recv_buf.rf_hdr.rpt1, 8); + memcpy(Send_Modem_Header + 19, recv_buf.rf_hdr.rpt2, 8); + memcpy(Send_Modem_Header + 27, recv_buf.rf_hdr.urcall, 8); + memcpy(Send_Modem_Header + 35, recv_buf.rf_hdr.mycall, 8); + memcpy(Send_Modem_Header + 43, recv_buf.rf_hdr.sfx, 4); + Send_Modem_Header[47] =0xE1; + Send_Modem_Header[48] =0x00; + Send_Modem_Header[49] =0x00; + Send_Modem_Header[50] =0x00; + Send_Modem_Header[51] =0x00; + // printf("\nNetwork Header ID: %2.2x\n",seq_no2); + block = 0; + + logdata("From G2: streamid=%d,%d, flags=%02x:%02x:%02x, myCall=%.8s/%.4s, yrCall=%.8s, rpt1=%.8s, rpt2=%.8s\n", + recv_buf.myicm.streamid[0], recv_buf.myicm.streamid[1], + recv_buf.rf_hdr.flags[0], recv_buf.rf_hdr.flags[1], recv_buf.rf_hdr.flags[2], + recv_buf.rf_hdr.mycall, recv_buf.rf_hdr.sfx, recv_buf.rf_hdr.urcall, + recv_buf.rf_hdr.rpt2, recv_buf.rf_hdr.rpt1); + + ptt_off[4] = seq_no2; + start_Header[4]=seq_no2; + write(fd_ser, start_Header, sizeof (start_Header)); + seq_no2 ++; + if (seq_no2 == 250) + seq_no2 = 1; + + write(fd_ser, Send_Modem_Header, sizeof (Send_Modem_Header)); + inactive = 0; + seq_no = 0; + } else if (len == 29) { + seq_no = recv_buf.myicm.ctrl & 0x1f; + if ((seq_no < 3) && (old_seq_no > 17)) { + block ++; + if (block >= 12) + block = 0; + } + old_seq_no = seq_no; + seq_no = block * 21 + seq_no; + + if (busy20000) { + if ((recv_buf.myicm.streamid[0] == streamid[0]) && + (recv_buf.myicm.streamid[1] == streamid[1])) { + if ((recv_buf.myicm.ctrl <= ctrl_in) && (ctrl_in != 0x80)) { + /* do not update written_to_q, ctrl_in */ + ; // logdata("dup\n"); + } else { + ctrl_in = recv_buf.myicm.ctrl; + if (ctrl_in == 0x14) + ctrl_in = 0x80; + + written_to_q = true; + + writevoice[0] =0xD0; + writevoice[1] =0x13; + writevoice[2] =0x00; + writevoice[3] =0x19; + writevoice[4] =Send_Modem_Header[4]; + writevoice[5] =seq_no; + writevoice[6] =0x00; + writevoice[7] =0x00; + ambefec_regenerate((recv_buf.rf_audio.buff)); + memcpy(writevoice + 8, recv_buf.rf_audio.buff, 12); + writevoice[20] =0x00; + writevoice[21] =0x00; + writevoice[22] =0x00; + writevoice[23] =0x00; + --inactive; + + write(fd_ser, writevoice, sizeof (writevoice)); + inactive = 1; + + if ((recv_buf.myicm.ctrl & 0x40) != 0) { + logdata("End G2: streamid=%d,%d\n",recv_buf.myicm.streamid[0], recv_buf.myicm.streamid[1]); + + ptt_off[4] = Send_Modem_Header[4]; + write(fd_ser, ptt_off, 8); + busy20000 = false; + + streamid[0] = 0x00; + streamid[1] = 0x00; + + inactive = 0; + FD_CLR (insock, &readfd); + break; + } + } + } + } else { + FD_CLR (insock, &readfd); + break; + } + } else { + if (!busy20000) { + FD_CLR (insock, &readfd); + break; + } + } + FD_CLR (insock, &readfd); + } + + /* + If we received a dup or select() timed out or streamids dont match, + then written_to_q is false + */ + if (!written_to_q) { /* nothing was written to the adapter */ + if (busy20000) { + if (++inactive == inactiveMax) { + logdata("G2 Timeout...\n"); + ptt_off[4] = Send_Modem_Header[4]; + write(fd_ser, ptt_off, 8); + busy20000 = false; + + streamid[0] = 0x00; + streamid[1] = 0x00; + + inactive = 0; + break; + } + } else + break; + } + } + return; } bool check_serial() { - int i; - char dvrptr_device[FILENAME_MAX + 1]; - int InitCount = 1; - bool match = false; - unsigned char puffer[200]; - int bytes2; - short loop_count = 0; - char temp_dvrptr_serial[16]; - - for (i = 0; i < 32; i++) - { - sprintf(dvrptr_device, "/dev/ttyACM%d", i); - if (access(dvrptr_device, R_OK | W_OK) != 0) - continue; - - logdata("Trying to access device %s\n", dvrptr_device); - fd_ser = open_port(dvrptr_device); - if (fd_ser < 0) - continue; - - if (RX_Inverse == true) - Modem_Init2[6]=0x01; - if (TX_Inverse == true) - { - if (Modem_Init2[6]==0x01) - Modem_Init2[6]=0x03; - else - Modem_Init2[6]=0x02; - } - - if (flock(fd_ser, LOCK_EX | LOCK_NB) != 0) - { - close(fd_ser); fd_ser = -1; - logdata("Device %s is already locked/used by other dvrptr repeater\n", dvrptr_device); - continue; - } - logdata("Device %s now locked for exclusive use\n", dvrptr_device); - - loop_count = 0; - while (true) - { - if (InitCount == 4 ) {write(fd_ser, Modem_SERIAL, sizeof (Modem_SERIAL)); InitCount = 0;} - if (InitCount == 3 ) {write(fd_ser, Modem_Init0, sizeof (Modem_Init0)); InitCount = 4;} - if (InitCount == 2 ) {write(fd_ser, Modem_Init1, sizeof (Modem_Init1)); InitCount = 3;} - if (InitCount == 1 ) {write(fd_ser, Modem_Init2, sizeof (Modem_Init2)); InitCount = 2;} - - usleep(50000); - bytes2 = read_port(&fd_ser,puffer); - - if ((puffer[0] == 0xD0) && - (puffer[1] == 0x17) && - (puffer[2] == 0x00) && - (puffer[3] == 0x91)) - puffer[1] = 0x00; - - if ((puffer[0] == 0xD0) && - ((puffer[1] == 0x07) || (puffer[1] == 0x08)) && - (puffer[2] == 0x00) && - (puffer[3] == 0x90)) - puffer[1] = 0x00; - - if ((puffer[0] == 0xD0) && - (puffer[1] == 0x05) && - (puffer[2] == 0x00) && - (puffer[3] == 0x92)) - { - puffer[1] = 0x00; - sprintf(temp_dvrptr_serial, "%02X.%02X.%02X.%02X", puffer[4], puffer[5], puffer[6], puffer[7]); - logdata("Device %s has serial=[%s]\n", dvrptr_device, temp_dvrptr_serial); - if (strcmp(temp_dvrptr_serial, DVRPTR_SERIAL) == 0) - { - logdata("Device %s serial number matches DVRPTR_SERIAL in dvrptr.cfg\n", dvrptr_device); - match = true; - } - break; - } - - loop_count ++; - if (loop_count > 50) - { - logdata("Waited 5 seconds to receive serial number from device %s, ...aborting\n", dvrptr_device); - break; - } - } - - if (match) - { - logdata("Found a match after %d loops\n", loop_count); - break; - } - - flock(fd_ser, LOCK_UN | LOCK_NB); - close(fd_ser); fd_ser = -1; - logdata("Closing device %s\n", dvrptr_device); - - } - return match; + int i; + char dvrptr_device[FILENAME_MAX + 1]; + int InitCount = 1; + bool match = false; + unsigned char puffer[200]; + // int bytes2; + short loop_count = 0; + char temp_dvrptr_serial[16]; + + for (i = 0; i < 32; i++) { + sprintf(dvrptr_device, "/dev/ttyACM%d", i); + if (access(dvrptr_device, R_OK | W_OK) != 0) + continue; + + logdata("Trying to access device %s\n", dvrptr_device); + fd_ser = open_port(dvrptr_device); + if (fd_ser < 0) + continue; + + if (RX_Inverse == true) + Modem_Init2[6]=0x01; + if (TX_Inverse == true) { + if (Modem_Init2[6]==0x01) + Modem_Init2[6]=0x03; + else + Modem_Init2[6]=0x02; + } + + if (flock(fd_ser, LOCK_EX | LOCK_NB) != 0) { + close(fd_ser); + fd_ser = -1; + logdata("Device %s is already locked/used by other dvrptr repeater\n", dvrptr_device); + continue; + } + logdata("Device %s now locked for exclusive use\n", dvrptr_device); + + loop_count = 0; + while (true) { + if (InitCount == 4 ) { + write(fd_ser, Modem_SERIAL, sizeof (Modem_SERIAL)); + InitCount = 0; + } + if (InitCount == 3 ) { + write(fd_ser, Modem_Init0, sizeof (Modem_Init0)); + InitCount = 4; + } + if (InitCount == 2 ) { + write(fd_ser, Modem_Init1, sizeof (Modem_Init1)); + InitCount = 3; + } + if (InitCount == 1 ) { + write(fd_ser, Modem_Init2, sizeof (Modem_Init2)); + InitCount = 2; + } + + usleep(50000); + // bytes2 = + (void)read_port(&fd_ser,puffer); + + if ((puffer[0] == 0xD0) && + (puffer[1] == 0x17) && + (puffer[2] == 0x00) && + (puffer[3] == 0x91)) + puffer[1] = 0x00; + + if ((puffer[0] == 0xD0) && + ((puffer[1] == 0x07) || (puffer[1] == 0x08)) && + (puffer[2] == 0x00) && + (puffer[3] == 0x90)) + puffer[1] = 0x00; + + if ((puffer[0] == 0xD0) && + (puffer[1] == 0x05) && + (puffer[2] == 0x00) && + (puffer[3] == 0x92)) { + puffer[1] = 0x00; + sprintf(temp_dvrptr_serial, "%02X.%02X.%02X.%02X", puffer[4], puffer[5], puffer[6], puffer[7]); + logdata("Device %s has serial=[%s]\n", dvrptr_device, temp_dvrptr_serial); + if (strcmp(temp_dvrptr_serial, DVRPTR_SERIAL) == 0) { + logdata("Device %s serial number matches DVRPTR_SERIAL in dvrptr.cfg\n", dvrptr_device); + match = true; + } + break; + } + + loop_count ++; + if (loop_count > 50) { + logdata("Waited 5 seconds to receive serial number from device %s, ...aborting\n", dvrptr_device); + break; + } + } + + if (match) { + logdata("Found a match after %d loops\n", loop_count); + break; + } + + flock(fd_ser, LOCK_UN | LOCK_NB); + close(fd_ser); + fd_ser = -1; + logdata("Closing device %s\n", dvrptr_device); + + } + return match; } -int main(int argc, const char **argv) +int main(int argc, const char **argv) { - int bytes2; - int i; - int InitCount = 1; - short seq_no = 0; - unsigned char puffer[200]; - struct sockaddr_in inaddr; - int rc; - char Temp_Text[200]; - time_t last_RF_time = 0; - time_t tNow = 0; - time_t time_rqst = 0; - - int fw_version; - char fw_string[10]; - - char *temp_ptr = NULL; - - setvbuf(stdout, NULL, _IOLBF, 0); - logdata("dvrptr VERSION %s\n", VERSION); - - if (argc != 2) - { - logdata("Usage: ./dvrptr dvrptr.cfg\n"); - return 1; - } - - rc = read_config(argv[1]); - if (rc != 0) - { - logdata("Failed to process config file %s\n", argv[1]); - return 1; - } - - if (!check_serial()) - { - logdata("Cant find any FREE ACMx device that matches\n"); - return 1; - } - - if (strlen(DVCALL) != 8) - { - logdata("Bad DVCALL value, length must be exactly 8 bytes\n"); - return 1; - } - if ((DVRPTR_MOD != 'A') && (DVRPTR_MOD != 'B') && (DVRPTR_MOD != 'C')) - { - logdata("Bad DVCALL_MOD value, must be one of A or B or C\n"); - return 1; - } - - if (DVRPTR_MOD == 'A') - SND_TERM_ID = 0x03; - else - if (DVRPTR_MOD == 'B') - SND_TERM_ID = 0x01; - else - if (DVRPTR_MOD == 'C') - SND_TERM_ID = 0x02; - - strcpy(DVCALL_and_G, DVCALL); - DVCALL_and_G[7] = 'G'; - - strcpy(DVCALL_and_MOD, DVCALL); - DVCALL_and_MOD[7] = DVRPTR_MOD; - - insock = socket(PF_INET, SOCK_DGRAM, 0); - if (insock == -1) - { - logdata("Failed to create insock, error=%d, message=%s\n",errno,strerror(errno)); - return 1; - } - - memset(&inaddr, 0, sizeof(inaddr)); - inaddr.sin_family = AF_INET; - inaddr.sin_port = htons(DVRPTR_INTERNAL_PORT); - inaddr.sin_addr.s_addr = inet_addr(DVRPTR_INTERNAL_IP); - rc = bind(insock, (struct sockaddr *)&inaddr, sizeof(inaddr)); - if (rc == -1) - { - logdata("bind to socket failed, error=%d, message=%s\n", errno,strerror(errno)); - close(insock); insock = -1; - return 1; - } - fcntl(insock,F_SETFL,O_NONBLOCK); - - memset(&outaddr, 0, sizeof(outaddr)); - outaddr.sin_family = AF_INET; - outaddr.sin_port = htons(GATEWAY_PORT); - outaddr.sin_addr.s_addr = inet_addr(GATEWAY_IP); - - if (RX_Inverse == true) - { - Modem_Init2[6]=0x01; - } - - if (TX_Inverse == true) - { - if (Modem_Init2[6]==0x01) - Modem_Init2[6]=0x03; - else - Modem_Init2[6]=0x02; - } - - memcpy(S_packet, "DSTR", 4); - S_packet[4] = 0x00; - S_packet[5] = 0x00; - S_packet[6] = 0x73; - S_packet[7] = 0x21; - S_packet[8] = 0x00; - S_packet[9] = 0x10; - - dstar_dv_init(); - - time(&tNow); - srand(tNow + getpid()); - - time(&time_rqst); - - while (true) - { - time(&tNow); - if ((tNow - time_rqst) > 2) - { - if (rqst_count < (RQST_COUNT - 2)) - write(fd_ser, Modem_SERIAL, sizeof(Modem_SERIAL)); - - time_rqst = tNow; - - rqst_count --; - if (rqst_count < 0) - { - logdata("Modem is not responding... shuttting down\n"); - close(fd_ser); - break; - } - } - - /* send the S packet if needed */ - if ((tNow - S_ctrl_msg_time) > 60) - { - S_packet[5] = (unsigned char)(C_COUNTER & 0xff); - S_packet[4] = ((C_COUNTER >> 8) & 0xff); - memcpy(S_packet + 10, DVCALL, 8); S_packet[17] = 'S'; - memcpy(S_packet + 18, DVCALL, 8); S_packet[25] = 'S'; - sendto(insock, (char *)S_packet, sizeof(S_packet), 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); - C_COUNTER ++; - S_ctrl_msg_time = tNow; - } - - // init Modem - if (InitCount == 4 ) {write(fd_ser, Modem_STATUS, sizeof (Modem_STATUS)); InitCount = 0;} - if (InitCount == 3 ) {write(fd_ser, Modem_Init0, sizeof (Modem_Init0)); InitCount = 4;} - if (InitCount == 2 ) {write(fd_ser, Modem_Init1, sizeof (Modem_Init1)); InitCount = 3;} - if (InitCount == 1 ) {write(fd_ser, Modem_Init2, sizeof (Modem_Init2)); InitCount = 2;} - - bytes2 = read_port(&fd_ser,puffer); - - if (bytes2 > 0) - { - switch (bytes2) - { - case 52: - - num_dv_frames = 0; - num_bit_errors = 0; - - ok = true; - rqst_count = RQST_COUNT; - - strcpy (Temp_Text,""); - strncat (Temp_Text,(char *)puffer + 27, 8); - strcpy (myUR, cleanstr (Temp_Text)); - - strcpy (Temp_Text,""); - strncat (Temp_Text,(char *) puffer + 35, 8); - strcpy (myCall, cleanstr (Temp_Text)); - - strcpy (Temp_Text,""); - strncat (Temp_Text ,(char *) puffer + 43,4); - strcpy (myCall2, cleanstr (Temp_Text)); - - strcpy (Temp_Text,""); - strncat (Temp_Text,(char *) puffer + 19, 8); - strcpy (myRPT1, cleanstr (Temp_Text)); - - strcpy (Temp_Text,""); - strncat (Temp_Text,(char *) puffer + 11,8); - strcpy (myRPT2, cleanstr (Temp_Text)); - - /* Accept only valid flags */ - /* just in case the data arrived from another repeater over RF */ - /* Also, just in case our local RF user's radio is messed up */ - if ((puffer[8] != 0x00) && - (puffer[8] != 0x08) && - (puffer[8] != 0x20) && - (puffer[8] != 0x28) && - (puffer[8] != 0x40) && - (puffer[8] != 0x48) && - (puffer[8] != 0x60) && - (puffer[8] != 0x68)) - { - // logdata("flags look BAD\n"); - ok = false; - } - - if ((puffer[9] != 0x00) || (puffer[10] != 0x00)) - { - // logdata("flags look BAD\n"); - ok = false; - } - - if (ok) - { - if ((puffer[5] & 0x80) == 0x80) - { - logdata("From RF: flags=%02x:%02x:%02x, myCall=%s/%s, yrCall=%s, rpt1=%s, rpt2=%s\n", - puffer[8], puffer[9], puffer[10], myCall, myCall2, myUR, myRPT1, myRPT2); - logdata("CRC checksum is BAD, will NOT process this QSO\n"); - ok = false; - } - } - - if (ok) - { - time(&last_RF_time); - - logdata("From RF: flags=%02x:%02x:%02x, myCall=%s/%s, yrCall=%s, rpt1=%s, rpt2=%s\n", - puffer[8], puffer[9], puffer[10], myCall, myCall2, myUR, myRPT1, myRPT2); - - /* do not allow connections to stupid/bad STN programs */ - temp_ptr = strstr(myUR, INVALID_YRCALL_KEY); - if (temp_ptr == myUR) - { - logdata("YRCALL value [%s] starts with the INVALID_YRCALL_KEY [%s], resetting to CQCQCQ\n", myUR, INVALID_YRCALL_KEY); - memcpy(myUR, "CQCQCQ ", 8); - } - - /* - If rpt1 is equal to rpt2, but the first 7 bytes is not our system, - then a remote repeater(standalone) is trying to reach our repeater over RF, - in this case, set rpt1 and rpt2 to our values, - because the remote standalone repeater does not have a gateway. - */ - if (memcmp(myRPT1, myRPT2, 7) == 0) - { - if ((memcmp(myRPT1, DVCALL, 7) != 0) && - (memcmp(myRPT1, RPTR, 7) != 0)) - { - memcpy(myRPT1, DVCALL_and_MOD, 8); - memcpy(myRPT2, DVCALL_and_G, 8); - } - } - } - - if (ok) - { - /* RPT1 must always be the repeater + module */ - memcpy(myRPT1, DVCALL_and_MOD, 8); - - /* RPT2 must also be valid */ - if ((myRPT2[7] == 'A') || - (myRPT2[7] == 'B') || - (myRPT2[7] == 'C') || - (myRPT2[7] == 'G')) - memcpy(myRPT2, DVCALL, 7); - else - memset(myRPT2, ' ', 8); - - if ((memcmp(myUR, "CQCQCQ", 6) != 0) && (myRPT2[0] != ' ')) - memcpy(myRPT2, DVCALL_and_G, 8); - - /* 8th in rpt1, rpt2 must be diff */ - if (myRPT2[7] == myRPT1[7]) - memset(myRPT2, ' ', 8); - - /* - Are we restricting the RF user ? - If RPTR is DVCALL, then any RF user can talk. - If RPTR is not DVCALL, - that means that mycall, rpt1, rpt2 must be equal to RPTR - otherwise we drop the rf data - */ - if (memcmp(RPTR, DVCALL, RPTR_SIZE) != 0) - { - if (memcmp(myCall, RPTR, RPTR_SIZE) != 0) - { - logdata("mycall=[%.8s], not equal to %s\n", myCall, RPTR); - ok = false; - } - } - else - if (memcmp(myCall, " ", 8) == 0) - { - logdata("Invalid value for mycall=[%.8s]\n", myCall); - ok = false; - } - } - - if (ok) - { - for (i = 0; i < 8; i++) - { - if (!isupper(myCall[i]) && - !isdigit(myCall[i]) && - (myCall[i] != ' ')) - { - memset(myCall, ' ', 8); - ok = false; - logdata("Invalid value for MYCALL\n"); - break; - } - } - - for (i = 0; i < 4; i++) - { - if (!isupper(myCall2[i]) && - !isdigit(myCall2[i]) && - (myCall2[i] != ' ')) - { - memset(myCall2, ' ', 4); - break; - } - } - - for (i = 0; i < 8; i++) - { - if (!isupper(myUR[i]) && - !isdigit(myUR[i]) && - (myUR[i] != ' ') && - (myUR[i] != '/')) - { - memcpy(myUR, "CQCQCQ ", 8); - break; - } - } - - /*** what if YRCALL is all spaces, we can NOT allow that ***/ - if (memcmp(myUR, " ", 8) == 0) - memcpy(myUR, "CQCQCQ ", 8); - } - - if (ok) - { - if ((memcmp(myUR, ENABLE_RF, 8) == 0) && (ENABLE_RF[0] != ' ')) - { - IS_ENABLED = true; - memcpy(myUR, "CQCQCQ ", 8); - } - else - if ((memcmp(myUR, DISABLE_RF, 8) == 0) && (DISABLE_RF[0] != ' ')) - { - IS_ENABLED = false; - memcpy(myUR, "CQCQCQ ", 8); - } - } - - S_packet[5] = (unsigned char)(C_COUNTER & 0xff); - S_packet[4] = ((C_COUNTER >> 8) & 0xff); - memcpy(S_packet + 10, myCall, 8); - memcpy(S_packet + 18, DVCALL, 8); S_packet[25] = DVRPTR_MOD; - - if (ok) - { - if (IS_ENABLED) - { - sendto(insock, (char *)S_packet, sizeof(S_packet), 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); - C_COUNTER ++; - } - } - - /* - Before we send the data to the local gateway, - set RPT1, RPT2 to be the local gateway - */ - memcpy(myRPT1, DVCALL, 7); - if (myRPT2[7] != ' ') - memcpy(myRPT2, DVCALL, 7); - - memcpy(Send_Network_Header , "DSTR", 4); - Send_Network_Header[4] = ((C_COUNTER >> 8) & 0xff); - Send_Network_Header[5] = (unsigned char)(C_COUNTER & 0xff); - Send_Network_Header[6] = 0x73; - Send_Network_Header[7] = 0x12; - Send_Network_Header[8] = 0x00; - Send_Network_Header[9] = 0x30; - Send_Network_Header[10] = 0x20; - Send_Network_Header[11] = 0x00; - Send_Network_Header[12] = 0x01; - Send_Network_Header[13] = SND_TERM_ID; - streamid_raw = (::rand() % 65535U) + 1U; - Send_Network_Header[14] = streamid_raw / 256U; - Send_Network_Header[15] = streamid_raw % 256U; - Send_Network_Header[16] = 0x80; seq_no = 0; - - if (puffer[8] == 0x40) - Send_Network_Header[17] = 0x00; - else - if (puffer[8] == 0x48) - Send_Network_Header[17] = 0x08; - else - if (puffer[8] == 0x60) - Send_Network_Header[17] = 0x20; - else - if (puffer[8] == 0x68) - Send_Network_Header[17] = 0x28; - else - Send_Network_Header[17] = 0x00; - - Send_Network_Header[18] = puffer[9]; - Send_Network_Header[19] = puffer[10]; - memcpy(Send_Network_Header + 20, myRPT2, 8); - memcpy(Send_Network_Header + 28, myRPT1, 8); - memcpy(Send_Network_Header + 36, myUR, 8); - memcpy(Send_Network_Header + 44, myCall, 8); - memcpy(Send_Network_Header + 52, myCall2, 4); - calcPFCS(Send_Network_Header); - - if (ok) - { - if (IS_ENABLED) - { - sendto(insock, (char *)&Send_Network_Header, 58, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); - C_COUNTER ++; - } - } - - seq_no3 = 0; - - bytes2 = 0; - - if (DUPLEX && !busy20000) - { - Send_Modem_Header[0] =0xd0; - Send_Modem_Header[1] =0x2f; - Send_Modem_Header[2] =0x00; - Send_Modem_Header[3] =0x17; - Send_Modem_Header[4] = puffer[4]; - Send_Modem_Header[5] = 0x00; - Send_Modem_Header[6] = 0x00; - Send_Modem_Header[7] = 0x00; - memcpy(Send_Modem_Header + 8, puffer + 8, 3); - memcpy(Send_Modem_Header + 11, DVCALL_and_MOD, 8); - memcpy(Send_Modem_Header + 19, DVCALL_and_G, 8); - memcpy(Send_Modem_Header + 27, myUR, 8); - memcpy(Send_Modem_Header + 35, myCall, 8); - memcpy(Send_Modem_Header + 43, myCall2, 4); - memcpy(Send_Modem_Header + 47, puffer + 47, 5); - - ptt_off[4] = seq_no1; - start_Header[4]=seq_no1; - - if (ok) - { - if (IS_ENABLED) - { - write(fd_ser, start_Header, sizeof (start_Header)); - write(fd_ser, Send_Modem_Header, sizeof (Send_Modem_Header)); - } - } - } - break; - - case 32: - case 24: - - rqst_count = RQST_COUNT; - - if (!ok) - break; - - if (last_RF_time > 0) - time(&last_RF_time); - - memcpy(Send_Network_Audio , "DSTR", 4); - Send_Network_Audio[4] = ((C_COUNTER >> 8) & 0xff); - Send_Network_Audio[5] = (unsigned char)(C_COUNTER & 0xff); - Send_Network_Audio[6] = 0X73; - Send_Network_Audio[7] = 0X12; - Send_Network_Audio[8] = 0X00; - Send_Network_Audio[9] = 0X13; - Send_Network_Audio[10] = 0X20; - Send_Network_Audio[11] = 0X00; - Send_Network_Audio[12] = 0X01; - Send_Network_Audio[13] = SND_TERM_ID; - Send_Network_Audio[14] = streamid_raw / 256U; - Send_Network_Audio[15] = streamid_raw % 256U; - Send_Network_Audio[16] = seq_no; - memcpy(Send_Network_Audio + 17 , puffer + 8, 12); - - if (IS_ENABLED) - { - sendto(insock, (char *)&Send_Network_Audio, 29, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); - ber_errs = dstar_dv_decode((unsigned char *)&Send_Network_Audio + 17, ber_data); - num_bit_errors += ber_errs; - num_dv_frames ++; - C_COUNTER ++; - } - - seq_no ++; - if (seq_no == 21) - seq_no = 0; - - if (DUPLEX && !busy20000) - { - writevoice1[0] =0xD0; - writevoice1[1] =0x13; - writevoice1[2] =0x00; - writevoice1[3] =0x19; - writevoice1[5] =seq_no3; - writevoice1[4] = Send_Modem_Header[4]; - writevoice1[6] =0x00; - writevoice1[7] =0x00; - ambefec_regenerate((puffer + 8)); - memcpy(writevoice1 + 8, puffer + 8, 12); // ambe audio 8bytes + data 3 bytes - memcpy(writevoice1 + 20, puffer + 20, 4); - - if (IS_ENABLED) - write(fd_ser, writevoice1, sizeof (writevoice1)); - - seq_no3 ++; - if (seq_no3 == 252) - seq_no3 = 0; - } - - if ((puffer[17] == 0x55) && - (puffer[18] == 0x55) && - (puffer[19] == 0x55)) - { - ptt_off[4] = writevoice1[4]; - write(fd_ser, ptt_off, 8); - } - - bytes2 = 0; - break; - - case 8: - - rqst_count = RQST_COUNT; - - bytes2 = 0; - break; - - default: - bytes2 = 0; - break; - } - } - - if ((puffer[0] == 0xD0) && - (puffer[1] == 0x17) && - (puffer[2] == 0x00) && - (puffer[3] == 0x91)) - { - rqst_count = RQST_COUNT; - - logdata("DVRPTR Hardware ver: %.20s\n",puffer+6 ); - - fw_version = puffer[4] + (puffer[5] << 8); - fw_string[0] = ((fw_version >> 12) & 0x0f) + '0'; - fw_string[1] = '.'; - fw_string[2] = ((fw_version >> 8) & 0x0f) + '0'; - fw_string[3] = ((fw_version >> 4) & 0x0f) + '0'; - fw_string[4] = ' '; - fw_string[5] = 0; - if ((fw_version & 0x0f) > 0) - fw_string[4] = (fw_version & 0x0f) + 'a' - 1; - - logdata("DVRPTR Firmware ver: %.5s\n",fw_string ); - puffer[1] = 0x00; - } - - if ((puffer[0] == 0xD0) && - ((puffer[1] == 0x07) || (puffer[1] == 0x08)) && - (puffer[2] == 0x00) && - (puffer[3] == 0x90)) - { - rqst_count = RQST_COUNT; - - logdata("\n------- STATUS READ FROM MODEM ---------\n"); - logdata("Bit1 : Transmitter enabled = %d\n", (puffer[4] & 2) >> 1); - logdata("Bit2 : PC Watchdog enabled = %d\n", (puffer[4] & 4) >> 2); - logdata("Bit3 : Checksum-Calculation enabled = %d\n", (puffer[4] & 8) >> 3); - logdata("Bit4 : I/O 21 Status = %d\n", (puffer[4] & 16) >> 4); - logdata("Bit5 : I/O 23 Status = %d\n", (puffer[4] & 32) >> 5); - logdata("Bit6 : Duplex-Capability = %d\n", (puffer[4] & 64) >> 6); - logdata("Bit7 : (1) physical layer = %d\n", (puffer[4] & 128) >> 7); - logdata("----------------------------------------\n"); - puffer[1] = 0x00; - } - - /* serial */ - if ((puffer[0] == 0xD0) && - (puffer[1] == 0x05) && - (puffer[2] == 0x00) && - (puffer[3] == 0x92)) - { - rqst_count = RQST_COUNT; - puffer[1] = 0x00; - } - - if (IS_ENABLED) - readFrom20000(); - - time(&tNow); - - /* If an RF user TXed and disappeared after that */ - if ((last_RF_time > 0) && ((tNow - last_RF_time) > 1)) - { - logdata("End RF(Timeout), ber=%.02f\n", - (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)) ); - ptt_off[4] = Send_Modem_Header[4]; - write(fd_ser, ptt_off, 8); - } - - if ( ((puffer[0] == 0xD0) && - (puffer[1] == 0x03) && - (puffer[2] == 0x00) && - (puffer[3] == 0x1A)) || - ((last_RF_time > 0) && ((tNow - last_RF_time) > 1)) ) - { - puffer[0] = 0x00; - if (last_RF_time > 0) - { - memcpy(Send_Network_Header , "DSTR", 4); - Send_Network_Header[4] = ((C_COUNTER >> 8) & 0xff); - Send_Network_Header[5] = (unsigned char)(C_COUNTER & 0xff); - Send_Network_Header[6] = 0x73; - Send_Network_Header[7] = 0x12; - Send_Network_Header[8] = 0x00; - Send_Network_Header[9] = 0x13; - Send_Network_Header[10] = 0x20; - Send_Network_Header[11] = 0x00; - Send_Network_Header[12] = 0x01; - Send_Network_Header[13] = 0x01; - Send_Network_Header[16] = seq_no | 0x40; - Send_Network_Header[17] = 0x40; - Send_Network_Header[18] = 0x55; - Send_Network_Header[19] = 0xc8; - - if (ok) - { - if (IS_ENABLED) - { - sendto(insock, (char *)&Send_Network_Header, 29, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); - C_COUNTER ++; - } - } - - ptt_off[4] = Send_Modem_Header[4]; - write(fd_ser, ptt_off, 8); - - logdata("End RF, ber=%.02f\n", - (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)) ); - last_RF_time = 0; - - if (IS_ENABLED && RPTR_ACK) - send_ack(ok?myCall:RPTR, - (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)) ); - ok = false; - } - } - } - - close(insock); - logdata("dvrptr exiting...\n"); - - return 0; + int bytes2; + int i; + int InitCount = 1; + short seq_no = 0; + unsigned char puffer[200]; + struct sockaddr_in inaddr; + int rc; + char Temp_Text[200]; + time_t last_RF_time = 0; + time_t tNow = 0; + time_t time_rqst = 0; + + int fw_version; + char fw_string[10]; + + char *temp_ptr = NULL; + + setvbuf(stdout, NULL, _IOLBF, 0); + logdata("dvrptr VERSION %s\n", VERSION); + + if (argc != 2) { + logdata("Usage: ./dvrptr dvrptr.cfg\n"); + return 1; + } + + rc = read_config(argv[1]); + if (rc != 0) { + logdata("Failed to process config file %s\n", argv[1]); + return 1; + } + + if (!check_serial()) { + logdata("Cant find any FREE ACMx device that matches\n"); + return 1; + } + + if (strlen(DVCALL) != 8) { + logdata("Bad DVCALL value, length must be exactly 8 bytes\n"); + return 1; + } + if ((DVRPTR_MOD != 'A') && (DVRPTR_MOD != 'B') && (DVRPTR_MOD != 'C')) { + logdata("Bad DVCALL_MOD value, must be one of A or B or C\n"); + return 1; + } + + if (DVRPTR_MOD == 'A') + SND_TERM_ID = 0x03; + else if (DVRPTR_MOD == 'B') + SND_TERM_ID = 0x01; + else if (DVRPTR_MOD == 'C') + SND_TERM_ID = 0x02; + + strcpy(DVCALL_and_G, DVCALL); + DVCALL_and_G[7] = 'G'; + + strcpy(DVCALL_and_MOD, DVCALL); + DVCALL_and_MOD[7] = DVRPTR_MOD; + + insock = socket(PF_INET, SOCK_DGRAM, 0); + if (insock == -1) { + logdata("Failed to create insock, error=%d, message=%s\n",errno,strerror(errno)); + return 1; + } + + memset(&inaddr, 0, sizeof(inaddr)); + inaddr.sin_family = AF_INET; + inaddr.sin_port = htons(DVRPTR_INTERNAL_PORT); + inaddr.sin_addr.s_addr = inet_addr(DVRPTR_INTERNAL_IP); + rc = bind(insock, (struct sockaddr *)&inaddr, sizeof(inaddr)); + if (rc == -1) { + logdata("bind to socket failed, error=%d, message=%s\n", errno,strerror(errno)); + close(insock); + insock = -1; + return 1; + } + fcntl(insock,F_SETFL,O_NONBLOCK); + + memset(&outaddr, 0, sizeof(outaddr)); + outaddr.sin_family = AF_INET; + outaddr.sin_port = htons(GATEWAY_PORT); + outaddr.sin_addr.s_addr = inet_addr(GATEWAY_IP); + + if (RX_Inverse == true) { + Modem_Init2[6]=0x01; + } + + if (TX_Inverse == true) { + if (Modem_Init2[6]==0x01) + Modem_Init2[6]=0x03; + else + Modem_Init2[6]=0x02; + } + + memcpy(S_packet, "DSTR", 4); + S_packet[4] = 0x00; + S_packet[5] = 0x00; + S_packet[6] = 0x73; + S_packet[7] = 0x21; + S_packet[8] = 0x00; + S_packet[9] = 0x10; + + dstar_dv_init(); + + time(&tNow); + srand(tNow + getpid()); + + time(&time_rqst); + + while (true) { + time(&tNow); + if ((tNow - time_rqst) > 2) { + if (rqst_count < (RQST_COUNT - 2)) + write(fd_ser, Modem_SERIAL, sizeof(Modem_SERIAL)); + + time_rqst = tNow; + + rqst_count --; + if (rqst_count < 0) { + logdata("Modem is not responding... shuttting down\n"); + close(fd_ser); + break; + } + } + + /* send the S packet if needed */ + if ((tNow - S_ctrl_msg_time) > 60) { + S_packet[5] = (unsigned char)(C_COUNTER & 0xff); + S_packet[4] = ((C_COUNTER >> 8) & 0xff); + memcpy(S_packet + 10, DVCALL, 8); + S_packet[17] = 'S'; + memcpy(S_packet + 18, DVCALL, 8); + S_packet[25] = 'S'; + sendto(insock, (char *)S_packet, sizeof(S_packet), 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); + C_COUNTER ++; + S_ctrl_msg_time = tNow; + } + + // init Modem + if (InitCount == 4 ) { + write(fd_ser, Modem_STATUS, sizeof (Modem_STATUS)); + InitCount = 0; + } + if (InitCount == 3 ) { + write(fd_ser, Modem_Init0, sizeof (Modem_Init0)); + InitCount = 4; + } + if (InitCount == 2 ) { + write(fd_ser, Modem_Init1, sizeof (Modem_Init1)); + InitCount = 3; + } + if (InitCount == 1 ) { + write(fd_ser, Modem_Init2, sizeof (Modem_Init2)); + InitCount = 2; + } + + bytes2 = read_port(&fd_ser,puffer); + + if (bytes2 > 0) { + switch (bytes2) { + case 52: + + num_dv_frames = 0; + num_bit_errors = 0; + + ok = true; + rqst_count = RQST_COUNT; + + strcpy (Temp_Text,""); + strncat (Temp_Text,(char *)puffer + 27, 8); + strcpy (myUR, cleanstr (Temp_Text)); + + strcpy (Temp_Text,""); + strncat (Temp_Text,(char *) puffer + 35, 8); + strcpy (myCall, cleanstr (Temp_Text)); + + strcpy (Temp_Text,""); + strncat (Temp_Text ,(char *) puffer + 43,4); + strcpy (myCall2, cleanstr (Temp_Text)); + + strcpy (Temp_Text,""); + strncat (Temp_Text,(char *) puffer + 19, 8); + strcpy (myRPT1, cleanstr (Temp_Text)); + + strcpy (Temp_Text,""); + strncat (Temp_Text,(char *) puffer + 11,8); + strcpy (myRPT2, cleanstr (Temp_Text)); + + /* Accept only valid flags */ + /* just in case the data arrived from another repeater over RF */ + /* Also, just in case our local RF user's radio is messed up */ + if ((puffer[8] != 0x00) && + (puffer[8] != 0x08) && + (puffer[8] != 0x20) && + (puffer[8] != 0x28) && + (puffer[8] != 0x40) && + (puffer[8] != 0x48) && + (puffer[8] != 0x60) && + (puffer[8] != 0x68)) { + // logdata("flags look BAD\n"); + ok = false; + } + + if ((puffer[9] != 0x00) || (puffer[10] != 0x00)) { + // logdata("flags look BAD\n"); + ok = false; + } + + if (ok) { + if ((puffer[5] & 0x80) == 0x80) { + logdata("From RF: flags=%02x:%02x:%02x, myCall=%s/%s, yrCall=%s, rpt1=%s, rpt2=%s\n", + puffer[8], puffer[9], puffer[10], myCall, myCall2, myUR, myRPT1, myRPT2); + logdata("CRC checksum is BAD, will NOT process this QSO\n"); + ok = false; + } + } + + if (ok) { + time(&last_RF_time); + + logdata("From RF: flags=%02x:%02x:%02x, myCall=%s/%s, yrCall=%s, rpt1=%s, rpt2=%s\n", + puffer[8], puffer[9], puffer[10], myCall, myCall2, myUR, myRPT1, myRPT2); + + /* do not allow connections to stupid/bad STN programs */ + temp_ptr = strstr(myUR, INVALID_YRCALL_KEY); + if (temp_ptr == myUR) { + logdata("YRCALL value [%s] starts with the INVALID_YRCALL_KEY [%s], resetting to CQCQCQ\n", myUR, INVALID_YRCALL_KEY); + memcpy(myUR, "CQCQCQ ", 8); + } + + /* + If rpt1 is equal to rpt2, but the first 7 bytes is not our system, + then a remote repeater(standalone) is trying to reach our repeater over RF, + in this case, set rpt1 and rpt2 to our values, + because the remote standalone repeater does not have a gateway. + */ + if (memcmp(myRPT1, myRPT2, 7) == 0) { + if ((memcmp(myRPT1, DVCALL, 7) != 0) && + (memcmp(myRPT1, RPTR, 7) != 0)) { + memcpy(myRPT1, DVCALL_and_MOD, 8); + memcpy(myRPT2, DVCALL_and_G, 8); + } + } + } + + if (ok) { + /* RPT1 must always be the repeater + module */ + memcpy(myRPT1, DVCALL_and_MOD, 8); + + /* RPT2 must also be valid */ + if ((myRPT2[7] == 'A') || + (myRPT2[7] == 'B') || + (myRPT2[7] == 'C') || + (myRPT2[7] == 'G')) + memcpy(myRPT2, DVCALL, 7); + else + memset(myRPT2, ' ', 8); + + if ((memcmp(myUR, "CQCQCQ", 6) != 0) && (myRPT2[0] != ' ')) + memcpy(myRPT2, DVCALL_and_G, 8); + + /* 8th in rpt1, rpt2 must be diff */ + if (myRPT2[7] == myRPT1[7]) + memset(myRPT2, ' ', 8); + + /* + Are we restricting the RF user ? + If RPTR is DVCALL, then any RF user can talk. + If RPTR is not DVCALL, + that means that mycall, rpt1, rpt2 must be equal to RPTR + otherwise we drop the rf data + */ + if (memcmp(RPTR, DVCALL, RPTR_SIZE) != 0) { + if (memcmp(myCall, RPTR, RPTR_SIZE) != 0) { + logdata("mycall=[%.8s], not equal to %s\n", myCall, RPTR); + ok = false; + } + } else if (memcmp(myCall, " ", 8) == 0) { + logdata("Invalid value for mycall=[%.8s]\n", myCall); + ok = false; + } + } + + if (ok) { + for (i = 0; i < 8; i++) { + if (!isupper(myCall[i]) && + !isdigit(myCall[i]) && + (myCall[i] != ' ')) { + memset(myCall, ' ', 8); + ok = false; + logdata("Invalid value for MYCALL\n"); + break; + } + } + + for (i = 0; i < 4; i++) { + if (!isupper(myCall2[i]) && + !isdigit(myCall2[i]) && + (myCall2[i] != ' ')) { + memset(myCall2, ' ', 4); + break; + } + } + + for (i = 0; i < 8; i++) { + if (!isupper(myUR[i]) && + !isdigit(myUR[i]) && + (myUR[i] != ' ') && + (myUR[i] != '/')) { + memcpy(myUR, "CQCQCQ ", 8); + break; + } + } + + /*** what if YRCALL is all spaces, we can NOT allow that ***/ + if (memcmp(myUR, " ", 8) == 0) + memcpy(myUR, "CQCQCQ ", 8); + } + + if (ok) { + if ((memcmp(myUR, ENABLE_RF, 8) == 0) && (ENABLE_RF[0] != ' ')) { + IS_ENABLED = true; + memcpy(myUR, "CQCQCQ ", 8); + } else if ((memcmp(myUR, DISABLE_RF, 8) == 0) && (DISABLE_RF[0] != ' ')) { + IS_ENABLED = false; + memcpy(myUR, "CQCQCQ ", 8); + } + } + + S_packet[5] = (unsigned char)(C_COUNTER & 0xff); + S_packet[4] = ((C_COUNTER >> 8) & 0xff); + memcpy(S_packet + 10, myCall, 8); + memcpy(S_packet + 18, DVCALL, 8); + S_packet[25] = DVRPTR_MOD; + + if (ok) { + if (IS_ENABLED) { + sendto(insock, (char *)S_packet, sizeof(S_packet), 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); + C_COUNTER ++; + } + } + + /* + Before we send the data to the local gateway, + set RPT1, RPT2 to be the local gateway + */ + memcpy(myRPT1, DVCALL, 7); + if (myRPT2[7] != ' ') + memcpy(myRPT2, DVCALL, 7); + + memcpy(Send_Network_Header , "DSTR", 4); + Send_Network_Header[4] = ((C_COUNTER >> 8) & 0xff); + Send_Network_Header[5] = (unsigned char)(C_COUNTER & 0xff); + Send_Network_Header[6] = 0x73; + Send_Network_Header[7] = 0x12; + Send_Network_Header[8] = 0x00; + Send_Network_Header[9] = 0x30; + Send_Network_Header[10] = 0x20; + Send_Network_Header[11] = 0x00; + Send_Network_Header[12] = 0x01; + Send_Network_Header[13] = SND_TERM_ID; + streamid_raw = (::rand() % 65535U) + 1U; + Send_Network_Header[14] = streamid_raw / 256U; + Send_Network_Header[15] = streamid_raw % 256U; + Send_Network_Header[16] = 0x80; + seq_no = 0; + + if (puffer[8] == 0x40) + Send_Network_Header[17] = 0x00; + else if (puffer[8] == 0x48) + Send_Network_Header[17] = 0x08; + else if (puffer[8] == 0x60) + Send_Network_Header[17] = 0x20; + else if (puffer[8] == 0x68) + Send_Network_Header[17] = 0x28; + else + Send_Network_Header[17] = 0x00; + + Send_Network_Header[18] = puffer[9]; + Send_Network_Header[19] = puffer[10]; + memcpy(Send_Network_Header + 20, myRPT2, 8); + memcpy(Send_Network_Header + 28, myRPT1, 8); + memcpy(Send_Network_Header + 36, myUR, 8); + memcpy(Send_Network_Header + 44, myCall, 8); + memcpy(Send_Network_Header + 52, myCall2, 4); + calcPFCS(Send_Network_Header); + + if (ok) { + if (IS_ENABLED) { + sendto(insock, (char *)&Send_Network_Header, 58, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); + C_COUNTER ++; + } + } + + seq_no3 = 0; + + bytes2 = 0; + + if (DUPLEX && !busy20000) { + Send_Modem_Header[0] =0xd0; + Send_Modem_Header[1] =0x2f; + Send_Modem_Header[2] =0x00; + Send_Modem_Header[3] =0x17; + Send_Modem_Header[4] = puffer[4]; + Send_Modem_Header[5] = 0x00; + Send_Modem_Header[6] = 0x00; + Send_Modem_Header[7] = 0x00; + memcpy(Send_Modem_Header + 8, puffer + 8, 3); + memcpy(Send_Modem_Header + 11, DVCALL_and_MOD, 8); + memcpy(Send_Modem_Header + 19, DVCALL_and_G, 8); + memcpy(Send_Modem_Header + 27, myUR, 8); + memcpy(Send_Modem_Header + 35, myCall, 8); + memcpy(Send_Modem_Header + 43, myCall2, 4); + memcpy(Send_Modem_Header + 47, puffer + 47, 5); + + ptt_off[4] = seq_no1; + start_Header[4]=seq_no1; + + if (ok) { + if (IS_ENABLED) { + write(fd_ser, start_Header, sizeof (start_Header)); + write(fd_ser, Send_Modem_Header, sizeof (Send_Modem_Header)); + } + } + } + break; + + case 32: + case 24: + + rqst_count = RQST_COUNT; + + if (!ok) + break; + + if (last_RF_time > 0) + time(&last_RF_time); + + memcpy(Send_Network_Audio , "DSTR", 4); + Send_Network_Audio[4] = ((C_COUNTER >> 8) & 0xff); + Send_Network_Audio[5] = (unsigned char)(C_COUNTER & 0xff); + Send_Network_Audio[6] = 0X73; + Send_Network_Audio[7] = 0X12; + Send_Network_Audio[8] = 0X00; + Send_Network_Audio[9] = 0X13; + Send_Network_Audio[10] = 0X20; + Send_Network_Audio[11] = 0X00; + Send_Network_Audio[12] = 0X01; + Send_Network_Audio[13] = SND_TERM_ID; + Send_Network_Audio[14] = streamid_raw / 256U; + Send_Network_Audio[15] = streamid_raw % 256U; + Send_Network_Audio[16] = seq_no; + memcpy(Send_Network_Audio + 17 , puffer + 8, 12); + + if (IS_ENABLED) { + sendto(insock, (char *)&Send_Network_Audio, 29, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); + ber_errs = dstar_dv_decode((unsigned char *)&Send_Network_Audio + 17, ber_data); + num_bit_errors += ber_errs; + num_dv_frames ++; + C_COUNTER ++; + } + + seq_no ++; + if (seq_no == 21) + seq_no = 0; + + if (DUPLEX && !busy20000) { + writevoice1[0] =0xD0; + writevoice1[1] =0x13; + writevoice1[2] =0x00; + writevoice1[3] =0x19; + writevoice1[5] =seq_no3; + writevoice1[4] = Send_Modem_Header[4]; + writevoice1[6] =0x00; + writevoice1[7] =0x00; + ambefec_regenerate((puffer + 8)); + memcpy(writevoice1 + 8, puffer + 8, 12); // ambe audio 8bytes + data 3 bytes + memcpy(writevoice1 + 20, puffer + 20, 4); + + if (IS_ENABLED) + write(fd_ser, writevoice1, sizeof (writevoice1)); + + seq_no3 ++; + if (seq_no3 == 252) + seq_no3 = 0; + } + + if ((puffer[17] == 0x55) && + (puffer[18] == 0x55) && + (puffer[19] == 0x55)) { + ptt_off[4] = writevoice1[4]; + write(fd_ser, ptt_off, 8); + } + + bytes2 = 0; + break; + + case 8: + + rqst_count = RQST_COUNT; + + bytes2 = 0; + break; + + default: + bytes2 = 0; + break; + } + } + + if ((puffer[0] == 0xD0) && + (puffer[1] == 0x17) && + (puffer[2] == 0x00) && + (puffer[3] == 0x91)) { + rqst_count = RQST_COUNT; + + logdata("DVRPTR Hardware ver: %.20s\n",puffer+6 ); + + fw_version = puffer[4] + (puffer[5] << 8); + fw_string[0] = ((fw_version >> 12) & 0x0f) + '0'; + fw_string[1] = '.'; + fw_string[2] = ((fw_version >> 8) & 0x0f) + '0'; + fw_string[3] = ((fw_version >> 4) & 0x0f) + '0'; + fw_string[4] = ' '; + fw_string[5] = 0; + if ((fw_version & 0x0f) > 0) + fw_string[4] = (fw_version & 0x0f) + 'a' - 1; + + logdata("DVRPTR Firmware ver: %.5s\n",fw_string ); + puffer[1] = 0x00; + } + + if ((puffer[0] == 0xD0) && + ((puffer[1] == 0x07) || (puffer[1] == 0x08)) && + (puffer[2] == 0x00) && + (puffer[3] == 0x90)) { + rqst_count = RQST_COUNT; + + logdata("\n------- STATUS READ FROM MODEM ---------\n"); + logdata("Bit1 : Transmitter enabled = %d\n", (puffer[4] & 2) >> 1); + logdata("Bit2 : PC Watchdog enabled = %d\n", (puffer[4] & 4) >> 2); + logdata("Bit3 : Checksum-Calculation enabled = %d\n", (puffer[4] & 8) >> 3); + logdata("Bit4 : I/O 21 Status = %d\n", (puffer[4] & 16) >> 4); + logdata("Bit5 : I/O 23 Status = %d\n", (puffer[4] & 32) >> 5); + logdata("Bit6 : Duplex-Capability = %d\n", (puffer[4] & 64) >> 6); + logdata("Bit7 : (1) physical layer = %d\n", (puffer[4] & 128) >> 7); + logdata("----------------------------------------\n"); + puffer[1] = 0x00; + } + + /* serial */ + if ((puffer[0] == 0xD0) && + (puffer[1] == 0x05) && + (puffer[2] == 0x00) && + (puffer[3] == 0x92)) { + rqst_count = RQST_COUNT; + puffer[1] = 0x00; + } + + if (IS_ENABLED) + readFrom20000(); + + time(&tNow); + + /* If an RF user TXed and disappeared after that */ + if ((last_RF_time > 0) && ((tNow - last_RF_time) > 1)) { + logdata("End RF(Timeout), ber=%.02f\n", + (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)) ); + ptt_off[4] = Send_Modem_Header[4]; + write(fd_ser, ptt_off, 8); + } + + if ( ((puffer[0] == 0xD0) && + (puffer[1] == 0x03) && + (puffer[2] == 0x00) && + (puffer[3] == 0x1A)) || + ((last_RF_time > 0) && ((tNow - last_RF_time) > 1)) ) { + puffer[0] = 0x00; + if (last_RF_time > 0) { + memcpy(Send_Network_Header , "DSTR", 4); + Send_Network_Header[4] = ((C_COUNTER >> 8) & 0xff); + Send_Network_Header[5] = (unsigned char)(C_COUNTER & 0xff); + Send_Network_Header[6] = 0x73; + Send_Network_Header[7] = 0x12; + Send_Network_Header[8] = 0x00; + Send_Network_Header[9] = 0x13; + Send_Network_Header[10] = 0x20; + Send_Network_Header[11] = 0x00; + Send_Network_Header[12] = 0x01; + Send_Network_Header[13] = 0x01; + Send_Network_Header[16] = seq_no | 0x40; + Send_Network_Header[17] = 0x40; + Send_Network_Header[18] = 0x55; + Send_Network_Header[19] = 0xc8; + + if (ok) { + if (IS_ENABLED) { + sendto(insock, (char *)&Send_Network_Header, 29, 0, (struct sockaddr *)&outaddr, sizeof(outaddr)); + C_COUNTER ++; + } + } + + ptt_off[4] = Send_Modem_Header[4]; + write(fd_ser, ptt_off, 8); + + logdata("End RF, ber=%.02f\n", + (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)) ); + last_RF_time = 0; + + if (IS_ENABLED && RPTR_ACK) + send_ack(ok?myCall:RPTR, + (num_dv_frames == 0)?0.00:100.00 * ((float)num_bit_errors / (float)(num_dv_frames * 24.00)) ); + ok = false; + } + } + } + + close(insock); + logdata("dvrptr exiting...\n"); + + return 0; } diff --git a/g2_ircddb.cpp b/g2_ircddb.cpp index 0d3a786..b8609ed 100644 --- a/g2_ircddb.cpp +++ b/g2_ircddb.cpp @@ -6,20 +6,20 @@ * 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, + * 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 + * 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 + * 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. */ /* by KI4LKF */ -/* - g2_ircddb is a dstar G2 gateway, using irc routing +/* + g2_ircddb is a dstar G2 gateway, using irc routing adapted from the OpenG2 G2 gateway Version 2.61 or higher will use ONLY the irc mechanism of routing and it will NOT use any local Postgres databases or any TRUST(s) @@ -78,7 +78,7 @@ static char OWNER[OWNER_SIZE + 1]; static char owner[OWNER_SIZE + 1]; static char PACKAGE_REV[56]; -static char LOCAL_IRC_IP[IP_SIZE + 1]; +static char LOCAL_IRC_IP[IP_SIZE + 1]; static bool SEND_QRGS_MAPS = false; static char QTH[257]; static char QRG_A[257]; @@ -87,7 +87,7 @@ static char QRG_C[257]; static char STATUS_FILE[FILENAME_MAX + 1]; -static char silence[9] = { 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8 }; +static unsigned char silence[9] = { 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8 }; static char DTMF_DIR[FILENAME_MAX + 1]; static char DTMF_FILE[FILENAME_MAX + 1]; @@ -110,30 +110,29 @@ static struct sockaddr_in aprs_addr; static socklen_t aprs_addr_len; /* data needed for aprs login and aprs beacon */ -static struct -{ - char aprs_host[MAXHOSTNAMELEN + 1]; - int aprs_port; - int aprs_hash; - int aprs_interval; - char aprs_filter[512]; - - /* 0=A, 1=B, 2=C */ - char rptr[3][CALL_SIZE + 1]; /* KJ4NHF-B */ - char band[3][5]; /* 23cm ... */ - int range[3]; - double lat[3]; - double lon[3]; - char desc[3][64]; +static struct { + char aprs_host[MAXHOSTNAMELEN + 1]; + int aprs_port; + int aprs_hash; + int aprs_interval; + char aprs_filter[512]; + + /* 0=A, 1=B, 2=C */ + char rptr[3][CALL_SIZE + 1]; /* KJ4NHF-B */ + char band[3][5]; /* 23cm ... */ + int range[3]; + double lat[3]; + double lon[3]; + char desc[3][64]; } RPTR_ID; /* Gateway external IP and port for remote G2 routing */ static char G2_EXTERNAL_IP[IP_SIZE + 1]; /* 0.0.0.0 */ static int G2_EXTERNAL_PORT = 40000; -/* - Internal Gateway internal IP and port, - so that the local repeater modules can talk to our g2_ircddb +/* + Internal Gateway internal IP and port, + so that the local repeater modules can talk to our g2_ircddb */ static char G2_INTERNAL_IP[IP_SIZE + 1]; /* 0.0.0.0 */ static int G2_INTERNAL_PORT = 19000; @@ -144,7 +143,7 @@ static char TO_G2_LINK_IP[IP_SIZE + 1]; /* local repeater module IP and port for each repeater module */ /* all set to 127.0.0.1, unless running on other boxes */ -static char TO_RPTR_IP[3][IP_SIZE + 1]; +static char TO_RPTR_IP[3][IP_SIZE + 1]; static int TO_RPTR_PORT[3]; /* Example: 19998 19999 20000 */ /* QSO details go to a log file */ @@ -155,14 +154,14 @@ static bool SEND_APRS = false; /* Recorded files are here */ static char ECHOTEST_DIR[FILENAME_MAX + 1]; -/* +/* How many SECONDS to wait before starting to playback the recorded file. 1 second is enough, some repeaters require 2 seconds to re-initialize before they accept new streams again. */ static int PLAY_WAIT = 1; -/* +/* How many MILLIseconds to delay when playing back each of the recorded packets Normal VoIP is 20 milliseconds */ @@ -179,30 +178,27 @@ static int FROM_LOCAL_RPTR_TIMEOUT = 1; /* local repeater modules being recorded */ /* This is for echotest */ -static struct -{ - time_t last_time; - unsigned char streamid[2]; - int fd; - char file[FILENAME_MAX + 1]; +static struct { + time_t last_time; + unsigned char streamid[2]; + int fd; + char file[FILENAME_MAX + 1]; } recd[3]; /* this is for vm */ -static struct -{ - time_t last_time; - unsigned char streamid[2]; - int fd; - char file[FILENAME_MAX + 1]; +static struct { + time_t last_time; + unsigned char streamid[2]; + int fd; + char file[FILENAME_MAX + 1]; } vm[3]; static unsigned char recbuf[100]; /* 56 or 27, max is 56 */ /* the streamids going to remote Gateways from each local module */ -static struct -{ - unsigned char streamid[2]; - struct sockaddr_in toDst4; - time_t last_time; +static struct { + unsigned char streamid[2]; + struct sockaddr_in toDst4; + time_t last_time; } to_remote_g2[3]; /* 0=A, 1=B, 2=C */ /* input from remote G2 gateway */ @@ -210,22 +206,21 @@ static int g2_sock = -1; static unsigned char readBuffer2[2000]; /* 56 or 27, max is 56 */ static struct sockaddr_in fromDst4; -/* - Incoming data from remote systems +/* + Incoming data from remote systems must be fed into our local repeater modules. */ -static struct -{ - /* help with header re-generation */ - unsigned char saved_hdr[58]; /* repeater format */ - uint32_t saved_adr; - - unsigned char streamid[2]; - uint32_t adr; - struct sockaddr_in band_addr; - time_t last_time; - unsigned short G2_COUNTER; - unsigned char sequence; +static struct { + /* help with header re-generation */ + unsigned char saved_hdr[58]; /* repeater format */ + uint32_t saved_adr; + + unsigned char streamid[2]; + uint32_t adr; + struct sockaddr_in band_addr; + time_t last_time; + unsigned short G2_COUNTER; + unsigned char sequence; } toRptr[3]; /* 0=A, 1=B, 2=C */ /* input from our own local repeater modules */ @@ -245,81 +240,76 @@ static struct sockaddr_in plug; /* for talking with the irc server */ static CIRCDDB *ii; -enum aprs_level -{ - al_none, - al_$1, - al_$2, - al_c1, - al_r1, - al_c2, - al_csum1, - al_csum2, - al_csum3, - al_csum4, - al_data, - al_end +enum aprs_level { + al_none, + al_$1, + al_$2, + al_c1, + al_r1, + al_c2, + al_csum1, + al_csum2, + al_csum3, + al_csum4, + al_data, + al_end }; -enum slow_level -{ - sl_first, - sl_second +enum slow_level { + sl_first, + sl_second }; -static struct -{ - aprs_level al; - unsigned char data[300]; - unsigned int len; - unsigned char buf[6]; - slow_level sl; - bool is_sent; +static struct { + aprs_level al; + unsigned char data[300]; + unsigned int len; + unsigned char buf[6]; + slow_level sl; + bool is_sent; } aprs_pack[3]; /* lock down a stream per band */ -static struct -{ - unsigned char streamID[2]; - time_t last_time; +static struct { + unsigned char streamID[2]; + time_t last_time; } aprs_streamID[3]; /* text coming from local repeater bands */ -static struct -{ - unsigned char streamID[2]; - unsigned char flags[3]; - char lh_mycall[CALL_SIZE + 1]; - char lh_sfx[5]; - char lh_yrcall[CALL_SIZE + 1]; - char lh_rpt1[CALL_SIZE + 1]; - char lh_rpt2[CALL_SIZE + 1]; - time_t last_time; - char txt[64]; /* Only 20 are used */ - unsigned short txt_cnt; - bool txt_stats_sent; - - char dest_rptr[CALL_SIZE + 1]; - - /* try to process GPS mode: GPRMC and ID */ - char temp_line[256]; - unsigned short temp_line_cnt; - char gprmc[256]; - char gpid[256]; - bool is_gps_sent; - time_t gps_last_time; - - int num_dv_frames; - int num_dv_silent_frames; - int num_bit_errors; +static struct { + unsigned char streamID[2]; + unsigned char flags[3]; + char lh_mycall[CALL_SIZE + 1]; + char lh_sfx[5]; + char lh_yrcall[CALL_SIZE + 1]; + char lh_rpt1[CALL_SIZE + 1]; + char lh_rpt2[CALL_SIZE + 1]; + time_t last_time; + char txt[64]; /* Only 20 are used */ + unsigned short txt_cnt; + bool txt_stats_sent; + + char dest_rptr[CALL_SIZE + 1]; + + /* try to process GPS mode: GPRMC and ID */ + char temp_line[256]; + unsigned short temp_line_cnt; + char gprmc[256]; + char gpid[256]; + bool is_gps_sent; + time_t gps_last_time; + + int num_dv_frames; + int num_dv_silent_frames; + int num_bit_errors; } band_txt[3]; /* 0=A, 1=B, 2=C */ /* Used to validate MYCALL input */ static regex_t preg; -/* - CACHE used to cache users, repeaters, +/* + CACHE used to cache users, repeaters, gateways, IP numbers coming from the irc server */ WX_DECLARE_STRING_HASH_MAP(wxString, user2rptr_type); @@ -333,40 +323,39 @@ static gwy2ip_type gwy2ip_map; static pthread_mutex_t irc_data_mutex = PTHREAD_MUTEX_INITIALIZER; -static unsigned short crc_tabccitt[256] = -{ - 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, - 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, - 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, - 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, - 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, - 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, - 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, - 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, - 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, - 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, - 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, - 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, - 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, - 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, - 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, - 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, - 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, - 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, - 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, - 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, - 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, - 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, - 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, - 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, - 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, - 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, - 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, - 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, - 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, - 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, - 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, - 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 +static unsigned short crc_tabccitt[256] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 }; static int g2_open(); @@ -374,9 +363,9 @@ static int srv_open(); static void calcPFCS(unsigned char *packet, int len); static void *get_irc_data(void *arg); static int get_yrcall_rptr_from_cache(char *call, char *arearp_cs, char *zonerp_cs, - char *mod, char *ip, char RoU); -static bool get_yrcall_rptr(char *call, char *arearp_cs, char *zonerp_cs, - char *mod, char *ip, char RoU); + char *mod, char *ip, char RoU); +static bool get_yrcall_rptr(char *call, char *arearp_cs, char *zonerp_cs, + char *mod, char *ip, char RoU); static void traceit(const char *fmt,...); static int read_config(char *); static void runit(); @@ -397,8 +386,8 @@ static bool aprs_check_data(short int rptr_idx); static unsigned int aprs_calc_crc(unsigned char* buf, unsigned int len); static void aprs_select_band(short int rptr_idx, unsigned char *streamID); static void aprs_process_text(unsigned char *streamID, - unsigned char seq, - unsigned char *buf, + unsigned char seq, + unsigned char *buf, unsigned int len); static void gps_send(short int rptr_idx); static bool verify_gps_csum(char *gps_text, char *csum_text); @@ -416,4032 +405,3444 @@ extern int dstar_dv_decode(const unsigned char *d, int data[3]); static bool resolve_rmt(char *name, int type, struct sockaddr_in *addr) { - struct addrinfo hints; - struct addrinfo *res; - struct addrinfo *rp; - int rc = 0; - bool found = false; - - memset(&hints, 0x00, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; - hints.ai_socktype = type; - - rc = getaddrinfo(name, NULL, &hints, &res); - if (rc != 0) - { - traceit("getaddrinfo return error code %d for [%s]\n", rc, name); - return false; - } - - for (rp = res; rp != NULL; rp = rp->ai_next) - { - if ((rp->ai_family == AF_INET) && - (rp->ai_socktype == type)) - { - memcpy(addr, rp->ai_addr, sizeof(struct sockaddr_in)); - found = true; - break; - } - } - freeaddrinfo(res); - return found; + struct addrinfo hints; + struct addrinfo *res; + struct addrinfo *rp; + int rc = 0; + bool found = false; + + memset(&hints, 0x00, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = type; + + rc = getaddrinfo(name, NULL, &hints, &res); + if (rc != 0) { + traceit("getaddrinfo return error code %d for [%s]\n", rc, name); + return false; + } + + for (rp = res; rp != NULL; rp = rp->ai_next) { + if ((rp->ai_family == AF_INET) && + (rp->ai_socktype == type)) { + memcpy(addr, rp->ai_addr, sizeof(struct sockaddr_in)); + found = true; + break; + } + } + freeaddrinfo(res); + return found; } static void set_dest_rptr(int mod_ndx, char *dest_rptr) { - FILE *statusfp = NULL; - char statusbuf[1024]; - char *status_local_mod = NULL; - char *status_remote_stm = NULL; - char *status_remote_mod = NULL; - const char *delim = ","; - char *saveptr = NULL; - char *p = NULL; - - statusfp = fopen(STATUS_FILE, "r"); - if (statusfp) - { - setvbuf(statusfp, (char *)NULL, _IOLBF, 0); - - while (fgets(statusbuf, 1020, statusfp) != NULL) - { - p = strchr(statusbuf, '\r'); - if (p) - *p = '\0'; - p = strchr(statusbuf, '\n'); - if (p) - *p = '\0'; - - status_local_mod = strtok_r(statusbuf, delim, &saveptr); - status_remote_stm = strtok_r(NULL, delim, &saveptr); - status_remote_mod = strtok_r(NULL, delim, &saveptr); - - if (!status_local_mod || !status_remote_stm || !status_remote_mod) - continue; - - if ( ((*status_local_mod == 'A') && (mod_ndx == 0)) || - ((*status_local_mod == 'B') && (mod_ndx == 1)) || - ((*status_local_mod == 'C') && (mod_ndx == 2)) ) - { - strncpy(dest_rptr, status_remote_stm, CALL_SIZE); - dest_rptr[7] = *status_remote_mod; - dest_rptr[CALL_SIZE] = '\0'; - break; - } - } - fclose(statusfp); - } - - return; + FILE *statusfp = NULL; + char statusbuf[1024]; + char *status_local_mod = NULL; + char *status_remote_stm = NULL; + char *status_remote_mod = NULL; + const char *delim = ","; + char *saveptr = NULL; + char *p = NULL; + + statusfp = fopen(STATUS_FILE, "r"); + if (statusfp) { + setvbuf(statusfp, (char *)NULL, _IOLBF, 0); + + while (fgets(statusbuf, 1020, statusfp) != NULL) { + p = strchr(statusbuf, '\r'); + if (p) + *p = '\0'; + p = strchr(statusbuf, '\n'); + if (p) + *p = '\0'; + + status_local_mod = strtok_r(statusbuf, delim, &saveptr); + status_remote_stm = strtok_r(NULL, delim, &saveptr); + status_remote_mod = strtok_r(NULL, delim, &saveptr); + + if (!status_local_mod || !status_remote_stm || !status_remote_mod) + continue; + + if ( ((*status_local_mod == 'A') && (mod_ndx == 0)) || + ((*status_local_mod == 'B') && (mod_ndx == 1)) || + ((*status_local_mod == 'C') && (mod_ndx == 2)) ) { + strncpy(dest_rptr, status_remote_stm, CALL_SIZE); + dest_rptr[7] = *status_remote_mod; + dest_rptr[CALL_SIZE] = '\0'; + break; + } + } + fclose(statusfp); + } + + return; } /* compute checksum */ static void calcPFCS(unsigned char *packet, int len) { - unsigned short crc_dstar_ffff = 0xffff; - unsigned short tmp, short_c; - short int i; - short int low; - short int high; - - if (len == 56) - { - low = 15; - high = 54; - } - else - if (len == 58) - { - low = 17; - high = 56; - } - else - return; - - - for (i = low; i < high ; i++) - { - short_c = 0x00ff & (unsigned short)packet[i]; - tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; - crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; - } - crc_dstar_ffff = ~crc_dstar_ffff; - tmp = crc_dstar_ffff; - - if (len == 56) - { - packet[54] = (unsigned char)(crc_dstar_ffff & 0xff); - packet[55] = (unsigned char)((tmp >> 8) & 0xff); - } - else - { - packet[56] = (unsigned char)(crc_dstar_ffff & 0xff); - packet[57] = (unsigned char)((tmp >> 8) & 0xff); - } - - return; + unsigned short crc_dstar_ffff = 0xffff; + unsigned short tmp, short_c; + short int i; + short int low; + short int high; + + if (len == 56) { + low = 15; + high = 54; + } else if (len == 58) { + low = 17; + high = 56; + } else + return; + + + for (i = low; i < high ; i++) { + short_c = 0x00ff & (unsigned short)packet[i]; + tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; + crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; + } + crc_dstar_ffff = ~crc_dstar_ffff; + tmp = crc_dstar_ffff; + + if (len == 56) { + packet[54] = (unsigned char)(crc_dstar_ffff & 0xff); + packet[55] = (unsigned char)((tmp >> 8) & 0xff); + } else { + packet[56] = (unsigned char)(crc_dstar_ffff & 0xff); + packet[57] = (unsigned char)((tmp >> 8) & 0xff); + } + + return; } /* log the event */ static void traceit(const char *fmt,...) { - time_t ltime; - struct tm tm; - const short BFSZ = 512; - char buf[BFSZ]; + time_t ltime; + struct tm tm; + const short BFSZ = 512; + char buf[BFSZ]; - time(<ime); - localtime_r(<ime, &tm); + time(<ime); + localtime_r(<ime, &tm); - snprintf(buf,BFSZ - 1,"%02d%02d%02d at %d:%02d:%02d:", - tm.tm_mon+1,tm.tm_mday,tm.tm_year % 100, - tm.tm_hour,tm.tm_min,tm.tm_sec); + snprintf(buf,BFSZ - 1,"%02d%02d%02d at %d:%02d:%02d:", + tm.tm_mon+1,tm.tm_mday,tm.tm_year % 100, + tm.tm_hour,tm.tm_min,tm.tm_sec); - va_list args; - va_start(args,fmt); - vsnprintf(buf + strlen(buf), BFSZ - strlen(buf) -1, fmt, args); - va_end(args); + va_list args; + va_start(args,fmt); + vsnprintf(buf + strlen(buf), BFSZ - strlen(buf) -1, fmt, args); + va_end(args); - fprintf(stdout, "%s", buf); - return; + fprintf(stdout, "%s", buf); + return; } /* process configuration file */ static int read_config(char *cfgFile) { - short int valid_params = 44; - short int params = 0; - unsigned short i; - - FILE *cnf = NULL; - char inbuf[1024]; - char *p = NULL; - char *ptr; - char *tok = NULL; - const char *delim = ","; - - cnf = fopen(cfgFile, "r"); - if (!cnf) - { - traceit("Failed to open file %s\n", cfgFile); - return 1; - } - - traceit("Reading file %s\n", cfgFile); - while (fgets(inbuf, 1020, cnf) != NULL) - { - if (strchr(inbuf, '#')) - continue; - - p = strchr(inbuf, '\r'); - if (p) - *p = '\0'; - p = strchr(inbuf, '\n'); - if (p) - *p = '\0'; - - p = strchr(inbuf, '='); - if (!p) - continue; - *p = '\0'; - - if (strcmp(inbuf,"OWNER") == 0) - { - memset(OWNER,' ', sizeof(OWNER)); - OWNER[OWNER_SIZE] = '\0'; - strcpy(owner, OWNER); - - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if ((strlen(p + 1) < 3) || (strlen(p + 1) > (OWNER_SIZE - 2))) - traceit("OWNER value [%s] invalid\n", p + 1); - else - { - memcpy(OWNER, p + 1, strlen(p + 1)); - - for (i = 0; i < strlen(OWNER); i++) - OWNER[i] = toupper(OWNER[i]); - - traceit("OWNER=[%s]\n",OWNER); - - for (i = 0; i < strlen(OWNER); i++) - { - if (OWNER[i] == ' ') - { - owner[i] = '\0'; - break; - } - owner[i] = tolower(OWNER[i]); - } - params ++; - } - } - else - if (strcmp(inbuf,"STATUS_FILE") == 0) - { - memset(STATUS_FILE, '\0', sizeof(STATUS_FILE)); - strncpy(STATUS_FILE, p + 1,FILENAME_MAX); - traceit("STATUS_FILE=[%s]\n",STATUS_FILE); - params ++; - } - else - if (strcmp(inbuf,"PACKAGE_REV") == 0) - { - memset(PACKAGE_REV, 0, sizeof(PACKAGE_REV)); - strncpy(PACKAGE_REV, p + 1, 55); - traceit("PACKAGE_REV=[%s]\n", PACKAGE_REV); - params ++; - } - else - if (strcmp(inbuf,"LOCAL_IRC_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("LOCAL_IRC_IP value [%s] invalid\n", p + 1); - else - { - strncpy(LOCAL_IRC_IP, p + 1, IP_SIZE); - LOCAL_IRC_IP[IP_SIZE] = '\0'; - traceit("LOCAL_IRC_IP=[%s]\n", LOCAL_IRC_IP); - params ++; - } - } - else - if (strcmp(inbuf,"SEND_QRGS_MAPS") == 0) - { - if (*(p + 1) == 'Y') - SEND_QRGS_MAPS = true; - else - SEND_QRGS_MAPS = false; - traceit("SEND_QRGS_MAPS=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"QTH") == 0) - { - memset(QTH, '\0', sizeof(QTH)); - strncpy(QTH, p + 1, 256); - traceit("QTH=[%s]\n", QTH); - params++; - } - else - if (strcmp(inbuf,"QRG_A") == 0) - { - memset(QRG_A, '\0', sizeof(QRG_A)); - strncpy(QRG_A, p + 1, 256); - traceit("QRG_A=[%s]\n", QRG_A); - params++; - } - else - if (strcmp(inbuf,"QRG_B") == 0) - { - memset(QRG_B, '\0', sizeof(QRG_B)); - strncpy(QRG_B, p + 1, 256); - traceit("QRG_B=[%s]\n", QRG_B); - params++; - } - else - if (strcmp(inbuf,"QRG_C") == 0) - { - memset(QRG_C, '\0', sizeof(QRG_C)); - strncpy(QRG_C, p + 1, 256); - traceit("QRG_C=[%s]\n", QRG_C); - params++; - } - else - if (strcmp(inbuf,"APRS_HOST") == 0) - { - memset(RPTR_ID.aprs_host, '\0', sizeof(RPTR_ID.aprs_host)); - strncpy(RPTR_ID.aprs_host, p + 1, MAXHOSTNAMELEN); - traceit("APRS_HOST=[%s]\n", RPTR_ID.aprs_host); - params++; - } - else - if (strcmp(inbuf,"APRS_PORT") == 0) - { - RPTR_ID.aprs_port = atoi(p + 1); - traceit("APRS_PORT=[%d]\n", RPTR_ID.aprs_port); - params++; - } - else - if (strcmp(inbuf,"APRS_INTERVAL") == 0) - { - RPTR_ID.aprs_interval = atoi(p + 1); - traceit("APRS_INTERVAL=[%d]\n", RPTR_ID.aprs_interval); - if (RPTR_ID.aprs_interval < 40) - { - RPTR_ID.aprs_interval = 40; - traceit("APRS_INTERVAL is low number, re-setting to 40\n"); - } - params++; - } - else - if (strcmp(inbuf,"APRS_FILTER") == 0) - { - memset(RPTR_ID.aprs_filter, '\0', sizeof(RPTR_ID.aprs_filter)); - strncpy(RPTR_ID.aprs_filter, p + 1, 511); - traceit("APRS_filter=[%s]\n", RPTR_ID.aprs_filter); - params++; - } - else - if (strcmp(inbuf, "RPTR_ID_A") == 0) - { - traceit("RPTR_ID_A=[%s]\n", p + 1); - - tok = strtok(p + 1, delim); - if (tok) - { - RPTR_ID.lat[0] = atof(tok); - tok = strtok(NULL, delim); - if (tok) - { - RPTR_ID.lon[0] = atof(tok); - tok = strtok(NULL,delim); - if (tok) - { - RPTR_ID.range[0] = atoi(tok); - tok = strtok(NULL, delim); - if (tok) - { - memset(RPTR_ID.desc[0], '\0', 64); - strncpy(RPTR_ID.desc[0], tok, 63); - params++; - - traceit("ModA: lat=[%lf], lon=[%lf], range=[%d], descr=[%s]\n", - RPTR_ID.lat[0], RPTR_ID.lon[0], - RPTR_ID.range[0], RPTR_ID.desc[0]); - } - else - traceit("ModA:Invalid value for description\n"); - } - else - traceit("ModA:Invalid value for range\n"); - } - else - traceit("ModA:Invalid values for longitude\n"); - } - else - { - params++; - traceit("ModA aprs parameters NOT defined...ok\n"); - } - } - else - if (strcmp(inbuf, "RPTR_ID_B") == 0) - { - traceit("RPTR_ID_B=[%s]\n", p + 1); - - tok = strtok(p + 1, delim); - if (tok) - { - RPTR_ID.lat[1] = atof(tok); - tok = strtok(NULL, delim); - if (tok) - { - RPTR_ID.lon[1] = atof(tok); - tok = strtok(NULL, delim); - if (tok) - { - RPTR_ID.range[1] = atoi(tok); - tok = strtok(NULL, delim); - if (tok) - { - memset(RPTR_ID.desc[1], '\0', 64); - strncpy(RPTR_ID.desc[1], tok, 63); - params++; - - traceit("ModB: lat=[%lf], lon=[%lf], range=[%d], descr=[%s]\n", - RPTR_ID.lat[1], RPTR_ID.lon[1], - RPTR_ID.range[1], RPTR_ID.desc[1]); - } - else - traceit("ModB:Invalid value for description\n"); - } - else - traceit("ModB:Invalid value for range\n"); - } - else - traceit("ModB:Invalid values for longitude\n"); - } - else - { - params++; - traceit("ModB aprs parameters NOT defined...ok\n"); - } - } - else - if (strcmp(inbuf, "RPTR_ID_C") == 0) - { - traceit("RPTR_ID_C=[%s]\n", p + 1); - - tok = strtok(p + 1, delim); - if (tok) - { - RPTR_ID.lat[2] = atof(tok); - tok = strtok(NULL, delim); - if (tok) - { - RPTR_ID.lon[2] = atof(tok); - tok = strtok(NULL, delim); - if (tok) - { - RPTR_ID.range[2] = atoi(tok); - tok = strtok(NULL, delim); - if (tok) - { - memset(RPTR_ID.desc[2], '\0', 64); - strncpy(RPTR_ID.desc[2], tok, 63); - params++; - - traceit("ModC: lat=[%lf], lon=[%lf], range=[%d], descr=[%s]\n", - RPTR_ID.lat[2], RPTR_ID.lon[2], - RPTR_ID.range[2], RPTR_ID.desc[2]); - } - else - traceit("ModC:Invalid value for description\n"); - } - else - traceit("ModC:Invalid value for range\n"); - } - else - traceit("ModC:Invalid values for longitude\n"); - } - else - { - params++; - traceit("ModC aprs parameters NOT defined...ok\n"); - } - } - else - if (strcmp(inbuf,"G2_EXTERNAL_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("G2_EXTERNAL_IP value [%s] invalid\n", p + 1); - else - { - strncpy(G2_EXTERNAL_IP, p + 1, IP_SIZE); - G2_EXTERNAL_IP[IP_SIZE] = '\0'; - traceit("G2_EXTERNAL_IP=[%s]\n", G2_EXTERNAL_IP); - params ++; - } - } - else - if (strcmp(inbuf,"G2_EXTERNAL_PORT") == 0) - { - G2_EXTERNAL_PORT = atoi(p + 1); - traceit("G2_EXTERNAL_PORT=[%d]\n",G2_EXTERNAL_PORT); - params ++; - } - else - if (strcmp(inbuf,"G2_INTERNAL_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("G2_INTERNAL_IP value [%s] invalid\n", p + 1); - else - { - strncpy(G2_INTERNAL_IP, p + 1, IP_SIZE); - G2_INTERNAL_IP[IP_SIZE] = '\0'; - traceit("G2_INTERNAL_IP=[%s]\n", G2_INTERNAL_IP); - params ++; - } - } - else - if (strcmp(inbuf,"G2_INTERNAL_PORT") == 0) - { - G2_INTERNAL_PORT = atoi(p + 1); - traceit("G2_INTERNAL_PORT=[%d]\n",G2_INTERNAL_PORT); - params ++; - } - else - if (strcmp(inbuf,"TO_G2_LINK_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("TO_G2_LINK_IP value [%s] invalid\n", p + 1); - else - { - strncpy(TO_G2_LINK_IP, p + 1, IP_SIZE); - TO_G2_LINK_IP[IP_SIZE] = '\0'; - traceit("TO_G2_LINK_IP=[%s]\n", TO_G2_LINK_IP); - params ++; - } - } - else - if (strcmp(inbuf,"TO_G2_LINK_PORT") == 0) - { - TO_G2_LINK_PORT = atoi(p + 1); - traceit("TO_G2_LINK_PORT=[%d]\n",TO_G2_LINK_PORT); - params ++; - } - else - if (strcmp(inbuf,"TO_RPTR_IP_A") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("TO_RPTR_IP_A value [%s] invalid\n", p + 1); - else - { - strncpy(TO_RPTR_IP[0], p + 1, IP_SIZE); - TO_RPTR_IP[0][IP_SIZE] = '\0'; - traceit("TO_RPTR_IP_A=[%s]\n", TO_RPTR_IP[0]); - params ++; - } - } - else - if (strcmp(inbuf,"TO_RPTR_PORT_A") == 0) - { - TO_RPTR_PORT[0] = atoi(p + 1); - traceit("TO_RPTR_PORT_A=[%d]\n",TO_RPTR_PORT[0]); - params ++; - } - else - if (strcmp(inbuf,"TO_RPTR_IP_B") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("TO_RPTR_IP_B value [%s] invalid\n", p + 1); - else - { - strncpy(TO_RPTR_IP[1], p + 1, IP_SIZE); - TO_RPTR_IP[1][IP_SIZE] = '\0'; - traceit("TO_RPTR_IP_B=[%s]\n", TO_RPTR_IP[1]); - params ++; - } - } - else - if (strcmp(inbuf,"TO_RPTR_PORT_B") == 0) - { - TO_RPTR_PORT[1] = atoi(p + 1); - traceit("TO_RPTR_PORT_B=[%d]\n",TO_RPTR_PORT[1]); - params ++; - } - else - if (strcmp(inbuf,"TO_RPTR_IP_C") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("TO_RPTR_IP_C value [%s] invalid\n", p + 1); - else - { - strncpy(TO_RPTR_IP[2], p + 1, IP_SIZE); - TO_RPTR_IP[2][IP_SIZE] = '\0'; - traceit("TO_RPTR_IP_C=[%s]\n", TO_RPTR_IP[2]); - params ++; - } - } - else - if (strcmp(inbuf,"TO_RPTR_PORT_C") == 0) - { - TO_RPTR_PORT[2] = atoi(p + 1); - traceit("TO_RPTR_PORT_C=[%d]\n",TO_RPTR_PORT[2]); - params ++; - } - else - if (strcmp(inbuf,"QSO_DETAILS") == 0) - { - if (*(p + 1) == 'Y') - QSO_DETAILS = true; - else - QSO_DETAILS = false; - traceit("QSO_DETAILS=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"IRC_DEBUG") == 0) - { - if (*(p + 1) == 'Y') - IRC_DEBUG = true; - else - IRC_DEBUG = false; - traceit("IRC_DEBUG=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"DTMF_DEBUG") == 0) - { - if (*(p + 1) == 'Y') - DTMF_DEBUG = true; - else - DTMF_DEBUG = false; - traceit("DTMF_DEBUG=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"REGEN_HDR") == 0) - { - if (*(p + 1) == 'Y') - REGEN_HDR = true; - else - REGEN_HDR = false; - traceit("REGEN_HDR=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"SEND_APRS") == 0) - { - if (*(p + 1) == 'Y') - SEND_APRS = true; - else - SEND_APRS = false; - traceit("SEND_APRS=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"ECHOTEST_DIR") == 0) - { - memset(ECHOTEST_DIR, '\0', sizeof(ECHOTEST_DIR)); - strncpy(ECHOTEST_DIR, p + 1, FILENAME_MAX); - traceit("ECHOTEST_DIR=[%s]\n", ECHOTEST_DIR); - params ++; - } - else - if (strcmp(inbuf, "PLAY_WAIT") == 0) - { - PLAY_WAIT = atoi(p + 1); - if ((PLAY_WAIT > 10) || (PLAY_WAIT < 1)) - PLAY_WAIT = 1; - traceit("PLAY_WAIT=[%d]\n", PLAY_WAIT); - params ++; - } - else - if (strcmp(inbuf, "PLAY_DELAY") == 0) - { - PLAY_DELAY = atoi(p + 1); - if ((PLAY_DELAY > 50) || (PLAY_DELAY < 10)) - PLAY_DELAY = 20; - traceit("PLAY_DELAY=[%d]\n", PLAY_DELAY); - params ++; - } - else - if (strcmp(inbuf,"ECHOTEST_REC_TIMEOUT") == 0) - { - ECHOTEST_REC_TIMEOUT = atoi(p + 1); - traceit("ECHOTEST_REC_TIMEOUT=[%d]\n", ECHOTEST_REC_TIMEOUT); - params ++; - } - else - if (strcmp(inbuf,"VOICEMAIL_REC_TIMEOUT") == 0) - { - VOICEMAIL_REC_TIMEOUT = atoi(p + 1); - traceit("VOICEMAIL_REC_TIMEOUT=[%d]\n", VOICEMAIL_REC_TIMEOUT); - params ++; - } - else - if (strcmp(inbuf,"FROM_REMOTE_G2_TIMEOUT") == 0) - { - FROM_REMOTE_G2_TIMEOUT = atoi(p + 1); - traceit("FROM_REMOTE_G2_TIMEOUT=[%d]\n", FROM_REMOTE_G2_TIMEOUT); - params ++; - } - else - if (strcmp(inbuf,"FROM_LOCAL_RPTR_TIMEOUT") == 0) - { - FROM_LOCAL_RPTR_TIMEOUT = atoi(p + 1); - traceit("FROM_LOCAL_RPTR_TIMEOUT=[%d]\n", FROM_LOCAL_RPTR_TIMEOUT); - params ++; - } - else - if (strcmp(inbuf,"IRC_DDB_HOST") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("IRC_DDB_HOST value [%s] invalid\n", p + 1); - else - { - memset(IRC_DDB_HOST, '\0', sizeof(IRC_DDB_HOST)); - strncpy(IRC_DDB_HOST, p + 1, sizeof(IRC_DDB_HOST) - 1); - traceit("IRC_DDB_HOST=[%s]\n", IRC_DDB_HOST); - params ++; - } - } - else - if (strcmp(inbuf,"IRC_DDB_PORT") == 0) - { - IRC_DDB_PORT = atoi(p + 1); - traceit("IRC_DDB_PORT=[%d]\n",IRC_DDB_PORT); - params ++; - } - else - if (strcmp(inbuf,"IRC_PASS") == 0) - { - memset(IRC_PASS, '\0', sizeof(IRC_PASS)); - strncpy(IRC_PASS, p + 1, sizeof(IRC_PASS) - 1); - params ++; - } - else - if (strcmp(inbuf,"DTMF_DIR") == 0) - { - memset(DTMF_DIR, '\0', sizeof(DTMF_DIR)); - strncpy(DTMF_DIR, p + 1, FILENAME_MAX); - traceit("DTMF_DIR=[%s]\n", DTMF_DIR); - params ++; - } - } - fclose(cnf); - - if (params != valid_params) - { - traceit("Configuration file %s invalid\n",cfgFile); - return 1; - } - return 0; + short int valid_params = 44; + short int params = 0; + unsigned short i; + + FILE *cnf = NULL; + char inbuf[1024]; + char *p = NULL; + char *ptr; + char *tok = NULL; + const char *delim = ","; + + cnf = fopen(cfgFile, "r"); + if (!cnf) { + traceit("Failed to open file %s\n", cfgFile); + return 1; + } + + traceit("Reading file %s\n", cfgFile); + while (fgets(inbuf, 1020, cnf) != NULL) { + if (strchr(inbuf, '#')) + continue; + + p = strchr(inbuf, '\r'); + if (p) + *p = '\0'; + p = strchr(inbuf, '\n'); + if (p) + *p = '\0'; + + p = strchr(inbuf, '='); + if (!p) + continue; + *p = '\0'; + + if (strcmp(inbuf,"OWNER") == 0) { + memset(OWNER,' ', sizeof(OWNER)); + OWNER[OWNER_SIZE] = '\0'; + strcpy(owner, OWNER); + + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if ((strlen(p + 1) < 3) || (strlen(p + 1) > (OWNER_SIZE - 2))) + traceit("OWNER value [%s] invalid\n", p + 1); + else { + memcpy(OWNER, p + 1, strlen(p + 1)); + + for (i = 0; i < strlen(OWNER); i++) + OWNER[i] = toupper(OWNER[i]); + + traceit("OWNER=[%s]\n",OWNER); + + for (i = 0; i < strlen(OWNER); i++) { + if (OWNER[i] == ' ') { + owner[i] = '\0'; + break; + } + owner[i] = tolower(OWNER[i]); + } + params ++; + } + } else if (strcmp(inbuf,"STATUS_FILE") == 0) { + memset(STATUS_FILE, '\0', sizeof(STATUS_FILE)); + strncpy(STATUS_FILE, p + 1,FILENAME_MAX); + traceit("STATUS_FILE=[%s]\n",STATUS_FILE); + params ++; + } else if (strcmp(inbuf,"PACKAGE_REV") == 0) { + memset(PACKAGE_REV, 0, sizeof(PACKAGE_REV)); + strncpy(PACKAGE_REV, p + 1, 55); + traceit("PACKAGE_REV=[%s]\n", PACKAGE_REV); + params ++; + } else if (strcmp(inbuf,"LOCAL_IRC_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("LOCAL_IRC_IP value [%s] invalid\n", p + 1); + else { + strncpy(LOCAL_IRC_IP, p + 1, IP_SIZE); + LOCAL_IRC_IP[IP_SIZE] = '\0'; + traceit("LOCAL_IRC_IP=[%s]\n", LOCAL_IRC_IP); + params ++; + } + } else if (strcmp(inbuf,"SEND_QRGS_MAPS") == 0) { + if (*(p + 1) == 'Y') + SEND_QRGS_MAPS = true; + else + SEND_QRGS_MAPS = false; + traceit("SEND_QRGS_MAPS=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"QTH") == 0) { + memset(QTH, '\0', sizeof(QTH)); + strncpy(QTH, p + 1, 256); + traceit("QTH=[%s]\n", QTH); + params++; + } else if (strcmp(inbuf,"QRG_A") == 0) { + memset(QRG_A, '\0', sizeof(QRG_A)); + strncpy(QRG_A, p + 1, 256); + traceit("QRG_A=[%s]\n", QRG_A); + params++; + } else if (strcmp(inbuf,"QRG_B") == 0) { + memset(QRG_B, '\0', sizeof(QRG_B)); + strncpy(QRG_B, p + 1, 256); + traceit("QRG_B=[%s]\n", QRG_B); + params++; + } else if (strcmp(inbuf,"QRG_C") == 0) { + memset(QRG_C, '\0', sizeof(QRG_C)); + strncpy(QRG_C, p + 1, 256); + traceit("QRG_C=[%s]\n", QRG_C); + params++; + } else if (strcmp(inbuf,"APRS_HOST") == 0) { + memset(RPTR_ID.aprs_host, '\0', sizeof(RPTR_ID.aprs_host)); + strncpy(RPTR_ID.aprs_host, p + 1, MAXHOSTNAMELEN); + traceit("APRS_HOST=[%s]\n", RPTR_ID.aprs_host); + params++; + } else if (strcmp(inbuf,"APRS_PORT") == 0) { + RPTR_ID.aprs_port = atoi(p + 1); + traceit("APRS_PORT=[%d]\n", RPTR_ID.aprs_port); + params++; + } else if (strcmp(inbuf,"APRS_INTERVAL") == 0) { + RPTR_ID.aprs_interval = atoi(p + 1); + traceit("APRS_INTERVAL=[%d]\n", RPTR_ID.aprs_interval); + if (RPTR_ID.aprs_interval < 40) { + RPTR_ID.aprs_interval = 40; + traceit("APRS_INTERVAL is low number, re-setting to 40\n"); + } + params++; + } else if (strcmp(inbuf,"APRS_FILTER") == 0) { + memset(RPTR_ID.aprs_filter, '\0', sizeof(RPTR_ID.aprs_filter)); + strncpy(RPTR_ID.aprs_filter, p + 1, 511); + traceit("APRS_filter=[%s]\n", RPTR_ID.aprs_filter); + params++; + } else if (strcmp(inbuf, "RPTR_ID_A") == 0) { + traceit("RPTR_ID_A=[%s]\n", p + 1); + + tok = strtok(p + 1, delim); + if (tok) { + RPTR_ID.lat[0] = atof(tok); + tok = strtok(NULL, delim); + if (tok) { + RPTR_ID.lon[0] = atof(tok); + tok = strtok(NULL,delim); + if (tok) { + RPTR_ID.range[0] = atoi(tok); + tok = strtok(NULL, delim); + if (tok) { + memset(RPTR_ID.desc[0], '\0', 64); + strncpy(RPTR_ID.desc[0], tok, 63); + params++; + + traceit("ModA: lat=[%lf], lon=[%lf], range=[%d], descr=[%s]\n", + RPTR_ID.lat[0], RPTR_ID.lon[0], + RPTR_ID.range[0], RPTR_ID.desc[0]); + } else + traceit("ModA:Invalid value for description\n"); + } else + traceit("ModA:Invalid value for range\n"); + } else + traceit("ModA:Invalid values for longitude\n"); + } else { + params++; + traceit("ModA aprs parameters NOT defined...ok\n"); + } + } else if (strcmp(inbuf, "RPTR_ID_B") == 0) { + traceit("RPTR_ID_B=[%s]\n", p + 1); + + tok = strtok(p + 1, delim); + if (tok) { + RPTR_ID.lat[1] = atof(tok); + tok = strtok(NULL, delim); + if (tok) { + RPTR_ID.lon[1] = atof(tok); + tok = strtok(NULL, delim); + if (tok) { + RPTR_ID.range[1] = atoi(tok); + tok = strtok(NULL, delim); + if (tok) { + memset(RPTR_ID.desc[1], '\0', 64); + strncpy(RPTR_ID.desc[1], tok, 63); + params++; + + traceit("ModB: lat=[%lf], lon=[%lf], range=[%d], descr=[%s]\n", + RPTR_ID.lat[1], RPTR_ID.lon[1], + RPTR_ID.range[1], RPTR_ID.desc[1]); + } else + traceit("ModB:Invalid value for description\n"); + } else + traceit("ModB:Invalid value for range\n"); + } else + traceit("ModB:Invalid values for longitude\n"); + } else { + params++; + traceit("ModB aprs parameters NOT defined...ok\n"); + } + } else if (strcmp(inbuf, "RPTR_ID_C") == 0) { + traceit("RPTR_ID_C=[%s]\n", p + 1); + + tok = strtok(p + 1, delim); + if (tok) { + RPTR_ID.lat[2] = atof(tok); + tok = strtok(NULL, delim); + if (tok) { + RPTR_ID.lon[2] = atof(tok); + tok = strtok(NULL, delim); + if (tok) { + RPTR_ID.range[2] = atoi(tok); + tok = strtok(NULL, delim); + if (tok) { + memset(RPTR_ID.desc[2], '\0', 64); + strncpy(RPTR_ID.desc[2], tok, 63); + params++; + + traceit("ModC: lat=[%lf], lon=[%lf], range=[%d], descr=[%s]\n", + RPTR_ID.lat[2], RPTR_ID.lon[2], + RPTR_ID.range[2], RPTR_ID.desc[2]); + } else + traceit("ModC:Invalid value for description\n"); + } else + traceit("ModC:Invalid value for range\n"); + } else + traceit("ModC:Invalid values for longitude\n"); + } else { + params++; + traceit("ModC aprs parameters NOT defined...ok\n"); + } + } else if (strcmp(inbuf,"G2_EXTERNAL_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("G2_EXTERNAL_IP value [%s] invalid\n", p + 1); + else { + strncpy(G2_EXTERNAL_IP, p + 1, IP_SIZE); + G2_EXTERNAL_IP[IP_SIZE] = '\0'; + traceit("G2_EXTERNAL_IP=[%s]\n", G2_EXTERNAL_IP); + params ++; + } + } else if (strcmp(inbuf,"G2_EXTERNAL_PORT") == 0) { + G2_EXTERNAL_PORT = atoi(p + 1); + traceit("G2_EXTERNAL_PORT=[%d]\n",G2_EXTERNAL_PORT); + params ++; + } else if (strcmp(inbuf,"G2_INTERNAL_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("G2_INTERNAL_IP value [%s] invalid\n", p + 1); + else { + strncpy(G2_INTERNAL_IP, p + 1, IP_SIZE); + G2_INTERNAL_IP[IP_SIZE] = '\0'; + traceit("G2_INTERNAL_IP=[%s]\n", G2_INTERNAL_IP); + params ++; + } + } else if (strcmp(inbuf,"G2_INTERNAL_PORT") == 0) { + G2_INTERNAL_PORT = atoi(p + 1); + traceit("G2_INTERNAL_PORT=[%d]\n",G2_INTERNAL_PORT); + params ++; + } else if (strcmp(inbuf,"TO_G2_LINK_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("TO_G2_LINK_IP value [%s] invalid\n", p + 1); + else { + strncpy(TO_G2_LINK_IP, p + 1, IP_SIZE); + TO_G2_LINK_IP[IP_SIZE] = '\0'; + traceit("TO_G2_LINK_IP=[%s]\n", TO_G2_LINK_IP); + params ++; + } + } else if (strcmp(inbuf,"TO_G2_LINK_PORT") == 0) { + TO_G2_LINK_PORT = atoi(p + 1); + traceit("TO_G2_LINK_PORT=[%d]\n",TO_G2_LINK_PORT); + params ++; + } else if (strcmp(inbuf,"TO_RPTR_IP_A") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("TO_RPTR_IP_A value [%s] invalid\n", p + 1); + else { + strncpy(TO_RPTR_IP[0], p + 1, IP_SIZE); + TO_RPTR_IP[0][IP_SIZE] = '\0'; + traceit("TO_RPTR_IP_A=[%s]\n", TO_RPTR_IP[0]); + params ++; + } + } else if (strcmp(inbuf,"TO_RPTR_PORT_A") == 0) { + TO_RPTR_PORT[0] = atoi(p + 1); + traceit("TO_RPTR_PORT_A=[%d]\n",TO_RPTR_PORT[0]); + params ++; + } else if (strcmp(inbuf,"TO_RPTR_IP_B") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("TO_RPTR_IP_B value [%s] invalid\n", p + 1); + else { + strncpy(TO_RPTR_IP[1], p + 1, IP_SIZE); + TO_RPTR_IP[1][IP_SIZE] = '\0'; + traceit("TO_RPTR_IP_B=[%s]\n", TO_RPTR_IP[1]); + params ++; + } + } else if (strcmp(inbuf,"TO_RPTR_PORT_B") == 0) { + TO_RPTR_PORT[1] = atoi(p + 1); + traceit("TO_RPTR_PORT_B=[%d]\n",TO_RPTR_PORT[1]); + params ++; + } else if (strcmp(inbuf,"TO_RPTR_IP_C") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("TO_RPTR_IP_C value [%s] invalid\n", p + 1); + else { + strncpy(TO_RPTR_IP[2], p + 1, IP_SIZE); + TO_RPTR_IP[2][IP_SIZE] = '\0'; + traceit("TO_RPTR_IP_C=[%s]\n", TO_RPTR_IP[2]); + params ++; + } + } else if (strcmp(inbuf,"TO_RPTR_PORT_C") == 0) { + TO_RPTR_PORT[2] = atoi(p + 1); + traceit("TO_RPTR_PORT_C=[%d]\n",TO_RPTR_PORT[2]); + params ++; + } else if (strcmp(inbuf,"QSO_DETAILS") == 0) { + if (*(p + 1) == 'Y') + QSO_DETAILS = true; + else + QSO_DETAILS = false; + traceit("QSO_DETAILS=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"IRC_DEBUG") == 0) { + if (*(p + 1) == 'Y') + IRC_DEBUG = true; + else + IRC_DEBUG = false; + traceit("IRC_DEBUG=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"DTMF_DEBUG") == 0) { + if (*(p + 1) == 'Y') + DTMF_DEBUG = true; + else + DTMF_DEBUG = false; + traceit("DTMF_DEBUG=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"REGEN_HDR") == 0) { + if (*(p + 1) == 'Y') + REGEN_HDR = true; + else + REGEN_HDR = false; + traceit("REGEN_HDR=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"SEND_APRS") == 0) { + if (*(p + 1) == 'Y') + SEND_APRS = true; + else + SEND_APRS = false; + traceit("SEND_APRS=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"ECHOTEST_DIR") == 0) { + memset(ECHOTEST_DIR, '\0', sizeof(ECHOTEST_DIR)); + strncpy(ECHOTEST_DIR, p + 1, FILENAME_MAX); + traceit("ECHOTEST_DIR=[%s]\n", ECHOTEST_DIR); + params ++; + } else if (strcmp(inbuf, "PLAY_WAIT") == 0) { + PLAY_WAIT = atoi(p + 1); + if ((PLAY_WAIT > 10) || (PLAY_WAIT < 1)) + PLAY_WAIT = 1; + traceit("PLAY_WAIT=[%d]\n", PLAY_WAIT); + params ++; + } else if (strcmp(inbuf, "PLAY_DELAY") == 0) { + PLAY_DELAY = atoi(p + 1); + if ((PLAY_DELAY > 50) || (PLAY_DELAY < 10)) + PLAY_DELAY = 20; + traceit("PLAY_DELAY=[%d]\n", PLAY_DELAY); + params ++; + } else if (strcmp(inbuf,"ECHOTEST_REC_TIMEOUT") == 0) { + ECHOTEST_REC_TIMEOUT = atoi(p + 1); + traceit("ECHOTEST_REC_TIMEOUT=[%d]\n", ECHOTEST_REC_TIMEOUT); + params ++; + } else if (strcmp(inbuf,"VOICEMAIL_REC_TIMEOUT") == 0) { + VOICEMAIL_REC_TIMEOUT = atoi(p + 1); + traceit("VOICEMAIL_REC_TIMEOUT=[%d]\n", VOICEMAIL_REC_TIMEOUT); + params ++; + } else if (strcmp(inbuf,"FROM_REMOTE_G2_TIMEOUT") == 0) { + FROM_REMOTE_G2_TIMEOUT = atoi(p + 1); + traceit("FROM_REMOTE_G2_TIMEOUT=[%d]\n", FROM_REMOTE_G2_TIMEOUT); + params ++; + } else if (strcmp(inbuf,"FROM_LOCAL_RPTR_TIMEOUT") == 0) { + FROM_LOCAL_RPTR_TIMEOUT = atoi(p + 1); + traceit("FROM_LOCAL_RPTR_TIMEOUT=[%d]\n", FROM_LOCAL_RPTR_TIMEOUT); + params ++; + } else if (strcmp(inbuf,"IRC_DDB_HOST") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("IRC_DDB_HOST value [%s] invalid\n", p + 1); + else { + memset(IRC_DDB_HOST, '\0', sizeof(IRC_DDB_HOST)); + strncpy(IRC_DDB_HOST, p + 1, sizeof(IRC_DDB_HOST) - 1); + traceit("IRC_DDB_HOST=[%s]\n", IRC_DDB_HOST); + params ++; + } + } else if (strcmp(inbuf,"IRC_DDB_PORT") == 0) { + IRC_DDB_PORT = atoi(p + 1); + traceit("IRC_DDB_PORT=[%d]\n",IRC_DDB_PORT); + params ++; + } else if (strcmp(inbuf,"IRC_PASS") == 0) { + memset(IRC_PASS, '\0', sizeof(IRC_PASS)); + strncpy(IRC_PASS, p + 1, sizeof(IRC_PASS) - 1); + params ++; + } else if (strcmp(inbuf,"DTMF_DIR") == 0) { + memset(DTMF_DIR, '\0', sizeof(DTMF_DIR)); + strncpy(DTMF_DIR, p + 1, FILENAME_MAX); + traceit("DTMF_DIR=[%s]\n", DTMF_DIR); + params ++; + } + } + fclose(cnf); + + if (params != valid_params) { + traceit("Configuration file %s invalid\n",cfgFile); + return 1; + } + return 0; } /* Create the 40000 external port */ static int g2_open() { - struct sockaddr_in sin; - - g2_sock = socket(PF_INET,SOCK_DGRAM,0); - if (g2_sock == -1) - { - traceit("Failed to create g2 socket,errno=%d\n",errno); - return 1; - } - fcntl(g2_sock,F_SETFL,O_NONBLOCK); - - memset(&sin,0,sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_port = htons(G2_EXTERNAL_PORT); - sin.sin_addr.s_addr = inet_addr(G2_EXTERNAL_IP); - - if (bind(g2_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) - { - traceit("Failed to bind g2 socket on port %d, errno=%d\n",G2_EXTERNAL_PORT,errno); - close(g2_sock); - g2_sock = -1; - return 1; - } - return 0; + struct sockaddr_in sin; + + g2_sock = socket(PF_INET,SOCK_DGRAM,0); + if (g2_sock == -1) { + traceit("Failed to create g2 socket,errno=%d\n",errno); + return 1; + } + fcntl(g2_sock,F_SETFL,O_NONBLOCK); + + memset(&sin,0,sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = htons(G2_EXTERNAL_PORT); + sin.sin_addr.s_addr = inet_addr(G2_EXTERNAL_IP); + + if (bind(g2_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) { + traceit("Failed to bind g2 socket on port %d, errno=%d\n",G2_EXTERNAL_PORT,errno); + close(g2_sock); + g2_sock = -1; + return 1; + } + return 0; } /* Create the 19000 internal port */ static int srv_open() { - struct sockaddr_in sin; - - srv_sock = socket(PF_INET,SOCK_DGRAM,0); - if (srv_sock == -1) - { - traceit("Failed to create srv socket,errno=%d\n",errno); - return 1; - } - fcntl(srv_sock,F_SETFL,O_NONBLOCK); - - memset(&sin,0,sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_port = htons(G2_INTERNAL_PORT); - sin.sin_addr.s_addr = inet_addr(G2_INTERNAL_IP); - - if (bind(srv_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) - { - traceit("Failed to bind srv socket on port %d, errno=%d\n", - G2_INTERNAL_PORT,errno); - close(srv_sock); - srv_sock = -1; - return 1; - } - - return 0; + struct sockaddr_in sin; + + srv_sock = socket(PF_INET,SOCK_DGRAM,0); + if (srv_sock == -1) { + traceit("Failed to create srv socket,errno=%d\n",errno); + return 1; + } + fcntl(srv_sock,F_SETFL,O_NONBLOCK); + + memset(&sin,0,sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = htons(G2_INTERNAL_PORT); + sin.sin_addr.s_addr = inet_addr(G2_INTERNAL_IP); + + if (bind(srv_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) { + traceit("Failed to bind srv socket on port %d, errno=%d\n", + G2_INTERNAL_PORT,errno); + close(srv_sock); + srv_sock = -1; + return 1; + } + + return 0; } /* receive data from the irc server and save it */ static void *get_irc_data(void *arg) { - struct timespec req; - - wxString user; - wxString rptr; - wxString gateway; - wxString ipaddr; - DSTAR_PROTOCOL proto; - IRCDDB_RESPONSE_TYPE type; - int rc = 0; - struct sigaction act; - short threshold = 0; - short THRESHOLD_MAX = 100; - short last_status = 0; - - arg = arg; - - act.sa_handler = sigCatch; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - traceit("get_irc_data thread exiting...\n"); - keep_running = false; - pthread_exit(NULL); - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - traceit("get_irc_data thread exiting...\n"); - keep_running = false; - pthread_exit(NULL); - } - if (sigaction(SIGPIPE, &act, 0) != 0) - { - traceit("sigaction-PIPE failed, error=%d\n", errno); - traceit("get_irc_data thread exiting...\n"); - keep_running = false; - pthread_exit(NULL); - } - - while (keep_running) - { - threshold ++; - if (threshold >= THRESHOLD_MAX) - { - rc = ii->getConnectionState(); - if ((rc == 0) || (rc == 10)) - { - if (last_status != 0) - { - traceit("irc status=%d, probable disconnect...\n", rc); - last_status = 0; - } - } - else - if (rc == 7) - { - if (last_status != 2) - { - traceit("irc status=%d, probable connect...\n", rc); - last_status = 2; - } - } - else - { - if (last_status != 1) - { - traceit("irc status=%d, probable connect...\n", rc); - last_status = 1; - } - } - threshold = 0; - } - - while (((type = ii->getMessageType()) != IDRT_NONE) && keep_running) - { - if (type == IDRT_USER) - { - ii->receiveUser(user, rptr, gateway, ipaddr); - if (!user.IsEmpty()) - { - if (!rptr.IsEmpty() && !gateway.IsEmpty() && !ipaddr.IsEmpty()) - { - if (IRC_DEBUG) - traceit("C-u:%s,%s,%s,%s\n", user.mb_str(), rptr.mb_str(), gateway.mb_str(), ipaddr.mb_str()); - - pthread_mutex_lock(&irc_data_mutex); - - user2rptr_map[user] = rptr; - rptr2gwy_map[rptr] = gateway; - gwy2ip_map[gateway] = ipaddr; - - pthread_mutex_unlock(&irc_data_mutex); - - // traceit("%d users, %d repeaters, %d gateways\n", user2rptr_map.size(), rptr2gwy_map.size(), gwy2ip_map.size()); - - } - } - } - else - if (type == IDRT_REPEATER) - { - ii->receiveRepeater(rptr, gateway, ipaddr, proto); - if (!rptr.IsEmpty()) - { - if (!gateway.IsEmpty() && !ipaddr.IsEmpty()) - { - if (IRC_DEBUG) - traceit("C-r:%s,%s,%s\n", rptr.mb_str(), gateway.mb_str(), ipaddr.mb_str()); - - pthread_mutex_lock(&irc_data_mutex); - - rptr2gwy_map[rptr] = gateway; - gwy2ip_map[gateway] = ipaddr; - - pthread_mutex_unlock(&irc_data_mutex); - - // traceit("%d repeaters, %d gateways\n", rptr2gwy_map.size(), gwy2ip_map.size()); - - } - } - } - else - if (type == IDRT_GATEWAY) - { - ii->receiveGateway(gateway, ipaddr, proto); - if (!gateway.IsEmpty() && !ipaddr.IsEmpty()) - { - if (IRC_DEBUG) - traceit("C-g:%s,%s\n", gateway.mb_str(),ipaddr.mb_str()); - - pthread_mutex_lock(&irc_data_mutex); - - gwy2ip_map[gateway] = ipaddr; - - pthread_mutex_unlock(&irc_data_mutex); - - // traceit("%d gateways\n", gwy2ip_map.size()); - - } - } - } - req.tv_sec = 0; - req.tv_nsec = 500000000; // 500 milli - nanosleep(&req, NULL); - } - traceit("get_irc_data thread exiting...\n"); - pthread_exit(NULL); + struct timespec req; + + wxString user; + wxString rptr; + wxString gateway; + wxString ipaddr; + DSTAR_PROTOCOL proto; + IRCDDB_RESPONSE_TYPE type; + int rc = 0; + struct sigaction act; + short threshold = 0; + short THRESHOLD_MAX = 100; + short last_status = 0; + + arg = arg; + + act.sa_handler = sigCatch; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + traceit("get_irc_data thread exiting...\n"); + keep_running = false; + pthread_exit(NULL); + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + traceit("get_irc_data thread exiting...\n"); + keep_running = false; + pthread_exit(NULL); + } + if (sigaction(SIGPIPE, &act, 0) != 0) { + traceit("sigaction-PIPE failed, error=%d\n", errno); + traceit("get_irc_data thread exiting...\n"); + keep_running = false; + pthread_exit(NULL); + } + + while (keep_running) { + threshold ++; + if (threshold >= THRESHOLD_MAX) { + rc = ii->getConnectionState(); + if ((rc == 0) || (rc == 10)) { + if (last_status != 0) { + traceit("irc status=%d, probable disconnect...\n", rc); + last_status = 0; + } + } else if (rc == 7) { + if (last_status != 2) { + traceit("irc status=%d, probable connect...\n", rc); + last_status = 2; + } + } else { + if (last_status != 1) { + traceit("irc status=%d, probable connect...\n", rc); + last_status = 1; + } + } + threshold = 0; + } + + while (((type = ii->getMessageType()) != IDRT_NONE) && keep_running) { + if (type == IDRT_USER) { + ii->receiveUser(user, rptr, gateway, ipaddr); + if (!user.IsEmpty()) { + if (!rptr.IsEmpty() && !gateway.IsEmpty() && !ipaddr.IsEmpty()) { + if (IRC_DEBUG) + traceit("C-u:%s,%s,%s,%s\n", user.mb_str(), rptr.mb_str(), gateway.mb_str(), ipaddr.mb_str()); + + pthread_mutex_lock(&irc_data_mutex); + + user2rptr_map[user] = rptr; + rptr2gwy_map[rptr] = gateway; + gwy2ip_map[gateway] = ipaddr; + + pthread_mutex_unlock(&irc_data_mutex); + + // traceit("%d users, %d repeaters, %d gateways\n", user2rptr_map.size(), rptr2gwy_map.size(), gwy2ip_map.size()); + + } + } + } else if (type == IDRT_REPEATER) { + ii->receiveRepeater(rptr, gateway, ipaddr, proto); + if (!rptr.IsEmpty()) { + if (!gateway.IsEmpty() && !ipaddr.IsEmpty()) { + if (IRC_DEBUG) + traceit("C-r:%s,%s,%s\n", rptr.mb_str(), gateway.mb_str(), ipaddr.mb_str()); + + pthread_mutex_lock(&irc_data_mutex); + + rptr2gwy_map[rptr] = gateway; + gwy2ip_map[gateway] = ipaddr; + + pthread_mutex_unlock(&irc_data_mutex); + + // traceit("%d repeaters, %d gateways\n", rptr2gwy_map.size(), gwy2ip_map.size()); + + } + } + } else if (type == IDRT_GATEWAY) { + ii->receiveGateway(gateway, ipaddr, proto); + if (!gateway.IsEmpty() && !ipaddr.IsEmpty()) { + if (IRC_DEBUG) + traceit("C-g:%s,%s\n", gateway.mb_str(),ipaddr.mb_str()); + + pthread_mutex_lock(&irc_data_mutex); + + gwy2ip_map[gateway] = ipaddr; + + pthread_mutex_unlock(&irc_data_mutex); + + // traceit("%d gateways\n", gwy2ip_map.size()); + + } + } + } + req.tv_sec = 0; + req.tv_nsec = 500000000; // 500 milli + nanosleep(&req, NULL); + } + traceit("get_irc_data thread exiting...\n"); + pthread_exit(NULL); } /* return codes: 0=OK(found it), 1=TRY AGAIN, 2=FAILED(bad data) */ static int get_yrcall_rptr_from_cache(char *call, char *arearp_cs, char *zonerp_cs, - char *mod, char *ip, char RoU) + char *mod, char *ip, char RoU) { - user2rptr_type::iterator user_pos = user2rptr_map.end(); - rptr2gwy_type::iterator rptr_pos = rptr2gwy_map.end(); - gwy2ip_type::iterator gwy_pos = gwy2ip_map.end(); - char temp[CALL_SIZE + 1]; - - memset(arearp_cs, ' ', CALL_SIZE); arearp_cs[CALL_SIZE] = '\0'; - memset(zonerp_cs, ' ', CALL_SIZE); zonerp_cs[CALL_SIZE] = '\0'; - *mod = ' '; - - /* find the user in the CACHE */ - if (RoU == 'U') - { - user_pos = user2rptr_map.find(call); - if (user_pos != user2rptr_map.end()) - { - memcpy(arearp_cs, user_pos->second.c_str(), 7); - *mod = user_pos->second.c_str()[7]; - } - else - return 1; - } - else - if (RoU == 'R') - { - memcpy(arearp_cs, call, 7); - *mod = call[7]; - } - else - { - traceit("Invalid specification %c for RoU\n", RoU); - return 2; - } - - if ((*mod != 'A') && (*mod != 'B') && (*mod != 'C')) - { - traceit("Invalid module %c\n", *mod); - return 2; - } - - memcpy(temp, arearp_cs, 7); temp[7] = *mod; - temp[CALL_SIZE] = '\0'; - - rptr_pos = rptr2gwy_map.find(temp); - if (rptr_pos != rptr2gwy_map.end()) - { - memcpy(zonerp_cs, rptr_pos->second.c_str(), CALL_SIZE); - zonerp_cs[CALL_SIZE] = '\0'; - - gwy_pos = gwy2ip_map.find(zonerp_cs); - if (gwy_pos != gwy2ip_map.end()) - { - strncpy(ip, gwy_pos->second.c_str(),IP_SIZE); - ip[IP_SIZE] = '\0'; - return 0; - } - else - { - /* traceit("Could not find IP for Gateway %s\n", zonerp_cs); */ - return 1; - } - } - else - { - /* traceit("Could not find Gateway for repeater %s\n", temp); */ - return 1; - } - - return 2; + user2rptr_type::iterator user_pos = user2rptr_map.end(); + rptr2gwy_type::iterator rptr_pos = rptr2gwy_map.end(); + gwy2ip_type::iterator gwy_pos = gwy2ip_map.end(); + char temp[CALL_SIZE + 1]; + + memset(arearp_cs, ' ', CALL_SIZE); + arearp_cs[CALL_SIZE] = '\0'; + memset(zonerp_cs, ' ', CALL_SIZE); + zonerp_cs[CALL_SIZE] = '\0'; + *mod = ' '; + + /* find the user in the CACHE */ + if (RoU == 'U') { + user_pos = user2rptr_map.find(call); + if (user_pos != user2rptr_map.end()) { + memcpy(arearp_cs, user_pos->second.c_str(), 7); + *mod = user_pos->second.c_str()[7]; + } else + return 1; + } else if (RoU == 'R') { + memcpy(arearp_cs, call, 7); + *mod = call[7]; + } else { + traceit("Invalid specification %c for RoU\n", RoU); + return 2; + } + + if ((*mod != 'A') && (*mod != 'B') && (*mod != 'C')) { + traceit("Invalid module %c\n", *mod); + return 2; + } + + memcpy(temp, arearp_cs, 7); + temp[7] = *mod; + temp[CALL_SIZE] = '\0'; + + rptr_pos = rptr2gwy_map.find(temp); + if (rptr_pos != rptr2gwy_map.end()) { + memcpy(zonerp_cs, rptr_pos->second.c_str(), CALL_SIZE); + zonerp_cs[CALL_SIZE] = '\0'; + + gwy_pos = gwy2ip_map.find(zonerp_cs); + if (gwy_pos != gwy2ip_map.end()) { + strncpy(ip, gwy_pos->second.c_str(),IP_SIZE); + ip[IP_SIZE] = '\0'; + return 0; + } else { + /* traceit("Could not find IP for Gateway %s\n", zonerp_cs); */ + return 1; + } + } else { + /* traceit("Could not find Gateway for repeater %s\n", temp); */ + return 1; + } + + return 2; } static bool get_yrcall_rptr(char *call, char *arearp_cs, char *zonerp_cs, - char *mod, char *ip, char RoU) + char *mod, char *ip, char RoU) { - int rc = 2; - int status = 0; - - pthread_mutex_lock(&irc_data_mutex); - rc = get_yrcall_rptr_from_cache(call, arearp_cs, zonerp_cs, mod, ip, RoU); - pthread_mutex_unlock(&irc_data_mutex); - if (rc == 0) - return true; - else - if (rc == 2) - return false; - - /* at this point, the data is not in cache */ - /* report the irc status */ - status = ii->getConnectionState(); - // traceit("irc status=%d\n", status); - if (status != 7) - { - traceit("Remote irc database not ready, irc status is not 7, try again\n"); - return false; - } - - /* request data from irc server */ - if (RoU == 'U') - { - traceit("User [%s] not in local cache, try again\n", call); - /*** YRCALL=KJ4NHFBL ***/ - if (((call[6] == 'A') || (call[6] == 'B') || (call[6] == 'C')) && - (call[7] == LINK_CODE)) - traceit("If this was a gateway link request, that is ok\n"); - - if (!ii->findUser(call)) - { - traceit("findUser(%s): Network error\n", call); - return false; - } - } - else - if (RoU == 'R') - { - traceit("Repeater [%s] not in local cache, try again\n", call); - if (!ii->findRepeater(call)) - { - traceit("findRepeater(%s): Network error\n", call); - return false; - } - } - - return false; + int rc = 2; + int status = 0; + + pthread_mutex_lock(&irc_data_mutex); + rc = get_yrcall_rptr_from_cache(call, arearp_cs, zonerp_cs, mod, ip, RoU); + pthread_mutex_unlock(&irc_data_mutex); + if (rc == 0) + return true; + else if (rc == 2) + return false; + + /* at this point, the data is not in cache */ + /* report the irc status */ + status = ii->getConnectionState(); + // traceit("irc status=%d\n", status); + if (status != 7) { + traceit("Remote irc database not ready, irc status is not 7, try again\n"); + return false; + } + + /* request data from irc server */ + if (RoU == 'U') { + traceit("User [%s] not in local cache, try again\n", call); + /*** YRCALL=KJ4NHFBL ***/ + if (((call[6] == 'A') || (call[6] == 'B') || (call[6] == 'C')) && + (call[7] == LINK_CODE)) + traceit("If this was a gateway link request, that is ok\n"); + + if (!ii->findUser(call)) { + traceit("findUser(%s): Network error\n", call); + return false; + } + } else if (RoU == 'R') { + traceit("Repeater [%s] not in local cache, try again\n", call); + if (!ii->findRepeater(call)) { + traceit("findRepeater(%s): Network error\n", call); + return false; + } + } + + return false; } /* signal catching function */ static void sigCatch(int signum) { - /* do NOT do any serious work here */ - if ((signum == SIGTERM) || (signum == SIGINT)) - keep_running = false; - - return; + /* do NOT do any serious work here */ + if ((signum == SIGTERM) || (signum == SIGINT)) + keep_running = false; + + return; } /* run the main loop for g2_ircddb */ static void runit() { - fd_set fdset; - struct timeval tv; - - socklen_t fromlen; - int recvlen; - int recvlen2; - - short i,j; - - bool result = false; - int mycall_valid = REG_NOERROR; - char temp_radio_user[CALL_SIZE + 1]; - char temp_mod; - time_t t_now; - - char arearp_cs[CALL_SIZE + 1]; - char zonerp_cs[CALL_SIZE + 1]; - char ip[IP_SIZE + 1]; - - int rc = 0; - char tempfile[FILENAME_MAX + 1]; - pthread_t echo_thread; - pthread_attr_t attr; - long num_recs = 0L; - short int rec_len = 56; - - pthread_t aprs_beacon_thread; - pthread_t irc_data_thread; - - /* START: TEXT crap */ - bool new_group[3] = { true, true, true }; - int header_type = 0; - short to_print[3] = { 0, 0, 0 }; - bool ABC_grp[3] = { false, false, false }; - bool C_seen[3] = { false, false, false }; - unsigned char tmp_txt[3]; - /* END: TEXT crap */ - - int ber_data[3]; - int ber_errs; - - int max_nfds = 0; - - dstar_dv_init(); - - if (g2_sock > max_nfds) - max_nfds = g2_sock; - if (srv_sock > max_nfds) - max_nfds = srv_sock; - traceit("g2=%d, srv=%d, MAX+1=%d\n", - g2_sock, srv_sock, max_nfds + 1); - - /* start the beacon thread */ - if (SEND_APRS) - { - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&aprs_beacon_thread,&attr,send_aprs_beacon,(void *)0); - if (rc != 0) - traceit("failed to start the aprs beacon thread\n"); - else - traceit("APRS beacon thread started\n"); - pthread_attr_destroy(&attr); - } - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&irc_data_thread,&attr,get_irc_data,(void *)0); - if (rc != 0) - { - traceit("failed to start the get_irc_data thread\n"); - keep_running = false; - } - else - traceit("get_irc_data thread started\n"); - pthread_attr_destroy(&attr); - - while (keep_running) - { - time(&t_now); - if ((t_now - wd_timer) >= 900) - { - ii->kickWatchdog(PACKAGE_REV); - wd_timer = t_now; - } - - for (i = 0; i < 3; i++) - { - /* echotest recording timed out? */ - if (recd[i].last_time != 0) - { - time(&t_now); - if ((t_now - recd[i].last_time) > ECHOTEST_REC_TIMEOUT) - { - traceit("Inactivity on echotest recording mod %d, removing stream id=%d,%d\n", - i,recd[i].streamid[0], recd[i].streamid[1]); - - recd[i].streamid[0] = 0x00; - recd[i].streamid[1] = 0x00; - recd[i].last_time = 0; - close(recd[i].fd); recd[i].fd = -1; - // traceit("Closed echotest audio file:[%s]\n", recd[i].file); - - /* START: echotest thread setup */ - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&echo_thread, &attr, echotest, (void *)recd[i].file); - if (rc != 0) - { - traceit("failed to start echotest thread\n"); - /* when the echotest thread runs, it deletes the file, - Because the echotest thread did NOT start, we delete the file here - */ - unlink(recd[i].file); - } - pthread_attr_destroy(&attr); - /* END: echotest thread setup */ - } - } - - /* voicemail recording timed out? */ - if (vm[i].last_time != 0) - { - time(&t_now); - if ((t_now - vm[i].last_time) > VOICEMAIL_REC_TIMEOUT) - { - traceit("Inactivity on voicemail recording mod %d, removing stream id=%d,%d\n", - i,vm[i].streamid[0], vm[i].streamid[1]); - - vm[i].streamid[0] = 0x00; - vm[i].streamid[1] = 0x00; - vm[i].last_time = 0; - close(vm[i].fd); vm[i].fd = -1; - // traceit("Closed voicemail audio file:[%s]\n", vm[i].file); - } - } - - /* any stream going to local repeater timed out? */ - if (toRptr[i].last_time != 0) - { - time(&t_now); - /* - The stream can be from a cross-band, or from a remote system, - so we could use either FROM_LOCAL_RPTR_TIMEOUT or FROM_REMOTE_G2_TIMEOUT - but FROM_REMOTE_G2_TIMEOUT makes more sense, probably is a bigger number - */ - if ((t_now - toRptr[i].last_time) > FROM_REMOTE_G2_TIMEOUT) - { - traceit("Inactivity to local rptr mod index %d, removing stream id %d,%d\n", - i, toRptr[i].streamid[0], toRptr[i].streamid[1]); - /* - Send end_of_audio to local repeater. - Let the repeater re-initialize - */ - end_of_audio[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); - end_of_audio[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); - if (i == 0) - end_of_audio[13] = 0x03; - else - if (i == 1) - end_of_audio[13] = 0x01; - else - end_of_audio[13] = 0x02; - end_of_audio[14] = toRptr[i].streamid[0]; - end_of_audio[15] = toRptr[i].streamid[1]; - end_of_audio[16] = toRptr[i].sequence | 0x40; - - for (j = 0; j < 2; j++) - sendto(srv_sock, (char *)end_of_audio,29,0, - (struct sockaddr *)&toRptr[i].band_addr, - sizeof(struct sockaddr_in)); - - toRptr[i].G2_COUNTER ++; - - toRptr[i].streamid[0] = '\0'; - toRptr[i].streamid[1] = '\0'; - toRptr[i].adr = 0; - toRptr[i].last_time = 0; - } - } - - /* any stream coming from local repeater timed out ? */ - if (band_txt[i].last_time != 0) - { - time(&t_now); - if ((t_now - band_txt[i].last_time) > FROM_LOCAL_RPTR_TIMEOUT) - { - /* This local stream never went to a remote system, so trace the timeout */ - if (to_remote_g2[i].toDst4.sin_addr.s_addr == 0) - traceit("Inactivity from local rptr band %d, removing stream id %d,%d\n", - i, band_txt[i].streamID[0], band_txt[i].streamID[1]); - - band_txt[i].streamID[0] = 0x00; - band_txt[i].streamID[1] = 0x00; - band_txt[i].flags[0] = 0x00; - band_txt[i].flags[1] = 0x00; - band_txt[i].flags[2] = 0x00; - band_txt[i].lh_mycall[0] = '\0'; - band_txt[i].lh_sfx[0] = '\0'; - band_txt[i].lh_yrcall[0] = '\0'; - band_txt[i].lh_rpt1[0] = '\0'; - band_txt[i].lh_rpt2[0] = '\0'; - - band_txt[i].last_time = 0; - - band_txt[i].txt[0] = '\0'; - band_txt[i].txt_cnt = 0; - - band_txt[i].dest_rptr[0] = '\0'; - - band_txt[i].num_dv_frames = 0; - band_txt[i].num_dv_silent_frames = 0; - band_txt[i].num_bit_errors = 0; - } - } - - /* any stream from local repeater to a remote gateway timed out ? */ - if (to_remote_g2[i].toDst4.sin_addr.s_addr != 0) - { - time(&t_now); - if ((t_now - to_remote_g2[i].last_time) > FROM_LOCAL_RPTR_TIMEOUT) - { - traceit("Inactivity from local rptr mod %d, removing stream id %d,%d\n", - i, to_remote_g2[i].streamid[0], to_remote_g2[i].streamid[1]); - - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].streamid[0] = '\0'; - to_remote_g2[i].streamid[1] = '\0'; - to_remote_g2[i].last_time = 0; - } - } - } - - /* wait 20 ms max */ - FD_ZERO(&fdset); - FD_SET(g2_sock,&fdset); - FD_SET(srv_sock,&fdset); - tv.tv_sec = 0; - tv.tv_usec = 20000; /* 20 ms */ - (void)select(max_nfds + 1,&fdset,0,0,&tv); - - /* process packets coming from remote G2 */ - if (FD_ISSET(g2_sock, &fdset)) - { - fromlen = sizeof(struct sockaddr_in); - recvlen2 = recvfrom(g2_sock,(char *)readBuffer2,2000, - 0,(struct sockaddr *)&fromDst4,&fromlen); - - if ( ((recvlen2 == 56) || - (recvlen2 == 27)) && - (memcmp(readBuffer2, "DSVT", 4) == 0) && - ((readBuffer2[4] == 0x10) || /* header */ - (readBuffer2[4] == 0x20)) && /* details */ - (readBuffer2[8] == 0x20)) /* voice type */ - { - if (recvlen2 == 56) - { - - /* - Find out the local repeater module IP/port - to send the data to - */ - i = -1; - if (readBuffer2[25] == 'A') - i = 0; - else - if (readBuffer2[25] == 'B') - i = 1; - else - if (readBuffer2[25] == 'C') - i = 2; - - /* valid repeater module? */ - if (i >= 0) - { - /* - toRptr[i] is active if a remote system is talking to it or - toRptr[i] is receiving data from a cross-band - */ - if ((toRptr[i].last_time == 0) && (band_txt[i].last_time == 0) && - ((readBuffer2[15] == 0x00) || - (readBuffer2[15] == 0x01) || /* allow the announcements from g2_link */ - (readBuffer2[15] == 0x08) || - (readBuffer2[15] == 0x20) || - (readBuffer2[15] == 0x28) || - (readBuffer2[15] == 0x40))) - { - if (QSO_DETAILS) - traceit("START from g2: streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s\n", - readBuffer2[12],readBuffer2[13], - readBuffer2[15], readBuffer2[16], readBuffer2[17], - &readBuffer2[42], - &readBuffer2[50], &readBuffer2[34], - &readBuffer2[18], &readBuffer2[26], - recvlen2,inet_ntoa(fromDst4.sin_addr)); - - memcpy(readBuffer,"DSTR", 4); - readBuffer[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); - readBuffer[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); - readBuffer[6] = 0x73; - readBuffer[7] = 0x12; - readBuffer[8] = 0x00; - readBuffer[9] = 0x30; - readBuffer[10] = 0x20; - memcpy(readBuffer + 11, readBuffer2 + 9, 47); - sendto(srv_sock, (char *)readBuffer,58,0, - (struct sockaddr *)&toRptr[i].band_addr, - sizeof(struct sockaddr_in)); - - /* save the header */ - memcpy(toRptr[i].saved_hdr, readBuffer, 58); - toRptr[i].saved_adr = fromDst4.sin_addr.s_addr; - - /* This is the active streamid */ - toRptr[i].streamid[0] = readBuffer2[12]; - toRptr[i].streamid[1] = readBuffer2[13]; - toRptr[i].adr = fromDst4.sin_addr.s_addr; - - /* time it, in case stream times out */ - time(&toRptr[i].last_time); - - /* bump the G2 counter */ - toRptr[i].G2_COUNTER ++; - - toRptr[i].sequence = readBuffer[16]; - } - } - } - else - { - if ((readBuffer2[14] & 0x40) != 0) - { - if (QSO_DETAILS) - traceit("END from g2: streamID=%d,%d, %d bytes from IP=%s\n", - readBuffer2[12],readBuffer2[13], - recvlen2,inet_ntoa(fromDst4.sin_addr)); - } - - /* find out which repeater module to send the data to */ - for (i = 0; i < 3; i++) - { - /* streamid match ? */ - if ((memcmp(toRptr[i].streamid, readBuffer2 + 12, 2) == 0) && - (toRptr[i].adr == fromDst4.sin_addr.s_addr)) - { - memcpy(readBuffer,"DSTR", 4); - readBuffer[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); - readBuffer[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); - readBuffer[6] = 0x73; - readBuffer[7] = 0x12; - readBuffer[8] = 0x00; - readBuffer[9] = 0x13; - readBuffer[10] = 0x20; - memcpy(readBuffer + 11, readBuffer2 + 9, 18); - - sendto(srv_sock, (char *)readBuffer,29,0, - (struct sockaddr *)&toRptr[i].band_addr, - sizeof(struct sockaddr_in)); - - /* timeit */ - time(&toRptr[i].last_time); - - /* bump G2 counter */ - toRptr[i].G2_COUNTER ++; - - toRptr[i].sequence = readBuffer[16]; - - /* End of stream ? */ - if ((readBuffer2[14] & 0x40) != 0) - { - /* clear the saved header */ - memset(toRptr[i].saved_hdr, 0, sizeof(toRptr[i].saved_hdr)); - toRptr[i].saved_adr = 0; - - toRptr[i].last_time = 0; - toRptr[i].streamid[0] = '\0'; - toRptr[i].streamid[1] = '\0'; - toRptr[i].adr = 0; - } - break; - } - } - - /* no match ? */ - if ((i == 3) && REGEN_HDR) - { - /* check if this a continuation of audio that timed out */ - - if ((readBuffer2[14] & 0x40) != 0) - ; /* we do not care about end-of-QSO */ - else - { - /* for which repeater this stream has timed out ? */ - for (i = 0; i < 3; i++) - { - /* match saved stream ? */ - if ((memcmp(toRptr[i].saved_hdr + 14, readBuffer2 + 12, 2) == 0) && - (toRptr[i].saved_adr == fromDst4.sin_addr.s_addr)) - { - /* repeater module is inactive ? */ - if ((toRptr[i].last_time == 0) && (band_txt[i].last_time == 0)) - { - traceit("Re-generating header for streamID=%d,%d\n", readBuffer2[12],readBuffer2[13]); - - toRptr[i].saved_hdr[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); - toRptr[i].saved_hdr[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); - - /* re-generate/send the header */ - sendto(srv_sock, (char *)toRptr[i].saved_hdr,58,0, - (struct sockaddr *)&toRptr[i].band_addr, - sizeof(struct sockaddr_in)); - - /* bump G2 counter */ - toRptr[i].G2_COUNTER ++; - - /* send this audio packet to repeater */ - memcpy(readBuffer,"DSTR", 4); - readBuffer[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); - readBuffer[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); - readBuffer[6] = 0x73; - readBuffer[7] = 0x12; - readBuffer[8] = 0x00; - readBuffer[9] = 0x13; - readBuffer[10] = 0x20; - memcpy(readBuffer + 11, readBuffer2 + 9, 18); - - sendto(srv_sock, (char *)readBuffer,29,0, - (struct sockaddr *)&toRptr[i].band_addr, - sizeof(struct sockaddr_in)); - - /* make sure that any more audio arriving will be accepted */ - toRptr[i].streamid[0] = readBuffer2[12]; - toRptr[i].streamid[1] = readBuffer2[13]; - toRptr[i].adr = fromDst4.sin_addr.s_addr; - - /* time it, in case stream times out */ - time(&toRptr[i].last_time); - - /* bump the G2 counter */ - toRptr[i].G2_COUNTER ++; - - toRptr[i].sequence = readBuffer[16]; - - } - break; - } - } - } - } - } - } - FD_CLR (g2_sock,&fdset); - } - - /* process data coming from local repeater modules */ - if (FD_ISSET(srv_sock, &fdset)) - { - fromlen = sizeof(struct sockaddr_in); - recvlen = recvfrom(srv_sock,(char *)readBuffer,2000, - 0,(struct sockaddr *)&fromRptr,&fromlen); - - /* DV */ - if ( ((recvlen == 58) || - (recvlen == 29) || - (recvlen == 32)) && - (readBuffer[6] == 0x73) && - (readBuffer[7] == 0x12) && - (memcmp(readBuffer,"DSTR", 4) == 0) && - (readBuffer[10] == 0x20) && - (readBuffer[8] == 0x00) && - ((readBuffer[9] == 0x30) || /* 48 bytes follow */ - (readBuffer[9] == 0x13) || /* 19 bytes follow */ - (readBuffer[9] == 0x16)) ) /* 22 bytes follow */ - { - - if (recvlen == 58) - { - if (QSO_DETAILS) - traceit("START from rptr: cntr=%02x %02x, streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s\n", - readBuffer[4], readBuffer[5], - readBuffer[14], readBuffer[15], - readBuffer[17], readBuffer[18], readBuffer[19], - readBuffer + 44, readBuffer + 52, readBuffer + 36, - readBuffer + 28, readBuffer + 20, recvlen, inet_ntoa(fromRptr.sin_addr)); - - if ((memcmp(readBuffer + 28, OWNER, 7) == 0) && /* rpt1 is this repeater */ - /*** (memcmp(readBuffer + 44, OWNER, 7) != 0) && ***/ /* MYCALL is NOT this repeater */ - ((readBuffer[17] == 0x00) || /* normal */ - (readBuffer[17] == 0x08) || /* EMR */ - (readBuffer[17] == 0x20) || /* BREAK */ - (readBuffer[17] == 0x28))) /* EMR + BREAK */ - { - - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - dtmf_last_frame[i] = 0; - dtmf_counter[i] = 0; - memset(dtmf_buf[i], 0, sizeof(dtmf_buf[i])); - dtmf_buf_count[i] = 0; - - /* Initialize the LAST HEARD data for the band */ - - band_txt[i].streamID[0] = readBuffer[14]; - band_txt[i].streamID[1] = readBuffer[15]; - - band_txt[i].flags[0] = readBuffer[17]; - band_txt[i].flags[1] = readBuffer[18]; - band_txt[i].flags[2] = readBuffer[19]; - - memcpy(band_txt[i].lh_mycall, readBuffer + 44, CALL_SIZE); - band_txt[i].lh_mycall[CALL_SIZE] = '\0'; - - memcpy(band_txt[i].lh_sfx, readBuffer + 52, 4); - band_txt[i].lh_sfx[4] = '\0'; - - memcpy(band_txt[i].lh_yrcall, readBuffer + 36, CALL_SIZE); - band_txt[i].lh_yrcall[CALL_SIZE] = '\0'; - - memcpy(band_txt[i].lh_rpt1, readBuffer + 28, CALL_SIZE); - band_txt[i].lh_rpt1[CALL_SIZE] = '\0'; - - memcpy(band_txt[i].lh_rpt2, readBuffer + 20, CALL_SIZE); - band_txt[i].lh_rpt2[CALL_SIZE] = '\0'; - - time(&band_txt[i].last_time); - - band_txt[i].txt[0] = '\0'; - band_txt[i].txt_cnt = 0; - band_txt[i].txt_stats_sent = false; - - band_txt[i].dest_rptr[0] = '\0'; - - /* try to process GPS mode: GPRMC and ID */ - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - band_txt[i].gprmc[0] = '\0'; - band_txt[i].gpid[0] = '\0'; - band_txt[i].is_gps_sent = false; - // band_txt[i].gps_last_time = 0; DO NOT reset it - - new_group[i] = true; - to_print[i] = 0; - ABC_grp[i] = false; - - band_txt[i].num_dv_frames = 0; - band_txt[i].num_dv_silent_frames = 0; - band_txt[i].num_bit_errors = 0; - - /* select the band for aprs processing, and lock on the stream ID */ - if (SEND_APRS) - aprs_select_band(i, readBuffer + 14); - } - } - - /* Is MYCALL valid ? */ - memset(temp_radio_user, ' ', CALL_SIZE); - memcpy(temp_radio_user, readBuffer + 44, 8); - temp_radio_user[CALL_SIZE] = '\0'; - - mycall_valid = regexec(&preg, temp_radio_user, 0, NULL, 0); - - if (mycall_valid == REG_NOERROR) - ; // traceit("MYCALL [%s] passed IRC expression validation\n", temp_radio_user); - else - { - if (mycall_valid == REG_NOMATCH) - traceit("MYCALL [%s] failed IRC expression validation\n", temp_radio_user); - else - traceit("Failed to validate MYCALL [%s], regexec error=%d\n", temp_radio_user, mycall_valid); - } - - /* send data g2_link */ - if (mycall_valid == REG_NOERROR) - sendto(srv_sock, (char *)readBuffer, recvlen,0, - (struct sockaddr *)&plug, - sizeof(struct sockaddr_in)); - - if ((mycall_valid == REG_NOERROR) && - (memcmp(readBuffer + 36, "XRF", 3) != 0) && /* not a reflector */ - (memcmp(readBuffer + 36, "REF", 3) != 0) && /* not a reflector */ - (memcmp(readBuffer + 36, "DCS", 3) != 0) && /* not a reflector */ - (readBuffer[36] != ' ') && /* must have something */ - (memcmp(readBuffer + 36, "CQCQCQ", 6) != 0)) /* urcall is NOT CQCQCQ */ - { - if ((readBuffer[36] == '/') && /* urcall starts with a slash */ - (memcmp(readBuffer + 28, OWNER, 7) == 0) && /* rpt1 is this repeater */ - ((readBuffer[35] == 'A') || - (readBuffer[35] == 'B') || - (readBuffer[35] == 'C')) && /* mod is A,B,C */ - (memcmp(readBuffer + 20, OWNER, 7) == 0) && /* rpt2 is this repeater */ - (readBuffer[27] == 'G') && /* local Gateway */ - /*** (memcmp(readBuffer + 44, OWNER, 7) != 0) && ***/ /* mycall is NOT this repeater */ - - ((readBuffer[17] == 0x00) || /* normal */ - (readBuffer[17] == 0x08) || /* EMR */ - (readBuffer[17] == 0x20) || /* BK */ - (readBuffer[17] == 0x28)) /* EMR + BK */ - ) - { - if (memcmp(readBuffer + 37, OWNER, 6) != 0) /* the value after the slash in urcall, is NOT this repeater */ - { - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - /* one radio user on a repeater module at a time */ - if (to_remote_g2[i].toDst4.sin_addr.s_addr == 0) - { - /* YRCALL=/repeater + mod */ - /* YRCALL=/KJ4NHFB */ - - memset(temp_radio_user, ' ', CALL_SIZE); - memcpy(temp_radio_user, readBuffer + 37, 6); - temp_radio_user[6] = ' '; - temp_radio_user[7] = readBuffer[43]; - if (temp_radio_user[7] == ' ') - temp_radio_user[7] = 'A'; - temp_radio_user[CALL_SIZE] = '\0'; - - result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'R'); - if (result) /* it is a repeater */ - { - /* set the destination */ - memcpy(to_remote_g2[i].streamid, readBuffer + 14, 2); - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].toDst4.sin_family = AF_INET; - to_remote_g2[i].toDst4.sin_port = htons(G2_EXTERNAL_PORT); - to_remote_g2[i].toDst4.sin_addr.s_addr = inet_addr(ip); - - memcpy(readBuffer2, "DSVT", 4); - readBuffer2[4] = 0x10; - readBuffer2[5] = 0x00; - readBuffer2[6] = 0x00; - readBuffer2[7] = 0x00; - readBuffer2[8] = readBuffer[10]; - readBuffer2[9] = readBuffer[11]; - readBuffer2[10] = readBuffer[12]; - readBuffer2[11] = readBuffer[13]; - memcpy(readBuffer2 + 12, readBuffer + 14, 44); - /* set rpt1 */ - memset(readBuffer2 + 18, ' ', CALL_SIZE); - memcpy(readBuffer2 + 18, arearp_cs, strlen(arearp_cs)); - readBuffer2[25] = temp_mod; - /* set rpt2 */ - memset(readBuffer2 + 26, ' ', CALL_SIZE); - memcpy(readBuffer2 + 26, zonerp_cs, strlen(zonerp_cs)); - readBuffer2[33] = 'G'; - /* set yrcall, can NOT let it be slash and repeater + module */ - memcpy(readBuffer2 + 34, "CQCQCQ ", 8); - - /* set PFCS */ - calcPFCS(readBuffer2, 56); - - /* - The remote repeater has been set, lets fill in the dest_rptr - so that later we can send that to the LIVE web site - */ - memcpy(band_txt[i].dest_rptr, readBuffer2 + 18, CALL_SIZE); - band_txt[i].dest_rptr[CALL_SIZE] = '\0'; - - /* send to remote gateway */ - for (j = 0; j < 5; j++) - sendto(g2_sock, (char *)readBuffer2, 56, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - - traceit("Routing to IP=%s, streamID=%d,%d, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes\n", - inet_ntoa(to_remote_g2[i].toDst4.sin_addr), - readBuffer2[12],readBuffer2[13],&readBuffer2[42], - &readBuffer2[50], &readBuffer2[34], - &readBuffer2[18], &readBuffer2[26], - 56); - - time(&(to_remote_g2[i].last_time)); - } - } - } - } - } - else - if ((memcmp(readBuffer + 36, OWNER, 7) != 0) && /* urcall is not this repeater */ - (memcmp(readBuffer + 28, OWNER, 7) == 0) && /* rpt1 is this repeater */ - ((readBuffer[35] == 'A') || - (readBuffer[35] == 'B') || - (readBuffer[35] == 'C')) && /* mod is A,B,C */ - (memcmp(readBuffer + 20, OWNER, 7) == 0) && /* rpt2 is this repeater */ - (readBuffer[27] == 'G') && /* local Gateway */ - /*** (memcmp(readBuffer + 44, OWNER, 7) != 0) && ***/ /* mycall is NOT this repeater */ - - ((readBuffer[17] == 0x00) || /* normal */ - (readBuffer[17] == 0x08) || /* EMR */ - (readBuffer[17] == 0x20) || /* BK */ - (readBuffer[17] == 0x28)) /* EMR + BK */ - ) - { - - memset(temp_radio_user, ' ', CALL_SIZE); - memcpy(temp_radio_user, readBuffer + 36, CALL_SIZE); - temp_radio_user[CALL_SIZE] = '\0'; - result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'U'); - if (result) - { - /* destination is a remote system */ - if (memcmp(zonerp_cs, OWNER, 7) != 0) - { - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - /* one radio user on a repeater module at a time */ - if (to_remote_g2[i].toDst4.sin_addr.s_addr == 0) - { - /* set the destination */ - memcpy(to_remote_g2[i].streamid, readBuffer + 14, 2); - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].toDst4.sin_family = AF_INET; - to_remote_g2[i].toDst4.sin_port = htons(G2_EXTERNAL_PORT); - to_remote_g2[i].toDst4.sin_addr.s_addr = inet_addr(ip); - - memcpy(readBuffer2, "DSVT", 4); - readBuffer2[4] = 0x10; - readBuffer2[5] = 0x00; - readBuffer2[6] = 0x00; - readBuffer2[7] = 0x00; - readBuffer2[8] = readBuffer[10]; - readBuffer2[9] = readBuffer[11]; - readBuffer2[10] = readBuffer[12]; - readBuffer2[11] = readBuffer[13]; - memcpy(readBuffer2 + 12, readBuffer + 14, 44); - /* set rpt1 */ - memset(readBuffer2 + 18, ' ', CALL_SIZE); - memcpy(readBuffer2 + 18, arearp_cs, strlen(arearp_cs)); - readBuffer2[25] = temp_mod; - /* set rpt2 */ - memset(readBuffer2 + 26, ' ', CALL_SIZE); - memcpy(readBuffer2 + 26, zonerp_cs, strlen(zonerp_cs)); - readBuffer2[33] = 'G'; - /* set PFCS */ - calcPFCS(readBuffer2, 56); - - /* - The remote repeater has been set, lets fill in the dest_rptr - so that later we can send that to the LIVE web site - */ - memcpy(band_txt[i].dest_rptr, readBuffer2 + 18, CALL_SIZE); - band_txt[i].dest_rptr[CALL_SIZE] = '\0'; - - /* send to remote gateway */ - for (j = 0; j < 5; j++) - sendto(g2_sock, (char *)readBuffer2, 56, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - - traceit("Routing to IP=%s, streamID=%d,%d, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes\n", - inet_ntoa(to_remote_g2[i].toDst4.sin_addr), - readBuffer2[12],readBuffer2[13],&readBuffer2[42], - &readBuffer2[50], &readBuffer2[34], - &readBuffer2[18], &readBuffer2[26], - 56); - - time(&(to_remote_g2[i].last_time)); - } - } - } - else - { - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - /* the user we are trying to contact is on our gateway */ - /* make sure they are on a different module */ - if (temp_mod != readBuffer[35]) - { - /* - The remote repeater has been set, lets fill in the dest_rptr - so that later we can send that to the LIVE web site - */ - memcpy(band_txt[i].dest_rptr, readBuffer + 20, CALL_SIZE); - band_txt[i].dest_rptr[7] = temp_mod; - band_txt[i].dest_rptr[CALL_SIZE] = '\0'; - - i = -1; - if (temp_mod == 'A') - i = 0; - else - if (temp_mod == 'B') - i = 1; - else - if (temp_mod == 'C') - i = 2; - - /* valid destination repeater module? */ - if (i >= 0) - { - /* - toRptr[i] : receiving from a remote system or cross-band - band_txt[i] : local RF is talking. - */ - if ((toRptr[i].last_time == 0) && (band_txt[i].last_time == 0)) - { - traceit("CALLmode cross-banding from mod %c to %c\n", readBuffer[35], temp_mod); - - readBuffer[27] = temp_mod; - readBuffer[35] = 'G'; - calcPFCS(readBuffer, 58); - - sendto(srv_sock, (char *)readBuffer,58,0, - (struct sockaddr *)&toRptr[i].band_addr, - sizeof(struct sockaddr_in)); - - /* This is the active streamid */ - toRptr[i].streamid[0] = readBuffer[14]; - toRptr[i].streamid[1] = readBuffer[15]; - toRptr[i].adr = fromRptr.sin_addr.s_addr; - - /* time it, in case stream times out */ - time(&toRptr[i].last_time); - - /* bump the G2 counter */ - toRptr[i].G2_COUNTER ++; - - toRptr[i].sequence = readBuffer[16]; - } - } - } - else - traceit("icom rule: no routing from %.8s to %s%c\n", readBuffer + 28, arearp_cs,temp_mod); - } - } - } - } - } - else - if ((readBuffer[43] == '0') && - (readBuffer[42] == CLEAR_VM_CODE) && - (readBuffer[36] == ' ')) - { - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - /* voicemail file is closed */ - if ((vm[i].fd == -1) && (vm[i].file[0] != '\0')) - { - unlink(vm[i].file); - traceit("removed voicemail file: %s\n", vm[i].file); - vm[i].file[0] = '\0'; - } - else - traceit("No voicemail to clear or still recording\n"); - } - } - else - if ((readBuffer[43] == '0') && - (readBuffer[42] == RECALL_VM_CODE) && - (readBuffer[36] == ' ')) - { - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - /* voicemail file is closed */ - if ((vm[i].fd == -1) && (vm[i].file[0] != '\0')) - { - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&echo_thread, &attr, echotest, (void *)vm[i].file); - if (rc != 0) - traceit("failed to start playing back voicemail\n"); - pthread_attr_destroy(&attr); - } - else - traceit("No voicemail to recall or still recording\n"); - } - } - else - if ((readBuffer[43] == '0') && - (readBuffer[42] == STORE_VM_CODE) && - (readBuffer[36] == ' ')) - { - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - if (vm[i].fd >= 0) - traceit("Already recording for voicemail on mod %d\n", i); - else - { - memset(tempfile, '\0', sizeof(tempfile)); - snprintf(tempfile, FILENAME_MAX, "%s/%c_%s", - ECHOTEST_DIR, - readBuffer[35], - "voicemail.dat"); - - vm[i].fd = open(tempfile, - O_CREAT | O_WRONLY | O_TRUNC | O_APPEND, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (vm[i].fd < 0) - traceit("Failed to create file %s for voicemail\n", tempfile); - else - { - strcpy(vm[i].file, tempfile); - traceit("Recording mod %c for voicemail into file:[%s]\n", - readBuffer[35], - vm[i].file); - - time(&vm[i].last_time); - memcpy(vm[i].streamid, readBuffer + 14, 2); - - memcpy(recbuf, "DSVT", 4); - recbuf[4] = 0x10; - recbuf[5] = 0x00; - recbuf[6] = 0x00; - recbuf[7] = 0x00; - recbuf[8] = readBuffer[10]; - recbuf[9] = readBuffer[11]; - recbuf[10] = readBuffer[12]; - recbuf[11] = readBuffer[13]; - memcpy(recbuf + 12, readBuffer + 14, 44); - memset(recbuf + 18, ' ', CALL_SIZE); - memcpy(recbuf + 18, OWNER, strlen(OWNER)); - recbuf[25] = readBuffer[35]; - memset(recbuf + 26, ' ', CALL_SIZE); - memcpy(recbuf + 26, OWNER, strlen(OWNER)); - recbuf[33] = 'G'; - memcpy(recbuf + 34, "CQCQCQ ", 8); - - calcPFCS(recbuf,56); - - rec_len = 56; - (void)write(vm[i].fd, "DVTOOL", 6); - (void)write(vm[i].fd, &num_recs, 4); - (void)write(vm[i].fd, &rec_len, 2); - (void)write(vm[i].fd, (char *)recbuf, rec_len); - } - } - } - } - else - if ((readBuffer[43] == ECHO_CODE) && - (readBuffer[36] == ' ')) - { - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - if (recd[i].fd >= 0) - traceit("Already recording for echotest on mod %d\n", i); - else - { - memset(tempfile, '\0', sizeof(tempfile)); - snprintf(tempfile, FILENAME_MAX, "%s/%c_%s", - ECHOTEST_DIR, - readBuffer[35], - "echotest.dat"); - - recd[i].fd = open(tempfile, - O_CREAT | O_WRONLY | O_EXCL | O_TRUNC | O_APPEND, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (recd[i].fd < 0) - traceit("Failed to create file %s for echotest\n", tempfile); - else - { - strcpy(recd[i].file, tempfile); - traceit("Recording mod %c for echotest into file:[%s]\n", - readBuffer[35], - recd[i].file); - - time(&recd[i].last_time); - memcpy(recd[i].streamid, readBuffer + 14, 2); - - memcpy(recbuf, "DSVT", 4); - recbuf[4] = 0x10; - recbuf[5] = 0x00; - recbuf[6] = 0x00; - recbuf[7] = 0x00; - recbuf[8] = readBuffer[10]; - recbuf[9] = readBuffer[11]; - recbuf[10] = readBuffer[12]; - recbuf[11] = readBuffer[13]; - memcpy(recbuf + 12, readBuffer + 14, 44); - memset(recbuf + 18, ' ', CALL_SIZE); - memcpy(recbuf + 18, OWNER, strlen(OWNER)); - recbuf[25] = readBuffer[35]; - memset(recbuf + 26, ' ', CALL_SIZE); - memcpy(recbuf + 26, OWNER, strlen(OWNER)); - recbuf[33] = 'G'; - memcpy(recbuf + 34, "CQCQCQ ", 8); - - calcPFCS(recbuf,56); - - rec_len = 56; - (void)write(recd[i].fd, "DVTOOL", 6); - (void)write(recd[i].fd, &num_recs, 4); - (void)write(recd[i].fd, &rec_len, 2); - (void)write(recd[i].fd, (char *)recbuf, rec_len); - } - } - } - } - else - /* check for cross-banding */ - if ((memcmp(readBuffer + 36, "CQCQCQ", 6) == 0) && /* yrcall is CQCQCQ */ - (memcmp(readBuffer + 28, OWNER, 7) == 0) && /* rpt1 is this repeater */ - (memcmp(readBuffer + 20, OWNER, 7) == 0) && /* rpt2 is this repeater */ - ((readBuffer[35] == 'A') || - (readBuffer[35] == 'B') || - (readBuffer[35] == 'C')) && /* mod of rpt1 is A,B,C */ - ((readBuffer[27] == 'A') || - (readBuffer[27] == 'B') || - (readBuffer[27] == 'C')) && /* !!! usually a G of rpt2, but we see A,B,C */ - (readBuffer[35] != readBuffer[27])) /* cross-banding? make sure NOT the same */ - { - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - /* - The remote repeater has been set, lets fill in the dest_rptr - so that later we can send that to the LIVE web site - */ - memcpy(band_txt[i].dest_rptr, readBuffer + 20, CALL_SIZE); - band_txt[i].dest_rptr[CALL_SIZE] = '\0'; - } - - i = -1; - if (readBuffer[27] == 'A') - i = 0; - else - if (readBuffer[27] == 'B') - i = 1; - else - if (readBuffer[27] == 'C') - i = 2; - - /* valid destination repeater module? */ - if (i >= 0) - { - /* - toRptr[i] : receiving from a remote system or cross-band - band_txt[i] : local RF is talking. - */ - if ((toRptr[i].last_time == 0) && (band_txt[i].last_time == 0)) - { - traceit("ZONEmode cross-banding from mod %c to %c\n", readBuffer[35], readBuffer[27]); - - readBuffer[35] = 'G'; - calcPFCS(readBuffer, 58); - - sendto(srv_sock, (char *)readBuffer,58,0, - (struct sockaddr *)&toRptr[i].band_addr, - sizeof(struct sockaddr_in)); - - /* This is the active streamid */ - toRptr[i].streamid[0] = readBuffer[14]; - toRptr[i].streamid[1] = readBuffer[15]; - toRptr[i].adr = fromRptr.sin_addr.s_addr; - - /* time it, in case stream times out */ - time(&toRptr[i].last_time); - - /* bump the G2 counter */ - toRptr[i].G2_COUNTER ++; - - toRptr[i].sequence = readBuffer[16]; - } - } - } - } - else - { - for (i = 0; i < 3; i++) - { - if (memcmp(band_txt[i].streamID, readBuffer + 14, 2) == 0) - { - time(&band_txt[i].last_time); - - if ((readBuffer[16] & 0x40) != 0) - { - if (dtmf_buf_count[i] > 0) - { - memset(DTMF_FILE, 0, sizeof(DTMF_FILE)); - snprintf(DTMF_FILE, FILENAME_MAX, "%s/%d_mod_DTMF_NOTIFY", DTMF_DIR, i); - if (DTMF_DEBUG) - traceit("Saving dtmfs=[%s] into file: [%s]\n", dtmf_buf[i], DTMF_FILE); - dtmf_fp = fopen(DTMF_FILE, "w"); - if (!dtmf_fp) - traceit("Failed to create dtmf file %s\n", DTMF_FILE); - else - { - fprintf(dtmf_fp, "%s\n%s", dtmf_buf[i], band_txt[i].lh_mycall); - fclose(dtmf_fp); dtmf_fp = NULL; - } - memset(dtmf_buf[i], 0, sizeof(dtmf_buf[i])); - dtmf_buf_count[i] = 0; - dtmf_counter[i] = 0; - dtmf_last_frame[i] = 0; - } - - ii->sendHeardWithTXStats(band_txt[i].lh_mycall, - band_txt[i].lh_sfx, - (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", - band_txt[i].lh_rpt1, - band_txt[i].lh_rpt2, - band_txt[i].flags[0], - band_txt[i].flags[1], - band_txt[i].flags[2], - band_txt[i].num_dv_frames, - band_txt[i].num_dv_silent_frames, - band_txt[i].num_bit_errors); - - band_txt[i].streamID[0] = 0x00; - band_txt[i].streamID[1] = 0x00; - band_txt[i].flags[0] = 0x00; - band_txt[i].flags[1] = 0x00; - band_txt[i].flags[2] = 0x00; - band_txt[i].lh_mycall[0] = '\0'; - band_txt[i].lh_sfx[0] = '\0'; - band_txt[i].lh_yrcall[0] = '\0'; - band_txt[i].lh_rpt1[0] = '\0'; - band_txt[i].lh_rpt2[0] = '\0'; - - band_txt[i].last_time = 0; - - band_txt[i].txt[0] = '\0'; - band_txt[i].txt_cnt = 0; - - band_txt[i].dest_rptr[0] = '\0'; - - band_txt[i].num_dv_frames = 0; - band_txt[i].num_dv_silent_frames = 0; - band_txt[i].num_bit_errors = 0; - - } - else - { - ber_errs = dstar_dv_decode(readBuffer + 17, ber_data); - if (ber_data[0] == 0xf85) - band_txt[i].num_dv_silent_frames ++; - band_txt[i].num_bit_errors += ber_errs; - band_txt[i].num_dv_frames ++; - - if ((ber_data[0] & 0x0ffc) == 0xfc0) - { - dtmf_digit = (ber_data[0] & 0x03) | ((ber_data[2] & 0x60) >> 3); - if (dtmf_counter[i] > 0) - { - if (dtmf_last_frame[i] != dtmf_digit) - dtmf_counter[i] = 0; - } - dtmf_last_frame[i] = dtmf_digit; - dtmf_counter[i] ++; - - if ((dtmf_counter[i] == 5) && (dtmf_digit >= 0) && (dtmf_digit <= 15)) - { - if (dtmf_buf_count[i] < MAX_DTMF_BUF) - { - dtmf_buf[i][ dtmf_buf_count[i] ] = dtmf_chars[dtmf_digit]; - dtmf_buf_count[i] ++; - } - } - memcpy(readBuffer + 17, silence, 9); - } - else - dtmf_counter[i] = 0; - } - break; - } - } - - if (recvlen == 29) - memcpy(tmp_txt, readBuffer + 26, 3); - else - memcpy(tmp_txt, readBuffer + 29, 3); - - // traceit("%x%x%x\n", tmp_txt[0], tmp_txt[1], tmp_txt[2]); - // traceit("%c%c%c\n", tmp_txt[0] ^ 0x70, tmp_txt[1] ^ 0x4f, tmp_txt[2] ^ 0x93); - - /* extract 20-byte RADIO ID */ - if ((tmp_txt[0] != 0x55) || (tmp_txt[1] != 0x2d) || (tmp_txt[2] != 0x16)) - { - // traceit("%x%x%x\n", tmp_txt[0], tmp_txt[1], tmp_txt[2]); - // traceit("%c%c%c\n", tmp_txt[0] ^ 0x70, tmp_txt[1] ^ 0x4f, tmp_txt[2] ^ 0x93); - - for (i = 0; i < 3; i++) - { - if (memcmp(band_txt[i].streamID, readBuffer + 14, 2) == 0) - { - if (new_group[i]) - { - tmp_txt[0] = tmp_txt[0] ^ 0x70; - header_type = tmp_txt[0] & 0xf0; - - if ((header_type == 0x50) || /* header */ - (header_type == 0xc0)) /* squelch */ - { - new_group[i] = false; - to_print[i] = 0; - ABC_grp[i] = false; - } - else - if (header_type == 0x30) /* GPS or GPS id or APRS */ - { - new_group[i] = false; - to_print[i] = tmp_txt[0] & 0x0f; - ABC_grp[i] = false; - if (to_print[i] > 5) - to_print[i] = 5; - else - if (to_print[i] < 1) - to_print[i] = 1; - - if ((to_print[i] > 1) && (to_print[i] <= 5)) - { - /* something went wrong? all bets are off */ - if (band_txt[i].temp_line_cnt > 200) - { - traceit("Reached the limit in the OLD gps mode\n"); - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - - /* fresh GPS string, re-initialize */ - if ((to_print[i] == 5) && ((tmp_txt[1] ^ 0x4f) == '$')) - { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - - /* do not copy CR, NL */ - if (((tmp_txt[1] ^ 0x4f) != '\r') && ((tmp_txt[1] ^ 0x4f) != '\n')) - { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[1] ^ 0x4f; - band_txt[i].temp_line_cnt++; - } - if (((tmp_txt[2] ^ 0x93) != '\r') && ((tmp_txt[2] ^ 0x93) != '\n')) - { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[2] ^ 0x93; - band_txt[i].temp_line_cnt++; - } - - if (((tmp_txt[1] ^ 0x4f) == '\r') || ((tmp_txt[2] ^ 0x93) == '\r')) - { - if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) - { - memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; - } - else - if (band_txt[i].temp_line[0] != '$') - { - memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; - if (SEND_APRS && !band_txt[i].is_gps_sent) - gps_send(i); - } - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - else - if (((tmp_txt[1] ^ 0x4f) == '\n') || ((tmp_txt[2] ^ 0x93) == '\n')) - { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - to_print[i] -= 2; - } - else - { - /* something went wrong? all bets are off */ - if (band_txt[i].temp_line_cnt > 200) - { - traceit("Reached the limit in the OLD gps mode\n"); - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - - /* do not copy CR, NL */ - if (((tmp_txt[1] ^ 0x4f) != '\r') && ((tmp_txt[1] ^ 0x4f) != '\n')) - { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[1] ^ 0x4f; - band_txt[i].temp_line_cnt++; - } - - if ((tmp_txt[1] ^ 0x4f) == '\r') - { - if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) - { - memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; - } - else - if (band_txt[i].temp_line[0] != '$') - { - memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; - if (SEND_APRS && !band_txt[i].is_gps_sent) - gps_send(i); - } - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - else - if ((tmp_txt[1] ^ 0x4f) == '\n') - { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - to_print[i] --; - } - } - else - if (header_type == 0x40) /* ABC text */ - { - new_group[i] = false; - to_print[i] = 3; - ABC_grp[i] = true; - C_seen[i] = ((tmp_txt[0] & 0x0f) == 0x03)?true:false; - - band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[1] ^ 0x4f; - band_txt[i].txt_cnt++; - - band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[2] ^ 0x93; - band_txt[i].txt_cnt++; - - /* - We should NOT see any more text, - if we already processed text, - so blank out the codes. - */ - if (band_txt[i].txt_stats_sent) - { - if (recvlen == 29) - { - readBuffer[26] = 0x70; - readBuffer[27] = 0x4f; - readBuffer[28] = 0x93; - } - else - { - readBuffer[29] = 0x70; - readBuffer[30] = 0x4f; - readBuffer[31] = 0x93; - } - } - - if (band_txt[i].txt_cnt >= 20) - { - band_txt[i].txt[band_txt[i].txt_cnt] = '\0'; - /*** - ii->sendHeardWithTXMsg(band_txt[i].lh_mycall, - band_txt[i].lh_sfx, - (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", - band_txt[i].lh_rpt1, - band_txt[i].lh_rpt2, - band_txt[i].flags[0], - band_txt[i].flags[1], - band_txt[i].flags[2], - band_txt[i].dest_rptr, - band_txt[i].txt); - ***/ - // traceit("TEXT1=[%s]\n", band_txt[i].txt); - band_txt[i].txt_cnt = 0; - } - } - else - { - new_group[i] = false; - to_print[i] = 0; - ABC_grp[i] = false; - } - } - else - { - if (to_print[i] == 3) - { - if (ABC_grp[i]) - { - band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[0] ^ 0x70; - band_txt[i].txt_cnt ++; - - band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[1] ^ 0x4f; - band_txt[i].txt_cnt ++; - - band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[2] ^ 0x93; - band_txt[i].txt_cnt ++; - - /* - We should NOT see any more text, - if we already processed text, - so blank out the codes. - */ - if (band_txt[i].txt_stats_sent) - { - if (recvlen == 29) - { - readBuffer[26] = 0x70; - readBuffer[27] = 0x4f; - readBuffer[28] = 0x93; - } - else - { - readBuffer[29] = 0x70; - readBuffer[30] = 0x4f; - readBuffer[31] = 0x93; - } - } - - if ((band_txt[i].txt_cnt >= 20) || C_seen[i]) - { - band_txt[i].txt[band_txt[i].txt_cnt] = '\0'; - if (!band_txt[i].txt_stats_sent) - { - /*** if YRCALL is CQCQCQ, set dest_rptr ***/ - if (memcmp(band_txt[i].lh_yrcall, "CQCQCQ", 6) == 0) - { - set_dest_rptr(i, band_txt[i].dest_rptr); - if (memcmp(band_txt[i].dest_rptr, "REF", 3) == 0) - band_txt[i].dest_rptr[0] = '\0'; - } - - ii->sendHeardWithTXMsg(band_txt[i].lh_mycall, - band_txt[i].lh_sfx, - (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", - band_txt[i].lh_rpt1, - band_txt[i].lh_rpt2, - band_txt[i].flags[0], - band_txt[i].flags[1], - band_txt[i].flags[2], - band_txt[i].dest_rptr, - band_txt[i].txt); - // traceit("TEXT2=[%s], destination repeater=[%s]\n", band_txt[i].txt, band_txt[i].dest_rptr); - band_txt[i].txt_stats_sent = true; - } - band_txt[i].txt_cnt = 0; - } - if (C_seen[i]) - C_seen[i] = false; - } - else - { - /* something went wrong? all bets are off */ - if (band_txt[i].temp_line_cnt > 200) - { - traceit("Reached the limit in the OLD gps mode\n"); - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - - /* do not copy CR, NL */ - if (((tmp_txt[0] ^ 0x70) != '\r') && ((tmp_txt[0] ^ 0x70) != '\n')) - { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[0] ^ 0x70; - band_txt[i].temp_line_cnt++; - } - if (((tmp_txt[1] ^ 0x4f) != '\r') && ((tmp_txt[1] ^ 0x4f) != '\n')) - { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[1] ^ 0x4f; - band_txt[i].temp_line_cnt++; - } - if (((tmp_txt[2] ^ 0x93) != '\r') && ((tmp_txt[2] ^ 0x93) != '\n')) - { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[2] ^ 0x93; - band_txt[i].temp_line_cnt++; - } - - if ( - ((tmp_txt[0] ^ 0x70) == '\r') || - ((tmp_txt[1] ^ 0x4f) == '\r') || - ((tmp_txt[2] ^ 0x93) == '\r') - ) - { - if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) - { - memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; - } - else - if (band_txt[i].temp_line[0] != '$') - { - memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; - if (SEND_APRS && !band_txt[i].is_gps_sent) - gps_send(i); - } - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - else - if (((tmp_txt[0] ^ 0x70) == '\n') || - ((tmp_txt[1] ^ 0x4f) == '\n') || - ((tmp_txt[2] ^ 0x93) == '\n')) - { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - } - } - else - if (to_print[i] == 2) - { - /* something went wrong? all bets are off */ - if (band_txt[i].temp_line_cnt > 200) - { - traceit("Reached the limit in the OLD gps mode\n"); - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - - /* do not copy CR, NL */ - if (((tmp_txt[0] ^ 0x70) != '\r') && ((tmp_txt[0] ^ 0x70) != '\n')) - { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[0] ^ 0x70; - band_txt[i].temp_line_cnt++; - } - if (((tmp_txt[1] ^ 0x4f) != '\r') && ((tmp_txt[1] ^ 0x4f) != '\n')) - { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[1] ^ 0x4f; - band_txt[i].temp_line_cnt++; - } - - if (((tmp_txt[0] ^ 0x70) == '\r') || ((tmp_txt[1] ^ 0x4f) == '\r')) - { - if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) - { - memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; - } - else - if (band_txt[i].temp_line[0] != '$') - { - memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; - if (SEND_APRS && !band_txt[i].is_gps_sent) - gps_send(i); - } - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - else - if (((tmp_txt[0] ^ 0x70) == '\n') || ((tmp_txt[1] ^ 0x4f) == '\n')) - { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - } - else - if (to_print[i] == 1) - { - /* something went wrong? all bets are off */ - if (band_txt[i].temp_line_cnt > 200) - { - traceit("Reached the limit in the OLD gps mode\n"); - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - - /* do not copy CR, NL */ - if (((tmp_txt[0] ^ 0x70) != '\r') && ((tmp_txt[0] ^ 0x70) != '\n')) - { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[0] ^ 0x70; - band_txt[i].temp_line_cnt++; - } - - if ((tmp_txt[0] ^ 0x70) == '\r') - { - if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) - { - memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; - } - else - if (band_txt[i].temp_line[0] != '$') - { - memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; - if (SEND_APRS && !band_txt[i].is_gps_sent) - gps_send(i); - } - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - else - if ((tmp_txt[0] ^ 0x70) == '\n') - { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - } - new_group[i] = true; - to_print[i] = 0; - ABC_grp[i] = false; - } - break; - } - } - } - - /* send data to g2_link */ - sendto(srv_sock, (char *)readBuffer, recvlen,0, - (struct sockaddr *)&plug, - sizeof(struct sockaddr_in)); - - /* aprs processing */ - if (SEND_APRS) - aprs_process_text(readBuffer + 14, /* stream ID */ - readBuffer[16], /* seq */ - readBuffer + 17, /* audio + text */ - (recvlen == 29)?12:15); /* size */ - - for (i = 0; i < 3; i++) - { - /* find out if data must go to the remote G2 */ - if (memcmp(to_remote_g2[i].streamid, readBuffer + 14, 2) == 0) - { - memcpy(readBuffer2, "DSVT", 4); - readBuffer2[4] = 0x20; - readBuffer2[5] = 0x00; - readBuffer2[6] = 0x00; - readBuffer2[7] = 0x00; - readBuffer2[8] = readBuffer[10]; - readBuffer2[9] = readBuffer[11]; - readBuffer2[10] = readBuffer[12]; - readBuffer2[11] = readBuffer[13]; - memcpy(readBuffer2 + 12, readBuffer + 14, 3); - if (recvlen == 29) - memcpy(readBuffer2 + 15, readBuffer + 17, 12); - else - memcpy(readBuffer2 + 15, readBuffer + 20, 12); - - sendto(g2_sock, (char *)readBuffer2, 27, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - - time(&(to_remote_g2[i].last_time)); - - /* Is this the end-of-stream */ - if ((readBuffer[16] & 0x40) != 0) - { - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].streamid[0] = '\0'; - to_remote_g2[i].streamid[1] = '\0'; - to_remote_g2[i].last_time = 0; - } - break; - } - else - /* Is the data to be recorded for echotest */ - if ((recd[i].fd >= 0) && - (memcmp(recd[i].streamid, readBuffer + 14, 2) == 0)) - { - time(&recd[i].last_time); - - memcpy(recbuf, "DSVT", 4); - recbuf[4] = 0x20; - recbuf[5] = 0x00; - recbuf[6] = 0x00; - recbuf[7] = 0x00; - recbuf[8] = readBuffer[10]; - recbuf[9] = readBuffer[11]; - recbuf[10] = readBuffer[12]; - recbuf[11] = readBuffer[13]; - memcpy(recbuf + 12, readBuffer + 14, 3); - if (recvlen == 29) - memcpy(recbuf + 15, readBuffer + 17, 12); - else - memcpy(recbuf + 15, readBuffer + 20, 12); - - rec_len = 27; - (void)write(recd[i].fd, &rec_len, 2); - (void)write(recd[i].fd, (char *)recbuf, rec_len); - - if ((readBuffer[16] & 0x40) != 0) - { - recd[i].streamid[0] = 0x00; - recd[i].streamid[1] = 0x00; - recd[i].last_time = 0; - close(recd[i].fd); recd[i].fd = -1; - // traceit("Closed echotest audio file:[%s]\n", recd[i].file); - - /* we are in echotest mode, so play it back */ - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&echo_thread, &attr, echotest, (void *)recd[i].file); - if (rc != 0) - { - traceit("failed to start echotest thread\n"); - /* - When the echotest thread runs, it deletes the file, - Because the echotest thread did NOT start, we delete the file here - */ - unlink(recd[i].file); - } - pthread_attr_destroy(&attr); - } - break; - } - else - /* Is the data to be recorded for voicemail */ - if ((vm[i].fd >= 0) && - (memcmp(vm[i].streamid, readBuffer + 14, 2) == 0)) - { - time(&vm[i].last_time); - - memcpy(recbuf, "DSVT", 4); - recbuf[4] = 0x20; - recbuf[5] = 0x00; - recbuf[6] = 0x00; - recbuf[7] = 0x00; - recbuf[8] = readBuffer[10]; - recbuf[9] = readBuffer[11]; - recbuf[10] = readBuffer[12]; - recbuf[11] = readBuffer[13]; - memcpy(recbuf + 12, readBuffer + 14, 3); - if (recvlen == 29) - memcpy(recbuf + 15, readBuffer + 17, 12); - else - memcpy(recbuf + 15, readBuffer + 20, 12); - - rec_len = 27; - (void)write(vm[i].fd, &rec_len, 2); - (void)write(vm[i].fd, (char *)recbuf, rec_len); - - if ((readBuffer[16] & 0x40) != 0) - { - vm[i].streamid[0] = 0x00; - vm[i].streamid[1] = 0x00; - vm[i].last_time = 0; - close(vm[i].fd); vm[i].fd = -1; - // traceit("Closed voicemail audio file:[%s]\n", vm[i].file); - } - break; - } - else - /* or maybe this is cross-banding data */ - if ((memcmp(toRptr[i].streamid, readBuffer + 14, 2) == 0) && - (toRptr[i].adr == fromRptr.sin_addr.s_addr)) - { - sendto(srv_sock, (char *)readBuffer,29,0, - (struct sockaddr *)&toRptr[i].band_addr, - sizeof(struct sockaddr_in)); - - /* timeit */ - time(&toRptr[i].last_time); - - /* bump G2 counter */ - toRptr[i].G2_COUNTER ++; - - toRptr[i].sequence = readBuffer[16]; - - /* End of stream ? */ - if ((readBuffer[16] & 0x40) != 0) - { - toRptr[i].last_time = 0; - toRptr[i].streamid[0] = '\0'; - toRptr[i].streamid[1] = '\0'; - toRptr[i].adr = 0; - } - break; - } - } - - if ((readBuffer[16] & 0x40) != 0) - { - if (QSO_DETAILS) - traceit("END from rptr: cntr=%02x %02x, streamID=%d,%d, %d bytes\n", - readBuffer[4], readBuffer[5], - readBuffer[14],readBuffer[15],recvlen); - } - } - } - FD_CLR (srv_sock,&fdset); - } - } + fd_set fdset; + struct timeval tv; + + socklen_t fromlen; + int recvlen; + int recvlen2; + + short i,j; + + bool result = false; + int mycall_valid = REG_NOERROR; + char temp_radio_user[CALL_SIZE + 1]; + char temp_mod; + time_t t_now; + + char arearp_cs[CALL_SIZE + 1]; + char zonerp_cs[CALL_SIZE + 1]; + char ip[IP_SIZE + 1]; + + int rc = 0; + char tempfile[FILENAME_MAX + 1]; + pthread_t echo_thread; + pthread_attr_t attr; + long num_recs = 0L; + short int rec_len = 56; + + pthread_t aprs_beacon_thread; + pthread_t irc_data_thread; + + /* START: TEXT crap */ + bool new_group[3] = { true, true, true }; + int header_type = 0; + short to_print[3] = { 0, 0, 0 }; + bool ABC_grp[3] = { false, false, false }; + bool C_seen[3] = { false, false, false }; + unsigned char tmp_txt[3]; + /* END: TEXT crap */ + + int ber_data[3]; + int ber_errs; + + int max_nfds = 0; + + dstar_dv_init(); + + if (g2_sock > max_nfds) + max_nfds = g2_sock; + if (srv_sock > max_nfds) + max_nfds = srv_sock; + traceit("g2=%d, srv=%d, MAX+1=%d\n", + g2_sock, srv_sock, max_nfds + 1); + + /* start the beacon thread */ + if (SEND_APRS) { + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&aprs_beacon_thread,&attr,send_aprs_beacon,(void *)0); + if (rc != 0) + traceit("failed to start the aprs beacon thread\n"); + else + traceit("APRS beacon thread started\n"); + pthread_attr_destroy(&attr); + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&irc_data_thread,&attr,get_irc_data,(void *)0); + if (rc != 0) { + traceit("failed to start the get_irc_data thread\n"); + keep_running = false; + } else + traceit("get_irc_data thread started\n"); + pthread_attr_destroy(&attr); + + while (keep_running) { + time(&t_now); + if ((t_now - wd_timer) >= 900) { + ii->kickWatchdog(PACKAGE_REV); + wd_timer = t_now; + } + + for (i = 0; i < 3; i++) { + /* echotest recording timed out? */ + if (recd[i].last_time != 0) { + time(&t_now); + if ((t_now - recd[i].last_time) > ECHOTEST_REC_TIMEOUT) { + traceit("Inactivity on echotest recording mod %d, removing stream id=%d,%d\n", + i,recd[i].streamid[0], recd[i].streamid[1]); + + recd[i].streamid[0] = 0x00; + recd[i].streamid[1] = 0x00; + recd[i].last_time = 0; + close(recd[i].fd); + recd[i].fd = -1; + // traceit("Closed echotest audio file:[%s]\n", recd[i].file); + + /* START: echotest thread setup */ + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&echo_thread, &attr, echotest, (void *)recd[i].file); + if (rc != 0) { + traceit("failed to start echotest thread\n"); + /* when the echotest thread runs, it deletes the file, + Because the echotest thread did NOT start, we delete the file here + */ + unlink(recd[i].file); + } + pthread_attr_destroy(&attr); + /* END: echotest thread setup */ + } + } + + /* voicemail recording timed out? */ + if (vm[i].last_time != 0) { + time(&t_now); + if ((t_now - vm[i].last_time) > VOICEMAIL_REC_TIMEOUT) { + traceit("Inactivity on voicemail recording mod %d, removing stream id=%d,%d\n", + i,vm[i].streamid[0], vm[i].streamid[1]); + + vm[i].streamid[0] = 0x00; + vm[i].streamid[1] = 0x00; + vm[i].last_time = 0; + close(vm[i].fd); + vm[i].fd = -1; + // traceit("Closed voicemail audio file:[%s]\n", vm[i].file); + } + } + + /* any stream going to local repeater timed out? */ + if (toRptr[i].last_time != 0) { + time(&t_now); + /* + The stream can be from a cross-band, or from a remote system, + so we could use either FROM_LOCAL_RPTR_TIMEOUT or FROM_REMOTE_G2_TIMEOUT + but FROM_REMOTE_G2_TIMEOUT makes more sense, probably is a bigger number + */ + if ((t_now - toRptr[i].last_time) > FROM_REMOTE_G2_TIMEOUT) { + traceit("Inactivity to local rptr mod index %d, removing stream id %d,%d\n", + i, toRptr[i].streamid[0], toRptr[i].streamid[1]); + /* + Send end_of_audio to local repeater. + Let the repeater re-initialize + */ + end_of_audio[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); + end_of_audio[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); + if (i == 0) + end_of_audio[13] = 0x03; + else if (i == 1) + end_of_audio[13] = 0x01; + else + end_of_audio[13] = 0x02; + end_of_audio[14] = toRptr[i].streamid[0]; + end_of_audio[15] = toRptr[i].streamid[1]; + end_of_audio[16] = toRptr[i].sequence | 0x40; + + for (j = 0; j < 2; j++) + sendto(srv_sock, (char *)end_of_audio,29,0, + (struct sockaddr *)&toRptr[i].band_addr, + sizeof(struct sockaddr_in)); + + toRptr[i].G2_COUNTER ++; + + toRptr[i].streamid[0] = '\0'; + toRptr[i].streamid[1] = '\0'; + toRptr[i].adr = 0; + toRptr[i].last_time = 0; + } + } + + /* any stream coming from local repeater timed out ? */ + if (band_txt[i].last_time != 0) { + time(&t_now); + if ((t_now - band_txt[i].last_time) > FROM_LOCAL_RPTR_TIMEOUT) { + /* This local stream never went to a remote system, so trace the timeout */ + if (to_remote_g2[i].toDst4.sin_addr.s_addr == 0) + traceit("Inactivity from local rptr band %d, removing stream id %d,%d\n", + i, band_txt[i].streamID[0], band_txt[i].streamID[1]); + + band_txt[i].streamID[0] = 0x00; + band_txt[i].streamID[1] = 0x00; + band_txt[i].flags[0] = 0x00; + band_txt[i].flags[1] = 0x00; + band_txt[i].flags[2] = 0x00; + band_txt[i].lh_mycall[0] = '\0'; + band_txt[i].lh_sfx[0] = '\0'; + band_txt[i].lh_yrcall[0] = '\0'; + band_txt[i].lh_rpt1[0] = '\0'; + band_txt[i].lh_rpt2[0] = '\0'; + + band_txt[i].last_time = 0; + + band_txt[i].txt[0] = '\0'; + band_txt[i].txt_cnt = 0; + + band_txt[i].dest_rptr[0] = '\0'; + + band_txt[i].num_dv_frames = 0; + band_txt[i].num_dv_silent_frames = 0; + band_txt[i].num_bit_errors = 0; + } + } + + /* any stream from local repeater to a remote gateway timed out ? */ + if (to_remote_g2[i].toDst4.sin_addr.s_addr != 0) { + time(&t_now); + if ((t_now - to_remote_g2[i].last_time) > FROM_LOCAL_RPTR_TIMEOUT) { + traceit("Inactivity from local rptr mod %d, removing stream id %d,%d\n", + i, to_remote_g2[i].streamid[0], to_remote_g2[i].streamid[1]); + + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].streamid[0] = '\0'; + to_remote_g2[i].streamid[1] = '\0'; + to_remote_g2[i].last_time = 0; + } + } + } + + /* wait 20 ms max */ + FD_ZERO(&fdset); + FD_SET(g2_sock,&fdset); + FD_SET(srv_sock,&fdset); + tv.tv_sec = 0; + tv.tv_usec = 20000; /* 20 ms */ + (void)select(max_nfds + 1,&fdset,0,0,&tv); + + /* process packets coming from remote G2 */ + if (FD_ISSET(g2_sock, &fdset)) { + fromlen = sizeof(struct sockaddr_in); + recvlen2 = recvfrom(g2_sock,(char *)readBuffer2,2000, + 0,(struct sockaddr *)&fromDst4,&fromlen); + + if ( ((recvlen2 == 56) || + (recvlen2 == 27)) && + (memcmp(readBuffer2, "DSVT", 4) == 0) && + ((readBuffer2[4] == 0x10) || /* header */ + (readBuffer2[4] == 0x20)) && /* details */ + (readBuffer2[8] == 0x20)) { /* voice type */ + if (recvlen2 == 56) { + + /* + Find out the local repeater module IP/port + to send the data to + */ + i = -1; + if (readBuffer2[25] == 'A') + i = 0; + else if (readBuffer2[25] == 'B') + i = 1; + else if (readBuffer2[25] == 'C') + i = 2; + + /* valid repeater module? */ + if (i >= 0) { + /* + toRptr[i] is active if a remote system is talking to it or + toRptr[i] is receiving data from a cross-band + */ + if ((toRptr[i].last_time == 0) && (band_txt[i].last_time == 0) && + ((readBuffer2[15] == 0x00) || + (readBuffer2[15] == 0x01) || /* allow the announcements from g2_link */ + (readBuffer2[15] == 0x08) || + (readBuffer2[15] == 0x20) || + (readBuffer2[15] == 0x28) || + (readBuffer2[15] == 0x40))) { + if (QSO_DETAILS) + traceit("START from g2: streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s\n", + readBuffer2[12],readBuffer2[13], + readBuffer2[15], readBuffer2[16], readBuffer2[17], + &readBuffer2[42], + &readBuffer2[50], &readBuffer2[34], + &readBuffer2[18], &readBuffer2[26], + recvlen2,inet_ntoa(fromDst4.sin_addr)); + + memcpy(readBuffer,"DSTR", 4); + readBuffer[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); + readBuffer[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); + readBuffer[6] = 0x73; + readBuffer[7] = 0x12; + readBuffer[8] = 0x00; + readBuffer[9] = 0x30; + readBuffer[10] = 0x20; + memcpy(readBuffer + 11, readBuffer2 + 9, 47); + sendto(srv_sock, (char *)readBuffer,58,0, + (struct sockaddr *)&toRptr[i].band_addr, + sizeof(struct sockaddr_in)); + + /* save the header */ + memcpy(toRptr[i].saved_hdr, readBuffer, 58); + toRptr[i].saved_adr = fromDst4.sin_addr.s_addr; + + /* This is the active streamid */ + toRptr[i].streamid[0] = readBuffer2[12]; + toRptr[i].streamid[1] = readBuffer2[13]; + toRptr[i].adr = fromDst4.sin_addr.s_addr; + + /* time it, in case stream times out */ + time(&toRptr[i].last_time); + + /* bump the G2 counter */ + toRptr[i].G2_COUNTER ++; + + toRptr[i].sequence = readBuffer[16]; + } + } + } else { + if ((readBuffer2[14] & 0x40) != 0) { + if (QSO_DETAILS) + traceit("END from g2: streamID=%d,%d, %d bytes from IP=%s\n", + readBuffer2[12],readBuffer2[13], + recvlen2,inet_ntoa(fromDst4.sin_addr)); + } + + /* find out which repeater module to send the data to */ + for (i = 0; i < 3; i++) { + /* streamid match ? */ + if ((memcmp(toRptr[i].streamid, readBuffer2 + 12, 2) == 0) && + (toRptr[i].adr == fromDst4.sin_addr.s_addr)) { + memcpy(readBuffer,"DSTR", 4); + readBuffer[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); + readBuffer[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); + readBuffer[6] = 0x73; + readBuffer[7] = 0x12; + readBuffer[8] = 0x00; + readBuffer[9] = 0x13; + readBuffer[10] = 0x20; + memcpy(readBuffer + 11, readBuffer2 + 9, 18); + + sendto(srv_sock, (char *)readBuffer,29,0, + (struct sockaddr *)&toRptr[i].band_addr, + sizeof(struct sockaddr_in)); + + /* timeit */ + time(&toRptr[i].last_time); + + /* bump G2 counter */ + toRptr[i].G2_COUNTER ++; + + toRptr[i].sequence = readBuffer[16]; + + /* End of stream ? */ + if ((readBuffer2[14] & 0x40) != 0) { + /* clear the saved header */ + memset(toRptr[i].saved_hdr, 0, sizeof(toRptr[i].saved_hdr)); + toRptr[i].saved_adr = 0; + + toRptr[i].last_time = 0; + toRptr[i].streamid[0] = '\0'; + toRptr[i].streamid[1] = '\0'; + toRptr[i].adr = 0; + } + break; + } + } + + /* no match ? */ + if ((i == 3) && REGEN_HDR) { + /* check if this a continuation of audio that timed out */ + + if ((readBuffer2[14] & 0x40) != 0) + ; /* we do not care about end-of-QSO */ + else { + /* for which repeater this stream has timed out ? */ + for (i = 0; i < 3; i++) { + /* match saved stream ? */ + if ((memcmp(toRptr[i].saved_hdr + 14, readBuffer2 + 12, 2) == 0) && + (toRptr[i].saved_adr == fromDst4.sin_addr.s_addr)) { + /* repeater module is inactive ? */ + if ((toRptr[i].last_time == 0) && (band_txt[i].last_time == 0)) { + traceit("Re-generating header for streamID=%d,%d\n", readBuffer2[12],readBuffer2[13]); + + toRptr[i].saved_hdr[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); + toRptr[i].saved_hdr[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); + + /* re-generate/send the header */ + sendto(srv_sock, (char *)toRptr[i].saved_hdr,58,0, + (struct sockaddr *)&toRptr[i].band_addr, + sizeof(struct sockaddr_in)); + + /* bump G2 counter */ + toRptr[i].G2_COUNTER ++; + + /* send this audio packet to repeater */ + memcpy(readBuffer,"DSTR", 4); + readBuffer[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); + readBuffer[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); + readBuffer[6] = 0x73; + readBuffer[7] = 0x12; + readBuffer[8] = 0x00; + readBuffer[9] = 0x13; + readBuffer[10] = 0x20; + memcpy(readBuffer + 11, readBuffer2 + 9, 18); + + sendto(srv_sock, (char *)readBuffer,29,0, + (struct sockaddr *)&toRptr[i].band_addr, + sizeof(struct sockaddr_in)); + + /* make sure that any more audio arriving will be accepted */ + toRptr[i].streamid[0] = readBuffer2[12]; + toRptr[i].streamid[1] = readBuffer2[13]; + toRptr[i].adr = fromDst4.sin_addr.s_addr; + + /* time it, in case stream times out */ + time(&toRptr[i].last_time); + + /* bump the G2 counter */ + toRptr[i].G2_COUNTER ++; + + toRptr[i].sequence = readBuffer[16]; + + } + break; + } + } + } + } + } + } + FD_CLR (g2_sock,&fdset); + } + + /* process data coming from local repeater modules */ + if (FD_ISSET(srv_sock, &fdset)) { + fromlen = sizeof(struct sockaddr_in); + recvlen = recvfrom(srv_sock,(char *)readBuffer,2000, + 0,(struct sockaddr *)&fromRptr,&fromlen); + + /* DV */ + if ( ((recvlen == 58) || + (recvlen == 29) || + (recvlen == 32)) && + (readBuffer[6] == 0x73) && + (readBuffer[7] == 0x12) && + (memcmp(readBuffer,"DSTR", 4) == 0) && + (readBuffer[10] == 0x20) && + (readBuffer[8] == 0x00) && + ((readBuffer[9] == 0x30) || /* 48 bytes follow */ + (readBuffer[9] == 0x13) || /* 19 bytes follow */ + (readBuffer[9] == 0x16)) ) { /* 22 bytes follow */ + + if (recvlen == 58) { + if (QSO_DETAILS) + traceit("START from rptr: cntr=%02x %02x, streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s\n", + readBuffer[4], readBuffer[5], + readBuffer[14], readBuffer[15], + readBuffer[17], readBuffer[18], readBuffer[19], + readBuffer + 44, readBuffer + 52, readBuffer + 36, + readBuffer + 28, readBuffer + 20, recvlen, inet_ntoa(fromRptr.sin_addr)); + + if ((memcmp(readBuffer + 28, OWNER, 7) == 0) && /* rpt1 is this repeater */ + /*** (memcmp(readBuffer + 44, OWNER, 7) != 0) && ***/ /* MYCALL is NOT this repeater */ + ((readBuffer[17] == 0x00) || /* normal */ + (readBuffer[17] == 0x08) || /* EMR */ + (readBuffer[17] == 0x20) || /* BREAK */ + (readBuffer[17] == 0x28))) { /* EMR + BREAK */ + + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + dtmf_last_frame[i] = 0; + dtmf_counter[i] = 0; + memset(dtmf_buf[i], 0, sizeof(dtmf_buf[i])); + dtmf_buf_count[i] = 0; + + /* Initialize the LAST HEARD data for the band */ + + band_txt[i].streamID[0] = readBuffer[14]; + band_txt[i].streamID[1] = readBuffer[15]; + + band_txt[i].flags[0] = readBuffer[17]; + band_txt[i].flags[1] = readBuffer[18]; + band_txt[i].flags[2] = readBuffer[19]; + + memcpy(band_txt[i].lh_mycall, readBuffer + 44, CALL_SIZE); + band_txt[i].lh_mycall[CALL_SIZE] = '\0'; + + memcpy(band_txt[i].lh_sfx, readBuffer + 52, 4); + band_txt[i].lh_sfx[4] = '\0'; + + memcpy(band_txt[i].lh_yrcall, readBuffer + 36, CALL_SIZE); + band_txt[i].lh_yrcall[CALL_SIZE] = '\0'; + + memcpy(band_txt[i].lh_rpt1, readBuffer + 28, CALL_SIZE); + band_txt[i].lh_rpt1[CALL_SIZE] = '\0'; + + memcpy(band_txt[i].lh_rpt2, readBuffer + 20, CALL_SIZE); + band_txt[i].lh_rpt2[CALL_SIZE] = '\0'; + + time(&band_txt[i].last_time); + + band_txt[i].txt[0] = '\0'; + band_txt[i].txt_cnt = 0; + band_txt[i].txt_stats_sent = false; + + band_txt[i].dest_rptr[0] = '\0'; + + /* try to process GPS mode: GPRMC and ID */ + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + band_txt[i].gprmc[0] = '\0'; + band_txt[i].gpid[0] = '\0'; + band_txt[i].is_gps_sent = false; + // band_txt[i].gps_last_time = 0; DO NOT reset it + + new_group[i] = true; + to_print[i] = 0; + ABC_grp[i] = false; + + band_txt[i].num_dv_frames = 0; + band_txt[i].num_dv_silent_frames = 0; + band_txt[i].num_bit_errors = 0; + + /* select the band for aprs processing, and lock on the stream ID */ + if (SEND_APRS) + aprs_select_band(i, readBuffer + 14); + } + } + + /* Is MYCALL valid ? */ + memset(temp_radio_user, ' ', CALL_SIZE); + memcpy(temp_radio_user, readBuffer + 44, 8); + temp_radio_user[CALL_SIZE] = '\0'; + + mycall_valid = regexec(&preg, temp_radio_user, 0, NULL, 0); + + if (mycall_valid == REG_NOERROR) + ; // traceit("MYCALL [%s] passed IRC expression validation\n", temp_radio_user); + else { + if (mycall_valid == REG_NOMATCH) + traceit("MYCALL [%s] failed IRC expression validation\n", temp_radio_user); + else + traceit("Failed to validate MYCALL [%s], regexec error=%d\n", temp_radio_user, mycall_valid); + } + + /* send data g2_link */ + if (mycall_valid == REG_NOERROR) + sendto(srv_sock, (char *)readBuffer, recvlen,0, + (struct sockaddr *)&plug, + sizeof(struct sockaddr_in)); + + if ((mycall_valid == REG_NOERROR) && + (memcmp(readBuffer + 36, "XRF", 3) != 0) && /* not a reflector */ + (memcmp(readBuffer + 36, "REF", 3) != 0) && /* not a reflector */ + (memcmp(readBuffer + 36, "DCS", 3) != 0) && /* not a reflector */ + (readBuffer[36] != ' ') && /* must have something */ + (memcmp(readBuffer + 36, "CQCQCQ", 6) != 0)) { /* urcall is NOT CQCQCQ */ + if ((readBuffer[36] == '/') && /* urcall starts with a slash */ + (memcmp(readBuffer + 28, OWNER, 7) == 0) && /* rpt1 is this repeater */ + ((readBuffer[35] == 'A') || + (readBuffer[35] == 'B') || + (readBuffer[35] == 'C')) && /* mod is A,B,C */ + (memcmp(readBuffer + 20, OWNER, 7) == 0) && /* rpt2 is this repeater */ + (readBuffer[27] == 'G') && /* local Gateway */ + /*** (memcmp(readBuffer + 44, OWNER, 7) != 0) && ***/ /* mycall is NOT this repeater */ + + ((readBuffer[17] == 0x00) || /* normal */ + (readBuffer[17] == 0x08) || /* EMR */ + (readBuffer[17] == 0x20) || /* BK */ + (readBuffer[17] == 0x28)) /* EMR + BK */ + ) { + if (memcmp(readBuffer + 37, OWNER, 6) != 0) { /* the value after the slash in urcall, is NOT this repeater */ + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + /* one radio user on a repeater module at a time */ + if (to_remote_g2[i].toDst4.sin_addr.s_addr == 0) { + /* YRCALL=/repeater + mod */ + /* YRCALL=/KJ4NHFB */ + + memset(temp_radio_user, ' ', CALL_SIZE); + memcpy(temp_radio_user, readBuffer + 37, 6); + temp_radio_user[6] = ' '; + temp_radio_user[7] = readBuffer[43]; + if (temp_radio_user[7] == ' ') + temp_radio_user[7] = 'A'; + temp_radio_user[CALL_SIZE] = '\0'; + + result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'R'); + if (result) { /* it is a repeater */ + /* set the destination */ + memcpy(to_remote_g2[i].streamid, readBuffer + 14, 2); + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].toDst4.sin_family = AF_INET; + to_remote_g2[i].toDst4.sin_port = htons(G2_EXTERNAL_PORT); + to_remote_g2[i].toDst4.sin_addr.s_addr = inet_addr(ip); + + memcpy(readBuffer2, "DSVT", 4); + readBuffer2[4] = 0x10; + readBuffer2[5] = 0x00; + readBuffer2[6] = 0x00; + readBuffer2[7] = 0x00; + readBuffer2[8] = readBuffer[10]; + readBuffer2[9] = readBuffer[11]; + readBuffer2[10] = readBuffer[12]; + readBuffer2[11] = readBuffer[13]; + memcpy(readBuffer2 + 12, readBuffer + 14, 44); + /* set rpt1 */ + memset(readBuffer2 + 18, ' ', CALL_SIZE); + memcpy(readBuffer2 + 18, arearp_cs, strlen(arearp_cs)); + readBuffer2[25] = temp_mod; + /* set rpt2 */ + memset(readBuffer2 + 26, ' ', CALL_SIZE); + memcpy(readBuffer2 + 26, zonerp_cs, strlen(zonerp_cs)); + readBuffer2[33] = 'G'; + /* set yrcall, can NOT let it be slash and repeater + module */ + memcpy(readBuffer2 + 34, "CQCQCQ ", 8); + + /* set PFCS */ + calcPFCS(readBuffer2, 56); + + /* + The remote repeater has been set, lets fill in the dest_rptr + so that later we can send that to the LIVE web site + */ + memcpy(band_txt[i].dest_rptr, readBuffer2 + 18, CALL_SIZE); + band_txt[i].dest_rptr[CALL_SIZE] = '\0'; + + /* send to remote gateway */ + for (j = 0; j < 5; j++) + sendto(g2_sock, (char *)readBuffer2, 56, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + + traceit("Routing to IP=%s, streamID=%d,%d, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes\n", + inet_ntoa(to_remote_g2[i].toDst4.sin_addr), + readBuffer2[12],readBuffer2[13],&readBuffer2[42], + &readBuffer2[50], &readBuffer2[34], + &readBuffer2[18], &readBuffer2[26], + 56); + + time(&(to_remote_g2[i].last_time)); + } + } + } + } + } else if ((memcmp(readBuffer + 36, OWNER, 7) != 0) && /* urcall is not this repeater */ + (memcmp(readBuffer + 28, OWNER, 7) == 0) && /* rpt1 is this repeater */ + ((readBuffer[35] == 'A') || + (readBuffer[35] == 'B') || + (readBuffer[35] == 'C')) && /* mod is A,B,C */ + (memcmp(readBuffer + 20, OWNER, 7) == 0) && /* rpt2 is this repeater */ + (readBuffer[27] == 'G') && /* local Gateway */ + /*** (memcmp(readBuffer + 44, OWNER, 7) != 0) && ***/ /* mycall is NOT this repeater */ + + ((readBuffer[17] == 0x00) || /* normal */ + (readBuffer[17] == 0x08) || /* EMR */ + (readBuffer[17] == 0x20) || /* BK */ + (readBuffer[17] == 0x28)) /* EMR + BK */ + ) { + + memset(temp_radio_user, ' ', CALL_SIZE); + memcpy(temp_radio_user, readBuffer + 36, CALL_SIZE); + temp_radio_user[CALL_SIZE] = '\0'; + result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'U'); + if (result) { + /* destination is a remote system */ + if (memcmp(zonerp_cs, OWNER, 7) != 0) { + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + /* one radio user on a repeater module at a time */ + if (to_remote_g2[i].toDst4.sin_addr.s_addr == 0) { + /* set the destination */ + memcpy(to_remote_g2[i].streamid, readBuffer + 14, 2); + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].toDst4.sin_family = AF_INET; + to_remote_g2[i].toDst4.sin_port = htons(G2_EXTERNAL_PORT); + to_remote_g2[i].toDst4.sin_addr.s_addr = inet_addr(ip); + + memcpy(readBuffer2, "DSVT", 4); + readBuffer2[4] = 0x10; + readBuffer2[5] = 0x00; + readBuffer2[6] = 0x00; + readBuffer2[7] = 0x00; + readBuffer2[8] = readBuffer[10]; + readBuffer2[9] = readBuffer[11]; + readBuffer2[10] = readBuffer[12]; + readBuffer2[11] = readBuffer[13]; + memcpy(readBuffer2 + 12, readBuffer + 14, 44); + /* set rpt1 */ + memset(readBuffer2 + 18, ' ', CALL_SIZE); + memcpy(readBuffer2 + 18, arearp_cs, strlen(arearp_cs)); + readBuffer2[25] = temp_mod; + /* set rpt2 */ + memset(readBuffer2 + 26, ' ', CALL_SIZE); + memcpy(readBuffer2 + 26, zonerp_cs, strlen(zonerp_cs)); + readBuffer2[33] = 'G'; + /* set PFCS */ + calcPFCS(readBuffer2, 56); + + /* + The remote repeater has been set, lets fill in the dest_rptr + so that later we can send that to the LIVE web site + */ + memcpy(band_txt[i].dest_rptr, readBuffer2 + 18, CALL_SIZE); + band_txt[i].dest_rptr[CALL_SIZE] = '\0'; + + /* send to remote gateway */ + for (j = 0; j < 5; j++) + sendto(g2_sock, (char *)readBuffer2, 56, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + + traceit("Routing to IP=%s, streamID=%d,%d, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes\n", + inet_ntoa(to_remote_g2[i].toDst4.sin_addr), + readBuffer2[12],readBuffer2[13],&readBuffer2[42], + &readBuffer2[50], &readBuffer2[34], + &readBuffer2[18], &readBuffer2[26], + 56); + + time(&(to_remote_g2[i].last_time)); + } + } + } else { + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + /* the user we are trying to contact is on our gateway */ + /* make sure they are on a different module */ + if (temp_mod != readBuffer[35]) { + /* + The remote repeater has been set, lets fill in the dest_rptr + so that later we can send that to the LIVE web site + */ + memcpy(band_txt[i].dest_rptr, readBuffer + 20, CALL_SIZE); + band_txt[i].dest_rptr[7] = temp_mod; + band_txt[i].dest_rptr[CALL_SIZE] = '\0'; + + i = -1; + if (temp_mod == 'A') + i = 0; + else if (temp_mod == 'B') + i = 1; + else if (temp_mod == 'C') + i = 2; + + /* valid destination repeater module? */ + if (i >= 0) { + /* + toRptr[i] : receiving from a remote system or cross-band + band_txt[i] : local RF is talking. + */ + if ((toRptr[i].last_time == 0) && (band_txt[i].last_time == 0)) { + traceit("CALLmode cross-banding from mod %c to %c\n", readBuffer[35], temp_mod); + + readBuffer[27] = temp_mod; + readBuffer[35] = 'G'; + calcPFCS(readBuffer, 58); + + sendto(srv_sock, (char *)readBuffer,58,0, + (struct sockaddr *)&toRptr[i].band_addr, + sizeof(struct sockaddr_in)); + + /* This is the active streamid */ + toRptr[i].streamid[0] = readBuffer[14]; + toRptr[i].streamid[1] = readBuffer[15]; + toRptr[i].adr = fromRptr.sin_addr.s_addr; + + /* time it, in case stream times out */ + time(&toRptr[i].last_time); + + /* bump the G2 counter */ + toRptr[i].G2_COUNTER ++; + + toRptr[i].sequence = readBuffer[16]; + } + } + } else + traceit("icom rule: no routing from %.8s to %s%c\n", readBuffer + 28, arearp_cs,temp_mod); + } + } + } + } + } else if ((readBuffer[43] == '0') && + (readBuffer[42] == CLEAR_VM_CODE) && + (readBuffer[36] == ' ')) { + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + /* voicemail file is closed */ + if ((vm[i].fd == -1) && (vm[i].file[0] != '\0')) { + unlink(vm[i].file); + traceit("removed voicemail file: %s\n", vm[i].file); + vm[i].file[0] = '\0'; + } else + traceit("No voicemail to clear or still recording\n"); + } + } else if ((readBuffer[43] == '0') && + (readBuffer[42] == RECALL_VM_CODE) && + (readBuffer[36] == ' ')) { + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + /* voicemail file is closed */ + if ((vm[i].fd == -1) && (vm[i].file[0] != '\0')) { + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&echo_thread, &attr, echotest, (void *)vm[i].file); + if (rc != 0) + traceit("failed to start playing back voicemail\n"); + pthread_attr_destroy(&attr); + } else + traceit("No voicemail to recall or still recording\n"); + } + } else if ((readBuffer[43] == '0') && + (readBuffer[42] == STORE_VM_CODE) && + (readBuffer[36] == ' ')) { + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + if (vm[i].fd >= 0) + traceit("Already recording for voicemail on mod %d\n", i); + else { + memset(tempfile, '\0', sizeof(tempfile)); + snprintf(tempfile, FILENAME_MAX, "%s/%c_%s", + ECHOTEST_DIR, + readBuffer[35], + "voicemail.dat"); + + vm[i].fd = open(tempfile, + O_CREAT | O_WRONLY | O_TRUNC | O_APPEND, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (vm[i].fd < 0) + traceit("Failed to create file %s for voicemail\n", tempfile); + else { + strcpy(vm[i].file, tempfile); + traceit("Recording mod %c for voicemail into file:[%s]\n", + readBuffer[35], + vm[i].file); + + time(&vm[i].last_time); + memcpy(vm[i].streamid, readBuffer + 14, 2); + + memcpy(recbuf, "DSVT", 4); + recbuf[4] = 0x10; + recbuf[5] = 0x00; + recbuf[6] = 0x00; + recbuf[7] = 0x00; + recbuf[8] = readBuffer[10]; + recbuf[9] = readBuffer[11]; + recbuf[10] = readBuffer[12]; + recbuf[11] = readBuffer[13]; + memcpy(recbuf + 12, readBuffer + 14, 44); + memset(recbuf + 18, ' ', CALL_SIZE); + memcpy(recbuf + 18, OWNER, strlen(OWNER)); + recbuf[25] = readBuffer[35]; + memset(recbuf + 26, ' ', CALL_SIZE); + memcpy(recbuf + 26, OWNER, strlen(OWNER)); + recbuf[33] = 'G'; + memcpy(recbuf + 34, "CQCQCQ ", 8); + + calcPFCS(recbuf,56); + + rec_len = 56; + (void)write(vm[i].fd, "DVTOOL", 6); + (void)write(vm[i].fd, &num_recs, 4); + (void)write(vm[i].fd, &rec_len, 2); + (void)write(vm[i].fd, (char *)recbuf, rec_len); + } + } + } + } else if ((readBuffer[43] == ECHO_CODE) && + (readBuffer[36] == ' ')) { + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + if (recd[i].fd >= 0) + traceit("Already recording for echotest on mod %d\n", i); + else { + memset(tempfile, '\0', sizeof(tempfile)); + snprintf(tempfile, FILENAME_MAX, "%s/%c_%s", + ECHOTEST_DIR, + readBuffer[35], + "echotest.dat"); + + recd[i].fd = open(tempfile, + O_CREAT | O_WRONLY | O_EXCL | O_TRUNC | O_APPEND, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (recd[i].fd < 0) + traceit("Failed to create file %s for echotest\n", tempfile); + else { + strcpy(recd[i].file, tempfile); + traceit("Recording mod %c for echotest into file:[%s]\n", + readBuffer[35], + recd[i].file); + + time(&recd[i].last_time); + memcpy(recd[i].streamid, readBuffer + 14, 2); + + memcpy(recbuf, "DSVT", 4); + recbuf[4] = 0x10; + recbuf[5] = 0x00; + recbuf[6] = 0x00; + recbuf[7] = 0x00; + recbuf[8] = readBuffer[10]; + recbuf[9] = readBuffer[11]; + recbuf[10] = readBuffer[12]; + recbuf[11] = readBuffer[13]; + memcpy(recbuf + 12, readBuffer + 14, 44); + memset(recbuf + 18, ' ', CALL_SIZE); + memcpy(recbuf + 18, OWNER, strlen(OWNER)); + recbuf[25] = readBuffer[35]; + memset(recbuf + 26, ' ', CALL_SIZE); + memcpy(recbuf + 26, OWNER, strlen(OWNER)); + recbuf[33] = 'G'; + memcpy(recbuf + 34, "CQCQCQ ", 8); + + calcPFCS(recbuf,56); + + rec_len = 56; + (void)write(recd[i].fd, "DVTOOL", 6); + (void)write(recd[i].fd, &num_recs, 4); + (void)write(recd[i].fd, &rec_len, 2); + (void)write(recd[i].fd, (char *)recbuf, rec_len); + } + } + } + } else + /* check for cross-banding */ + if ((memcmp(readBuffer + 36, "CQCQCQ", 6) == 0) && /* yrcall is CQCQCQ */ + (memcmp(readBuffer + 28, OWNER, 7) == 0) && /* rpt1 is this repeater */ + (memcmp(readBuffer + 20, OWNER, 7) == 0) && /* rpt2 is this repeater */ + ((readBuffer[35] == 'A') || + (readBuffer[35] == 'B') || + (readBuffer[35] == 'C')) && /* mod of rpt1 is A,B,C */ + ((readBuffer[27] == 'A') || + (readBuffer[27] == 'B') || + (readBuffer[27] == 'C')) && /* !!! usually a G of rpt2, but we see A,B,C */ + (readBuffer[35] != readBuffer[27])) { /* cross-banding? make sure NOT the same */ + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + /* + The remote repeater has been set, lets fill in the dest_rptr + so that later we can send that to the LIVE web site + */ + memcpy(band_txt[i].dest_rptr, readBuffer + 20, CALL_SIZE); + band_txt[i].dest_rptr[CALL_SIZE] = '\0'; + } + + i = -1; + if (readBuffer[27] == 'A') + i = 0; + else if (readBuffer[27] == 'B') + i = 1; + else if (readBuffer[27] == 'C') + i = 2; + + /* valid destination repeater module? */ + if (i >= 0) { + /* + toRptr[i] : receiving from a remote system or cross-band + band_txt[i] : local RF is talking. + */ + if ((toRptr[i].last_time == 0) && (band_txt[i].last_time == 0)) { + traceit("ZONEmode cross-banding from mod %c to %c\n", readBuffer[35], readBuffer[27]); + + readBuffer[35] = 'G'; + calcPFCS(readBuffer, 58); + + sendto(srv_sock, (char *)readBuffer,58,0, + (struct sockaddr *)&toRptr[i].band_addr, + sizeof(struct sockaddr_in)); + + /* This is the active streamid */ + toRptr[i].streamid[0] = readBuffer[14]; + toRptr[i].streamid[1] = readBuffer[15]; + toRptr[i].adr = fromRptr.sin_addr.s_addr; + + /* time it, in case stream times out */ + time(&toRptr[i].last_time); + + /* bump the G2 counter */ + toRptr[i].G2_COUNTER ++; + + toRptr[i].sequence = readBuffer[16]; + } + } + } + } else { + for (i = 0; i < 3; i++) { + if (memcmp(band_txt[i].streamID, readBuffer + 14, 2) == 0) { + time(&band_txt[i].last_time); + + if ((readBuffer[16] & 0x40) != 0) { + if (dtmf_buf_count[i] > 0) { + memset(DTMF_FILE, 0, sizeof(DTMF_FILE)); + snprintf(DTMF_FILE, FILENAME_MAX, "%s/%d_mod_DTMF_NOTIFY", DTMF_DIR, i); + if (DTMF_DEBUG) + traceit("Saving dtmfs=[%s] into file: [%s]\n", dtmf_buf[i], DTMF_FILE); + dtmf_fp = fopen(DTMF_FILE, "w"); + if (!dtmf_fp) + traceit("Failed to create dtmf file %s\n", DTMF_FILE); + else { + fprintf(dtmf_fp, "%s\n%s", dtmf_buf[i], band_txt[i].lh_mycall); + fclose(dtmf_fp); + dtmf_fp = NULL; + } + memset(dtmf_buf[i], 0, sizeof(dtmf_buf[i])); + dtmf_buf_count[i] = 0; + dtmf_counter[i] = 0; + dtmf_last_frame[i] = 0; + } + + ii->sendHeardWithTXStats(band_txt[i].lh_mycall, + band_txt[i].lh_sfx, + (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", + band_txt[i].lh_rpt1, + band_txt[i].lh_rpt2, + band_txt[i].flags[0], + band_txt[i].flags[1], + band_txt[i].flags[2], + band_txt[i].num_dv_frames, + band_txt[i].num_dv_silent_frames, + band_txt[i].num_bit_errors); + + band_txt[i].streamID[0] = 0x00; + band_txt[i].streamID[1] = 0x00; + band_txt[i].flags[0] = 0x00; + band_txt[i].flags[1] = 0x00; + band_txt[i].flags[2] = 0x00; + band_txt[i].lh_mycall[0] = '\0'; + band_txt[i].lh_sfx[0] = '\0'; + band_txt[i].lh_yrcall[0] = '\0'; + band_txt[i].lh_rpt1[0] = '\0'; + band_txt[i].lh_rpt2[0] = '\0'; + + band_txt[i].last_time = 0; + + band_txt[i].txt[0] = '\0'; + band_txt[i].txt_cnt = 0; + + band_txt[i].dest_rptr[0] = '\0'; + + band_txt[i].num_dv_frames = 0; + band_txt[i].num_dv_silent_frames = 0; + band_txt[i].num_bit_errors = 0; + + } else { + ber_errs = dstar_dv_decode(readBuffer + 17, ber_data); + if (ber_data[0] == 0xf85) + band_txt[i].num_dv_silent_frames ++; + band_txt[i].num_bit_errors += ber_errs; + band_txt[i].num_dv_frames ++; + + if ((ber_data[0] & 0x0ffc) == 0xfc0) { + dtmf_digit = (ber_data[0] & 0x03) | ((ber_data[2] & 0x60) >> 3); + if (dtmf_counter[i] > 0) { + if (dtmf_last_frame[i] != dtmf_digit) + dtmf_counter[i] = 0; + } + dtmf_last_frame[i] = dtmf_digit; + dtmf_counter[i] ++; + + if ((dtmf_counter[i] == 5) && (dtmf_digit >= 0) && (dtmf_digit <= 15)) { + if (dtmf_buf_count[i] < MAX_DTMF_BUF) { + dtmf_buf[i][ dtmf_buf_count[i] ] = dtmf_chars[dtmf_digit]; + dtmf_buf_count[i] ++; + } + } + memcpy(readBuffer + 17, silence, 9); + } else + dtmf_counter[i] = 0; + } + break; + } + } + + if (recvlen == 29) + memcpy(tmp_txt, readBuffer + 26, 3); + else + memcpy(tmp_txt, readBuffer + 29, 3); + + // traceit("%x%x%x\n", tmp_txt[0], tmp_txt[1], tmp_txt[2]); + // traceit("%c%c%c\n", tmp_txt[0] ^ 0x70, tmp_txt[1] ^ 0x4f, tmp_txt[2] ^ 0x93); + + /* extract 20-byte RADIO ID */ + if ((tmp_txt[0] != 0x55) || (tmp_txt[1] != 0x2d) || (tmp_txt[2] != 0x16)) { + // traceit("%x%x%x\n", tmp_txt[0], tmp_txt[1], tmp_txt[2]); + // traceit("%c%c%c\n", tmp_txt[0] ^ 0x70, tmp_txt[1] ^ 0x4f, tmp_txt[2] ^ 0x93); + + for (i = 0; i < 3; i++) { + if (memcmp(band_txt[i].streamID, readBuffer + 14, 2) == 0) { + if (new_group[i]) { + tmp_txt[0] = tmp_txt[0] ^ 0x70; + header_type = tmp_txt[0] & 0xf0; + + if ((header_type == 0x50) || /* header */ + (header_type == 0xc0)) { /* squelch */ + new_group[i] = false; + to_print[i] = 0; + ABC_grp[i] = false; + } else if (header_type == 0x30) { /* GPS or GPS id or APRS */ + new_group[i] = false; + to_print[i] = tmp_txt[0] & 0x0f; + ABC_grp[i] = false; + if (to_print[i] > 5) + to_print[i] = 5; + else if (to_print[i] < 1) + to_print[i] = 1; + + if ((to_print[i] > 1) && (to_print[i] <= 5)) { + /* something went wrong? all bets are off */ + if (band_txt[i].temp_line_cnt > 200) { + traceit("Reached the limit in the OLD gps mode\n"); + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + + /* fresh GPS string, re-initialize */ + if ((to_print[i] == 5) && ((tmp_txt[1] ^ 0x4f) == '$')) { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + + /* do not copy CR, NL */ + if (((tmp_txt[1] ^ 0x4f) != '\r') && ((tmp_txt[1] ^ 0x4f) != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[1] ^ 0x4f; + band_txt[i].temp_line_cnt++; + } + if (((tmp_txt[2] ^ 0x93) != '\r') && ((tmp_txt[2] ^ 0x93) != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[2] ^ 0x93; + band_txt[i].temp_line_cnt++; + } + + if (((tmp_txt[1] ^ 0x4f) == '\r') || ((tmp_txt[2] ^ 0x93) == '\r')) { + if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { + memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; + } else if (band_txt[i].temp_line[0] != '$') { + memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; + if (SEND_APRS && !band_txt[i].is_gps_sent) + gps_send(i); + } + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } else if (((tmp_txt[1] ^ 0x4f) == '\n') || ((tmp_txt[2] ^ 0x93) == '\n')) { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + to_print[i] -= 2; + } else { + /* something went wrong? all bets are off */ + if (band_txt[i].temp_line_cnt > 200) { + traceit("Reached the limit in the OLD gps mode\n"); + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + + /* do not copy CR, NL */ + if (((tmp_txt[1] ^ 0x4f) != '\r') && ((tmp_txt[1] ^ 0x4f) != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[1] ^ 0x4f; + band_txt[i].temp_line_cnt++; + } + + if ((tmp_txt[1] ^ 0x4f) == '\r') { + if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { + memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; + } else if (band_txt[i].temp_line[0] != '$') { + memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; + if (SEND_APRS && !band_txt[i].is_gps_sent) + gps_send(i); + } + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } else if ((tmp_txt[1] ^ 0x4f) == '\n') { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + to_print[i] --; + } + } else if (header_type == 0x40) { /* ABC text */ + new_group[i] = false; + to_print[i] = 3; + ABC_grp[i] = true; + C_seen[i] = ((tmp_txt[0] & 0x0f) == 0x03)?true:false; + + band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[1] ^ 0x4f; + band_txt[i].txt_cnt++; + + band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[2] ^ 0x93; + band_txt[i].txt_cnt++; + + /* + We should NOT see any more text, + if we already processed text, + so blank out the codes. + */ + if (band_txt[i].txt_stats_sent) { + if (recvlen == 29) { + readBuffer[26] = 0x70; + readBuffer[27] = 0x4f; + readBuffer[28] = 0x93; + } else { + readBuffer[29] = 0x70; + readBuffer[30] = 0x4f; + readBuffer[31] = 0x93; + } + } + + if (band_txt[i].txt_cnt >= 20) { + band_txt[i].txt[band_txt[i].txt_cnt] = '\0'; + /*** + ii->sendHeardWithTXMsg(band_txt[i].lh_mycall, + band_txt[i].lh_sfx, + (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", + band_txt[i].lh_rpt1, + band_txt[i].lh_rpt2, + band_txt[i].flags[0], + band_txt[i].flags[1], + band_txt[i].flags[2], + band_txt[i].dest_rptr, + band_txt[i].txt); + ***/ + // traceit("TEXT1=[%s]\n", band_txt[i].txt); + band_txt[i].txt_cnt = 0; + } + } else { + new_group[i] = false; + to_print[i] = 0; + ABC_grp[i] = false; + } + } else { + if (to_print[i] == 3) { + if (ABC_grp[i]) { + band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[0] ^ 0x70; + band_txt[i].txt_cnt ++; + + band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[1] ^ 0x4f; + band_txt[i].txt_cnt ++; + + band_txt[i].txt[band_txt[i].txt_cnt] = tmp_txt[2] ^ 0x93; + band_txt[i].txt_cnt ++; + + /* + We should NOT see any more text, + if we already processed text, + so blank out the codes. + */ + if (band_txt[i].txt_stats_sent) { + if (recvlen == 29) { + readBuffer[26] = 0x70; + readBuffer[27] = 0x4f; + readBuffer[28] = 0x93; + } else { + readBuffer[29] = 0x70; + readBuffer[30] = 0x4f; + readBuffer[31] = 0x93; + } + } + + if ((band_txt[i].txt_cnt >= 20) || C_seen[i]) { + band_txt[i].txt[band_txt[i].txt_cnt] = '\0'; + if (!band_txt[i].txt_stats_sent) { + /*** if YRCALL is CQCQCQ, set dest_rptr ***/ + if (memcmp(band_txt[i].lh_yrcall, "CQCQCQ", 6) == 0) { + set_dest_rptr(i, band_txt[i].dest_rptr); + if (memcmp(band_txt[i].dest_rptr, "REF", 3) == 0) + band_txt[i].dest_rptr[0] = '\0'; + } + + ii->sendHeardWithTXMsg(band_txt[i].lh_mycall, + band_txt[i].lh_sfx, + (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", + band_txt[i].lh_rpt1, + band_txt[i].lh_rpt2, + band_txt[i].flags[0], + band_txt[i].flags[1], + band_txt[i].flags[2], + band_txt[i].dest_rptr, + band_txt[i].txt); + // traceit("TEXT2=[%s], destination repeater=[%s]\n", band_txt[i].txt, band_txt[i].dest_rptr); + band_txt[i].txt_stats_sent = true; + } + band_txt[i].txt_cnt = 0; + } + if (C_seen[i]) + C_seen[i] = false; + } else { + /* something went wrong? all bets are off */ + if (band_txt[i].temp_line_cnt > 200) { + traceit("Reached the limit in the OLD gps mode\n"); + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + + /* do not copy CR, NL */ + if (((tmp_txt[0] ^ 0x70) != '\r') && ((tmp_txt[0] ^ 0x70) != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[0] ^ 0x70; + band_txt[i].temp_line_cnt++; + } + if (((tmp_txt[1] ^ 0x4f) != '\r') && ((tmp_txt[1] ^ 0x4f) != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[1] ^ 0x4f; + band_txt[i].temp_line_cnt++; + } + if (((tmp_txt[2] ^ 0x93) != '\r') && ((tmp_txt[2] ^ 0x93) != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[2] ^ 0x93; + band_txt[i].temp_line_cnt++; + } + + if ( + ((tmp_txt[0] ^ 0x70) == '\r') || + ((tmp_txt[1] ^ 0x4f) == '\r') || + ((tmp_txt[2] ^ 0x93) == '\r') + ) { + if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { + memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; + } else if (band_txt[i].temp_line[0] != '$') { + memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; + if (SEND_APRS && !band_txt[i].is_gps_sent) + gps_send(i); + } + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } else if (((tmp_txt[0] ^ 0x70) == '\n') || + ((tmp_txt[1] ^ 0x4f) == '\n') || + ((tmp_txt[2] ^ 0x93) == '\n')) { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + } + } else if (to_print[i] == 2) { + /* something went wrong? all bets are off */ + if (band_txt[i].temp_line_cnt > 200) { + traceit("Reached the limit in the OLD gps mode\n"); + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + + /* do not copy CR, NL */ + if (((tmp_txt[0] ^ 0x70) != '\r') && ((tmp_txt[0] ^ 0x70) != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[0] ^ 0x70; + band_txt[i].temp_line_cnt++; + } + if (((tmp_txt[1] ^ 0x4f) != '\r') && ((tmp_txt[1] ^ 0x4f) != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[1] ^ 0x4f; + band_txt[i].temp_line_cnt++; + } + + if (((tmp_txt[0] ^ 0x70) == '\r') || ((tmp_txt[1] ^ 0x4f) == '\r')) { + if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { + memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; + } else if (band_txt[i].temp_line[0] != '$') { + memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; + if (SEND_APRS && !band_txt[i].is_gps_sent) + gps_send(i); + } + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } else if (((tmp_txt[0] ^ 0x70) == '\n') || ((tmp_txt[1] ^ 0x4f) == '\n')) { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + } else if (to_print[i] == 1) { + /* something went wrong? all bets are off */ + if (band_txt[i].temp_line_cnt > 200) { + traceit("Reached the limit in the OLD gps mode\n"); + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + + /* do not copy CR, NL */ + if (((tmp_txt[0] ^ 0x70) != '\r') && ((tmp_txt[0] ^ 0x70) != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = tmp_txt[0] ^ 0x70; + band_txt[i].temp_line_cnt++; + } + + if ((tmp_txt[0] ^ 0x70) == '\r') { + if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { + memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; + } else if (band_txt[i].temp_line[0] != '$') { + memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; + if (SEND_APRS && !band_txt[i].is_gps_sent) + gps_send(i); + } + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } else if ((tmp_txt[0] ^ 0x70) == '\n') { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + } + new_group[i] = true; + to_print[i] = 0; + ABC_grp[i] = false; + } + break; + } + } + } + + /* send data to g2_link */ + sendto(srv_sock, (char *)readBuffer, recvlen,0, + (struct sockaddr *)&plug, + sizeof(struct sockaddr_in)); + + /* aprs processing */ + if (SEND_APRS) + aprs_process_text(readBuffer + 14, /* stream ID */ + readBuffer[16], /* seq */ + readBuffer + 17, /* audio + text */ + (recvlen == 29)?12:15); /* size */ + + for (i = 0; i < 3; i++) { + /* find out if data must go to the remote G2 */ + if (memcmp(to_remote_g2[i].streamid, readBuffer + 14, 2) == 0) { + memcpy(readBuffer2, "DSVT", 4); + readBuffer2[4] = 0x20; + readBuffer2[5] = 0x00; + readBuffer2[6] = 0x00; + readBuffer2[7] = 0x00; + readBuffer2[8] = readBuffer[10]; + readBuffer2[9] = readBuffer[11]; + readBuffer2[10] = readBuffer[12]; + readBuffer2[11] = readBuffer[13]; + memcpy(readBuffer2 + 12, readBuffer + 14, 3); + if (recvlen == 29) + memcpy(readBuffer2 + 15, readBuffer + 17, 12); + else + memcpy(readBuffer2 + 15, readBuffer + 20, 12); + + sendto(g2_sock, (char *)readBuffer2, 27, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + + time(&(to_remote_g2[i].last_time)); + + /* Is this the end-of-stream */ + if ((readBuffer[16] & 0x40) != 0) { + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].streamid[0] = '\0'; + to_remote_g2[i].streamid[1] = '\0'; + to_remote_g2[i].last_time = 0; + } + break; + } else + /* Is the data to be recorded for echotest */ + if ((recd[i].fd >= 0) && + (memcmp(recd[i].streamid, readBuffer + 14, 2) == 0)) { + time(&recd[i].last_time); + + memcpy(recbuf, "DSVT", 4); + recbuf[4] = 0x20; + recbuf[5] = 0x00; + recbuf[6] = 0x00; + recbuf[7] = 0x00; + recbuf[8] = readBuffer[10]; + recbuf[9] = readBuffer[11]; + recbuf[10] = readBuffer[12]; + recbuf[11] = readBuffer[13]; + memcpy(recbuf + 12, readBuffer + 14, 3); + if (recvlen == 29) + memcpy(recbuf + 15, readBuffer + 17, 12); + else + memcpy(recbuf + 15, readBuffer + 20, 12); + + rec_len = 27; + (void)write(recd[i].fd, &rec_len, 2); + (void)write(recd[i].fd, (char *)recbuf, rec_len); + + if ((readBuffer[16] & 0x40) != 0) { + recd[i].streamid[0] = 0x00; + recd[i].streamid[1] = 0x00; + recd[i].last_time = 0; + close(recd[i].fd); + recd[i].fd = -1; + // traceit("Closed echotest audio file:[%s]\n", recd[i].file); + + /* we are in echotest mode, so play it back */ + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&echo_thread, &attr, echotest, (void *)recd[i].file); + if (rc != 0) { + traceit("failed to start echotest thread\n"); + /* + When the echotest thread runs, it deletes the file, + Because the echotest thread did NOT start, we delete the file here + */ + unlink(recd[i].file); + } + pthread_attr_destroy(&attr); + } + break; + } else + /* Is the data to be recorded for voicemail */ + if ((vm[i].fd >= 0) && + (memcmp(vm[i].streamid, readBuffer + 14, 2) == 0)) { + time(&vm[i].last_time); + + memcpy(recbuf, "DSVT", 4); + recbuf[4] = 0x20; + recbuf[5] = 0x00; + recbuf[6] = 0x00; + recbuf[7] = 0x00; + recbuf[8] = readBuffer[10]; + recbuf[9] = readBuffer[11]; + recbuf[10] = readBuffer[12]; + recbuf[11] = readBuffer[13]; + memcpy(recbuf + 12, readBuffer + 14, 3); + if (recvlen == 29) + memcpy(recbuf + 15, readBuffer + 17, 12); + else + memcpy(recbuf + 15, readBuffer + 20, 12); + + rec_len = 27; + (void)write(vm[i].fd, &rec_len, 2); + (void)write(vm[i].fd, (char *)recbuf, rec_len); + + if ((readBuffer[16] & 0x40) != 0) { + vm[i].streamid[0] = 0x00; + vm[i].streamid[1] = 0x00; + vm[i].last_time = 0; + close(vm[i].fd); + vm[i].fd = -1; + // traceit("Closed voicemail audio file:[%s]\n", vm[i].file); + } + break; + } else + /* or maybe this is cross-banding data */ + if ((memcmp(toRptr[i].streamid, readBuffer + 14, 2) == 0) && + (toRptr[i].adr == fromRptr.sin_addr.s_addr)) { + sendto(srv_sock, (char *)readBuffer,29,0, + (struct sockaddr *)&toRptr[i].band_addr, + sizeof(struct sockaddr_in)); + + /* timeit */ + time(&toRptr[i].last_time); + + /* bump G2 counter */ + toRptr[i].G2_COUNTER ++; + + toRptr[i].sequence = readBuffer[16]; + + /* End of stream ? */ + if ((readBuffer[16] & 0x40) != 0) { + toRptr[i].last_time = 0; + toRptr[i].streamid[0] = '\0'; + toRptr[i].streamid[1] = '\0'; + toRptr[i].adr = 0; + } + break; + } + } + + if ((readBuffer[16] & 0x40) != 0) { + if (QSO_DETAILS) + traceit("END from rptr: cntr=%02x %02x, streamID=%d,%d, %d bytes\n", + readBuffer[4], readBuffer[5], + readBuffer[14],readBuffer[15],recvlen); + } + } + } + FD_CLR (srv_sock,&fdset); + } + } } static void compute_aprs_hash() { - short hash = 0x73e2; - short i = 0; - short len = 0; - char *p = NULL; - char rptr_sign[CALL_SIZE + 1]; - - strcpy(rptr_sign, OWNER); - p = strchr(rptr_sign, ' '); - if (!p) - { - traceit("Failed to build repeater callsign for aprs hash\n"); - return; - } - *p = '\0'; - p = rptr_sign; - len = strlen(rptr_sign); - - while (i < len) - { - hash ^= (*p++) << 8; - hash ^= (*p++); - i += 2; - } - traceit("aprs hash code=[%d] for %s\n", hash, OWNER); - RPTR_ID.aprs_hash = hash; - - return; + short hash = 0x73e2; + short i = 0; + short len = 0; + char *p = NULL; + char rptr_sign[CALL_SIZE + 1]; + + strcpy(rptr_sign, OWNER); + p = strchr(rptr_sign, ' '); + if (!p) { + traceit("Failed to build repeater callsign for aprs hash\n"); + return; + } + *p = '\0'; + p = rptr_sign; + len = strlen(rptr_sign); + + while (i < len) { + hash ^= (*p++) << 8; + hash ^= (*p++); + i += 2; + } + traceit("aprs hash code=[%d] for %s\n", hash, OWNER); + RPTR_ID.aprs_hash = hash; + + return; } static void aprs_open() { - struct timespec req; - bool ok = false; - - fd_set fdset; - struct timeval tv; - short int MAX_WAIT = 15; /* 15 seconds wait time MAX */ - int val = 1; - socklen_t val_len; - char snd_buf[512]; - char rcv_buf[512]; - int rc = 0; - - /* do some mimimal checking */ - if (RPTR_ID.aprs_host[0] == '\0') - { - traceit("Invalid value for APRS_HOST\n"); - return; - } - if (RPTR_ID.aprs_port == 0) - { - traceit("Invalid value for APRS_PORT\n"); - return; - } - if (RPTR_ID.aprs_interval == 0) - { - traceit("Invalid value for APRS_INTERVAL\n"); - return; - } - - ok = resolve_rmt(RPTR_ID.aprs_host, SOCK_STREAM, &aprs_addr); - if (!ok) - { - traceit("Can not resolve APRS_HOST %s\n", RPTR_ID.aprs_host); - return; - } - - /* fill it in */ - aprs_addr.sin_family = AF_INET; - aprs_addr.sin_port = htons(RPTR_ID.aprs_port); - - aprs_addr_len = sizeof(aprs_addr); - - aprs_sock = socket(PF_INET,SOCK_STREAM,0); - if (aprs_sock == -1) - { - traceit("Failed to create aprs socket,error=%d\n",errno); - return; - } - fcntl(aprs_sock,F_SETFL,O_NONBLOCK); - - val = 1; - if (setsockopt(aprs_sock,IPPROTO_TCP,TCP_NODELAY,(char *)&val, sizeof(val)) == -1) - { - traceit("setsockopt TCP_NODELAY TCP for aprs socket failed,error=%d\n",errno); - close(aprs_sock); - aprs_sock = -1; - return; - } - - traceit("Trying to connect to APRS...\n"); - rc = connect(aprs_sock, (struct sockaddr *)&aprs_addr, aprs_addr_len); - if (rc != 0) - { - if (errno == EINPROGRESS) - { - traceit("Waiting for up to %d seconds for APRS_HOST\n", MAX_WAIT); - while (MAX_WAIT > 0) - { - tv.tv_sec = 0; - tv.tv_usec = 0; - FD_ZERO(&fdset); - FD_SET(aprs_sock, &fdset); - rc = select(aprs_sock + 1, NULL, &fdset, NULL, &tv); - - if (rc < 0) - { - traceit("Failed to connect to APRS...select,error=%d\n", errno); - close(aprs_sock); - aprs_sock = -1; - return; - } - else - if (rc == 0) /* timeout */ - { - MAX_WAIT--; - sleep(1); - } - else - { - val = 1; /* Assume it fails */ - val_len = sizeof(val); - if (getsockopt(aprs_sock, SOL_SOCKET, SO_ERROR, (char *) &val, &val_len) < 0) - { - traceit("Failed to connect to APRS...getsockopt, error=%d\n", errno); - close(aprs_sock); - aprs_sock = -1; - return; - } - else - if (val == 0) - break; - - MAX_WAIT--; - sleep(1); - } - } - if (MAX_WAIT == 0) - { - traceit("Failed to connect to APRS...timeout\n"); - close(aprs_sock); - aprs_sock = -1; - return; - } - } - else - { - traceit("Failed to connect to APRS, error=%d\n", errno); - close(aprs_sock); - aprs_sock = -1; - return; - } - } - traceit("Connected to APRS %s:%d\n", RPTR_ID.aprs_host, RPTR_ID.aprs_port); - - /* login to aprs */ - sprintf(snd_buf, "user %s pass %d vers g2_ircddb 2.99 UDP 5 ", - OWNER, RPTR_ID.aprs_hash); - - /* add the user's filter */ - if (RPTR_ID.aprs_filter[0] != '\0') - { - strcat(snd_buf, "filter "); - strcat(snd_buf, RPTR_ID.aprs_filter); - } - // traceit("APRS login command:[%s]\n", snd_buf); - strcat(snd_buf, "\r\n"); - - while (true) - { - rc = writen(snd_buf, strlen(snd_buf)); - if (rc < 0) - { - if (errno == EWOULDBLOCK) - { - recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); - req.tv_sec = 0; - req.tv_nsec = 100000000; // 100 milli - nanosleep(&req, NULL); - } - else - { - traceit("APRS login command failed, error=%d\n", errno); - break; - } - } - else - { - // traceit("APRS login command sent\n"); - break; - } - } - recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); - - return; + struct timespec req; + bool ok = false; + + fd_set fdset; + struct timeval tv; + short int MAX_WAIT = 15; /* 15 seconds wait time MAX */ + int val = 1; + socklen_t val_len; + char snd_buf[512]; + char rcv_buf[512]; + int rc = 0; + + /* do some mimimal checking */ + if (RPTR_ID.aprs_host[0] == '\0') { + traceit("Invalid value for APRS_HOST\n"); + return; + } + if (RPTR_ID.aprs_port == 0) { + traceit("Invalid value for APRS_PORT\n"); + return; + } + if (RPTR_ID.aprs_interval == 0) { + traceit("Invalid value for APRS_INTERVAL\n"); + return; + } + + ok = resolve_rmt(RPTR_ID.aprs_host, SOCK_STREAM, &aprs_addr); + if (!ok) { + traceit("Can not resolve APRS_HOST %s\n", RPTR_ID.aprs_host); + return; + } + + /* fill it in */ + aprs_addr.sin_family = AF_INET; + aprs_addr.sin_port = htons(RPTR_ID.aprs_port); + + aprs_addr_len = sizeof(aprs_addr); + + aprs_sock = socket(PF_INET,SOCK_STREAM,0); + if (aprs_sock == -1) { + traceit("Failed to create aprs socket,error=%d\n",errno); + return; + } + fcntl(aprs_sock,F_SETFL,O_NONBLOCK); + + val = 1; + if (setsockopt(aprs_sock,IPPROTO_TCP,TCP_NODELAY,(char *)&val, sizeof(val)) == -1) { + traceit("setsockopt TCP_NODELAY TCP for aprs socket failed,error=%d\n",errno); + close(aprs_sock); + aprs_sock = -1; + return; + } + + traceit("Trying to connect to APRS...\n"); + rc = connect(aprs_sock, (struct sockaddr *)&aprs_addr, aprs_addr_len); + if (rc != 0) { + if (errno == EINPROGRESS) { + traceit("Waiting for up to %d seconds for APRS_HOST\n", MAX_WAIT); + while (MAX_WAIT > 0) { + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&fdset); + FD_SET(aprs_sock, &fdset); + rc = select(aprs_sock + 1, NULL, &fdset, NULL, &tv); + + if (rc < 0) { + traceit("Failed to connect to APRS...select,error=%d\n", errno); + close(aprs_sock); + aprs_sock = -1; + return; + } else if (rc == 0) { /* timeout */ + MAX_WAIT--; + sleep(1); + } else { + val = 1; /* Assume it fails */ + val_len = sizeof(val); + if (getsockopt(aprs_sock, SOL_SOCKET, SO_ERROR, (char *) &val, &val_len) < 0) { + traceit("Failed to connect to APRS...getsockopt, error=%d\n", errno); + close(aprs_sock); + aprs_sock = -1; + return; + } else if (val == 0) + break; + + MAX_WAIT--; + sleep(1); + } + } + if (MAX_WAIT == 0) { + traceit("Failed to connect to APRS...timeout\n"); + close(aprs_sock); + aprs_sock = -1; + return; + } + } else { + traceit("Failed to connect to APRS, error=%d\n", errno); + close(aprs_sock); + aprs_sock = -1; + return; + } + } + traceit("Connected to APRS %s:%d\n", RPTR_ID.aprs_host, RPTR_ID.aprs_port); + + /* login to aprs */ + sprintf(snd_buf, "user %s pass %d vers g2_ircddb 2.99 UDP 5 ", + OWNER, RPTR_ID.aprs_hash); + + /* add the user's filter */ + if (RPTR_ID.aprs_filter[0] != '\0') { + strcat(snd_buf, "filter "); + strcat(snd_buf, RPTR_ID.aprs_filter); + } + // traceit("APRS login command:[%s]\n", snd_buf); + strcat(snd_buf, "\r\n"); + + while (true) { + rc = writen(snd_buf, strlen(snd_buf)); + if (rc < 0) { + if (errno == EWOULDBLOCK) { + recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); + req.tv_sec = 0; + req.tv_nsec = 100000000; // 100 milli + nanosleep(&req, NULL); + } else { + traceit("APRS login command failed, error=%d\n", errno); + break; + } + } else { + // traceit("APRS login command sent\n"); + break; + } + } + recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); + + return; } void *send_aprs_beacon(void *arg) { - struct timespec req; - - int rc; - char snd_buf[512]; - char rcv_buf[512]; - float tmp_lat; - float tmp_lon; - float lat; - float lon; - char lat_s[15]; - char lon_s[15]; - time_t last_beacon_time = 0; - time_t last_keepalive_time = 0; - time_t tnow = 0; - short int i; - struct sigaction act; - - /* - Every 20 seconds, the remote APRS host sends a KEEPALIVE packet-comment - on the TCP/APRS port. - If we have not received any KEEPALIVE packet-comment after 5 minutes - we must assume that the remote APRS host is down or disappeared - or has dropped the connection. In these cases, we must re-connect. - There are 3 keepalive packets in one minute, or every 20 seconds. - In 5 minutes, we should have received a total of 15 keepalive packets. - */ - short THRESHOLD_COUNTDOWN = 15; - - arg = arg; - - act.sa_handler = sigCatch; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - traceit("beacon thread exiting...\n"); - pthread_exit(NULL); - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - traceit("beacon thread exiting...\n"); - pthread_exit(NULL); - } - if (sigaction(SIGPIPE, &act, 0) != 0) - { - traceit("sigaction-PIPE failed, error=%d\n", errno); - traceit("beacon thread exiting...\n"); - pthread_exit(NULL); - } - - time(&last_keepalive_time); - - /* This thread is also saying to the APRS_HOST that we are ALIVE */ - while (keep_running) - { - if (aprs_sock == -1) - { - aprs_open(); - if (aprs_sock == -1) - sleep(1); - else - THRESHOLD_COUNTDOWN = 15; - } - - time(&tnow); - if ((tnow - last_beacon_time) > (RPTR_ID.aprs_interval * 60)) - { - for (i = 0; i < 3; i++) - { - if (RPTR_ID.desc[i][0] != '\0') - { - tmp_lat = fabs(RPTR_ID.lat[i]); - tmp_lon = fabs(RPTR_ID.lon[i]); - lat = floor(tmp_lat); - lon = floor(tmp_lon); - lat = (tmp_lat - lat) * 60.0F + lat * 100.0F; - lon = (tmp_lon - lon) * 60.0F + lon * 100.0F; - - if (lat >= 1000.0F) - sprintf(lat_s, "%.2f", lat); - else - if (lat >= 100.0F) - sprintf(lat_s, "0%.2f", lat); - else - if (lat >= 10.0F) - sprintf(lat_s, "00%.2f", lat); - else - sprintf(lat_s, "000%.2f", lat); - - if (lon >= 10000.0F) - sprintf(lon_s, "%.2f", lon); - else - if (lon >= 1000.0F) - sprintf(lon_s, "0%.2f", lon); - else - if (lon >= 100.0F) - sprintf(lon_s, "00%.2f", lon); - else - if (lon >= 10.0F) - sprintf(lon_s, "000%.2f", lon); - else - sprintf(lon_s, "0000%.2f", lon); - - /* send to aprs */ - sprintf(snd_buf, "%s>APJI23,TCPIP*,qAC,%sS:!%s%cD%s%c&RNG%04u %s %s", - RPTR_ID.rptr[i], RPTR_ID.rptr[i], - lat_s, (RPTR_ID.lat[i] < 0.0F) ? 'S' : 'N', - lon_s, (RPTR_ID.lon[i] < 0.0F) ? 'W' : 'E', - RPTR_ID.range[i], RPTR_ID.band[i], RPTR_ID.desc[i]); - - // traceit("APRS Beacon =[%s]\n", snd_buf); - strcat(snd_buf, "\r\n"); - - while (keep_running) - { - if (aprs_sock == -1) - { - aprs_open(); - if (aprs_sock == -1) - sleep(1); - else - THRESHOLD_COUNTDOWN = 15; - } - else - { - rc = writen(snd_buf, strlen(snd_buf)); - if (rc < 0) - { - if ((errno == EPIPE) || - (errno == ECONNRESET) || - (errno == ETIMEDOUT) || - (errno == ECONNABORTED) || - (errno == ESHUTDOWN) || - (errno == EHOSTUNREACH) || - (errno == ENETRESET) || - (errno == ENETDOWN) || - (errno == ENETUNREACH) || - (errno == EHOSTDOWN) || - (errno == ENOTCONN)) - { - traceit("send_aprs_beacon: APRS_HOST closed connection,error=%d\n",errno); - close(aprs_sock); - aprs_sock = -1; - } - else - if (errno == EWOULDBLOCK) - { - req.tv_sec = 0; - req.tv_nsec = 100000000; // 100 milli - nanosleep(&req, NULL); - } - else - { - /* Cant do nothing about it */ - traceit("send_aprs_beacon failed, error=%d\n", errno); - break; - } - } - else - { - // traceit("APRS beacon sent\n"); - break; - } - } - rc = recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); - if (rc > 0) - THRESHOLD_COUNTDOWN = 15; - } - } - rc = recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); - if (rc > 0) - THRESHOLD_COUNTDOWN = 15; - } - time(&last_beacon_time); - } - /* - Are we still receiving from APRS host ? - */ - rc = recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); - if (rc < 0) - { - if ((errno == EPIPE) || - (errno == ECONNRESET) || - (errno == ETIMEDOUT) || - (errno == ECONNABORTED) || - (errno == ESHUTDOWN) || - (errno == EHOSTUNREACH) || - (errno == ENETRESET) || - (errno == ENETDOWN) || - (errno == ENETUNREACH) || - (errno == EHOSTDOWN) || - (errno == ENOTCONN)) - { - traceit("send_aprs_beacon: recv error: APRS_HOST closed connection,error=%d\n",errno); - close(aprs_sock); - aprs_sock = -1; - } - } - else - if (rc == 0) - { - traceit("send_aprs_beacon: recv: APRS shutdown\n"); - close(aprs_sock); - aprs_sock = -1; - } - else - THRESHOLD_COUNTDOWN = 15; - - req.tv_sec = 0; - req.tv_nsec = 100000000; // 100 milli - nanosleep(&req, NULL); - - /* 20 seconds passed already ? */ - time(&tnow); - if ((tnow - last_keepalive_time) > 20) - { - /* we should be receving keepalive packets ONLY if the connection is alive */ - if (aprs_sock >= 0) - { - if (THRESHOLD_COUNTDOWN > 0) - THRESHOLD_COUNTDOWN--; - - if (THRESHOLD_COUNTDOWN == 0) - { - traceit("APRS host keepalive timeout\n"); - close(aprs_sock); - aprs_sock = -1; - } - } - /* reset timer */ - time(&last_keepalive_time); - } - } - traceit("beacon thread exiting...\n"); - pthread_exit(NULL); + struct timespec req; + + int rc; + char snd_buf[512]; + char rcv_buf[512]; + float tmp_lat; + float tmp_lon; + float lat; + float lon; + char lat_s[15]; + char lon_s[15]; + time_t last_beacon_time = 0; + time_t last_keepalive_time = 0; + time_t tnow = 0; + short int i; + struct sigaction act; + + /* + Every 20 seconds, the remote APRS host sends a KEEPALIVE packet-comment + on the TCP/APRS port. + If we have not received any KEEPALIVE packet-comment after 5 minutes + we must assume that the remote APRS host is down or disappeared + or has dropped the connection. In these cases, we must re-connect. + There are 3 keepalive packets in one minute, or every 20 seconds. + In 5 minutes, we should have received a total of 15 keepalive packets. + */ + short THRESHOLD_COUNTDOWN = 15; + + arg = arg; + + act.sa_handler = sigCatch; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + traceit("beacon thread exiting...\n"); + pthread_exit(NULL); + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + traceit("beacon thread exiting...\n"); + pthread_exit(NULL); + } + if (sigaction(SIGPIPE, &act, 0) != 0) { + traceit("sigaction-PIPE failed, error=%d\n", errno); + traceit("beacon thread exiting...\n"); + pthread_exit(NULL); + } + + time(&last_keepalive_time); + + /* This thread is also saying to the APRS_HOST that we are ALIVE */ + while (keep_running) { + if (aprs_sock == -1) { + aprs_open(); + if (aprs_sock == -1) + sleep(1); + else + THRESHOLD_COUNTDOWN = 15; + } + + time(&tnow); + if ((tnow - last_beacon_time) > (RPTR_ID.aprs_interval * 60)) { + for (i = 0; i < 3; i++) { + if (RPTR_ID.desc[i][0] != '\0') { + tmp_lat = fabs(RPTR_ID.lat[i]); + tmp_lon = fabs(RPTR_ID.lon[i]); + lat = floor(tmp_lat); + lon = floor(tmp_lon); + lat = (tmp_lat - lat) * 60.0F + lat * 100.0F; + lon = (tmp_lon - lon) * 60.0F + lon * 100.0F; + + if (lat >= 1000.0F) + sprintf(lat_s, "%.2f", lat); + else if (lat >= 100.0F) + sprintf(lat_s, "0%.2f", lat); + else if (lat >= 10.0F) + sprintf(lat_s, "00%.2f", lat); + else + sprintf(lat_s, "000%.2f", lat); + + if (lon >= 10000.0F) + sprintf(lon_s, "%.2f", lon); + else if (lon >= 1000.0F) + sprintf(lon_s, "0%.2f", lon); + else if (lon >= 100.0F) + sprintf(lon_s, "00%.2f", lon); + else if (lon >= 10.0F) + sprintf(lon_s, "000%.2f", lon); + else + sprintf(lon_s, "0000%.2f", lon); + + /* send to aprs */ + sprintf(snd_buf, "%s>APJI23,TCPIP*,qAC,%sS:!%s%cD%s%c&RNG%04u %s %s", + RPTR_ID.rptr[i], RPTR_ID.rptr[i], + lat_s, (RPTR_ID.lat[i] < 0.0F) ? 'S' : 'N', + lon_s, (RPTR_ID.lon[i] < 0.0F) ? 'W' : 'E', + RPTR_ID.range[i], RPTR_ID.band[i], RPTR_ID.desc[i]); + + // traceit("APRS Beacon =[%s]\n", snd_buf); + strcat(snd_buf, "\r\n"); + + while (keep_running) { + if (aprs_sock == -1) { + aprs_open(); + if (aprs_sock == -1) + sleep(1); + else + THRESHOLD_COUNTDOWN = 15; + } else { + rc = writen(snd_buf, strlen(snd_buf)); + if (rc < 0) { + if ((errno == EPIPE) || + (errno == ECONNRESET) || + (errno == ETIMEDOUT) || + (errno == ECONNABORTED) || + (errno == ESHUTDOWN) || + (errno == EHOSTUNREACH) || + (errno == ENETRESET) || + (errno == ENETDOWN) || + (errno == ENETUNREACH) || + (errno == EHOSTDOWN) || + (errno == ENOTCONN)) { + traceit("send_aprs_beacon: APRS_HOST closed connection,error=%d\n",errno); + close(aprs_sock); + aprs_sock = -1; + } else if (errno == EWOULDBLOCK) { + req.tv_sec = 0; + req.tv_nsec = 100000000; // 100 milli + nanosleep(&req, NULL); + } else { + /* Cant do nothing about it */ + traceit("send_aprs_beacon failed, error=%d\n", errno); + break; + } + } else { + // traceit("APRS beacon sent\n"); + break; + } + } + rc = recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); + if (rc > 0) + THRESHOLD_COUNTDOWN = 15; + } + } + rc = recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); + if (rc > 0) + THRESHOLD_COUNTDOWN = 15; + } + time(&last_beacon_time); + } + /* + Are we still receiving from APRS host ? + */ + rc = recv(aprs_sock, rcv_buf, sizeof(rcv_buf), 0); + if (rc < 0) { + if ((errno == EPIPE) || + (errno == ECONNRESET) || + (errno == ETIMEDOUT) || + (errno == ECONNABORTED) || + (errno == ESHUTDOWN) || + (errno == EHOSTUNREACH) || + (errno == ENETRESET) || + (errno == ENETDOWN) || + (errno == ENETUNREACH) || + (errno == EHOSTDOWN) || + (errno == ENOTCONN)) { + traceit("send_aprs_beacon: recv error: APRS_HOST closed connection,error=%d\n",errno); + close(aprs_sock); + aprs_sock = -1; + } + } else if (rc == 0) { + traceit("send_aprs_beacon: recv: APRS shutdown\n"); + close(aprs_sock); + aprs_sock = -1; + } else + THRESHOLD_COUNTDOWN = 15; + + req.tv_sec = 0; + req.tv_nsec = 100000000; // 100 milli + nanosleep(&req, NULL); + + /* 20 seconds passed already ? */ + time(&tnow); + if ((tnow - last_keepalive_time) > 20) { + /* we should be receving keepalive packets ONLY if the connection is alive */ + if (aprs_sock >= 0) { + if (THRESHOLD_COUNTDOWN > 0) + THRESHOLD_COUNTDOWN--; + + if (THRESHOLD_COUNTDOWN == 0) { + traceit("APRS host keepalive timeout\n"); + close(aprs_sock); + aprs_sock = -1; + } + } + /* reset timer */ + time(&last_keepalive_time); + } + } + traceit("beacon thread exiting...\n"); + pthread_exit(NULL); } static void *echotest(void *arg) { - char *file = (char *)arg; - struct timespec req; - - FILE *fp = NULL; - unsigned short rlen = 0; - size_t nread = 0; - unsigned char dstar_buf[56]; - unsigned char rptr_buf[58]; - short int i = 0; - struct sigaction act; - - act.sa_handler = sigCatch; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - traceit("echotest thread exiting...\n"); - pthread_exit(NULL); - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - traceit("echotest thread exiting...\n"); - pthread_exit(NULL); - } - if (sigaction(SIGPIPE, &act, 0) != 0) - { - traceit("sigaction-PIPE failed, error=%d\n", errno); - traceit("echotest thread exiting...\n"); - pthread_exit(NULL); - } - - traceit("File to playback:[%s]\n", file); - - fp = fopen(file, "rb"); - if (!fp) - { - traceit("Failed to open file %s\n", file); - pthread_exit(NULL); - } - - nread = fread(dstar_buf, 10, 1, fp); - if (nread != 1) - { - traceit("Cant read first 10 bytes in %s\n", file); - fclose(fp); - pthread_exit(NULL); - } - - if (memcmp(dstar_buf, "DVTOOL", 6) != 0) - { - traceit("DVTOOL keyword not found in %s\n", file); - fclose(fp); - pthread_exit(NULL); - } - - sleep(PLAY_WAIT); - while (keep_running) - { - nread = fread(&rlen, 2, 1, fp); - if (nread != 1) - break; - - if ((rlen != 56) && (rlen != 27)) - { - traceit("Expected 56 bytes or 27 bytes, found %d\n", rlen); - break; - } - nread = fread(dstar_buf, rlen, 1, fp); - if (nread == 1) - { - if (memcmp(dstar_buf, "DSVT", 4) != 0) - { - traceit("DVST keyword not found in %s\n", file); - break; - } - - if (dstar_buf[8] != 0x20) - { - traceit("Not Voice type in %s\n", file); - break; - } - - if ((dstar_buf[4] != 0x10) && (dstar_buf[4] != 0x20)) - { - traceit("Not a valid record type in %s\n",file); - break; - } - - if (rlen == 56) - { - /* which module is this recording for? */ - if (dstar_buf[25] == 'A') - i = 0; - else - if (dstar_buf[25] == 'B') - i = 1; - else - if (dstar_buf[25] == 'C') - i = 2; - - - /*** - WARNING: G2_COUNTER is accessed by both threads. - It should be protected with a MUTEX, - but since this version is NOT for RP2C, but for home-brew - it does not really matter. - Anyway, accessing G2_COUNTER and adding 1 to it, - should be an atomic operation. - ***/ - - memcpy(rptr_buf, "DSTR", 4); - rptr_buf[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); - rptr_buf[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); - rptr_buf[6] = 0x73; - rptr_buf[7] = 0x12; - rptr_buf[8] = 0x00; - rptr_buf[9] = 0x30; - rptr_buf[10] = 0x20; - memcpy(rptr_buf + 11, dstar_buf + 9, 47); - - /* We did not change anything */ - // calcPFCS(rptr_buf, 58); - } - else - { - rptr_buf[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); - rptr_buf[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); - rptr_buf[9] = 0x13; - memcpy(rptr_buf + 11, dstar_buf + 9, 18); - } - - sendto(srv_sock, (char *)rptr_buf, rlen + 2, 0, - (struct sockaddr *)&toRptr[i].band_addr, - sizeof(struct sockaddr_in)); - - toRptr[i].G2_COUNTER ++; - - req.tv_sec = 0; - req.tv_nsec = PLAY_DELAY * 1000000; - nanosleep(&req, NULL); - } - } - fclose(fp); - if (!strstr(file, "voicemail.dat")) - unlink(file); - traceit("Finished playing\n"); - pthread_exit(NULL); + char *file = (char *)arg; + struct timespec req; + + FILE *fp = NULL; + unsigned short rlen = 0; + size_t nread = 0; + unsigned char dstar_buf[56]; + unsigned char rptr_buf[58]; + short int i = 0; + struct sigaction act; + + act.sa_handler = sigCatch; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + traceit("echotest thread exiting...\n"); + pthread_exit(NULL); + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + traceit("echotest thread exiting...\n"); + pthread_exit(NULL); + } + if (sigaction(SIGPIPE, &act, 0) != 0) { + traceit("sigaction-PIPE failed, error=%d\n", errno); + traceit("echotest thread exiting...\n"); + pthread_exit(NULL); + } + + traceit("File to playback:[%s]\n", file); + + fp = fopen(file, "rb"); + if (!fp) { + traceit("Failed to open file %s\n", file); + pthread_exit(NULL); + } + + nread = fread(dstar_buf, 10, 1, fp); + if (nread != 1) { + traceit("Cant read first 10 bytes in %s\n", file); + fclose(fp); + pthread_exit(NULL); + } + + if (memcmp(dstar_buf, "DVTOOL", 6) != 0) { + traceit("DVTOOL keyword not found in %s\n", file); + fclose(fp); + pthread_exit(NULL); + } + + sleep(PLAY_WAIT); + while (keep_running) { + nread = fread(&rlen, 2, 1, fp); + if (nread != 1) + break; + + if ((rlen != 56) && (rlen != 27)) { + traceit("Expected 56 bytes or 27 bytes, found %d\n", rlen); + break; + } + nread = fread(dstar_buf, rlen, 1, fp); + if (nread == 1) { + if (memcmp(dstar_buf, "DSVT", 4) != 0) { + traceit("DVST keyword not found in %s\n", file); + break; + } + + if (dstar_buf[8] != 0x20) { + traceit("Not Voice type in %s\n", file); + break; + } + + if ((dstar_buf[4] != 0x10) && (dstar_buf[4] != 0x20)) { + traceit("Not a valid record type in %s\n",file); + break; + } + + if (rlen == 56) { + /* which module is this recording for? */ + if (dstar_buf[25] == 'A') + i = 0; + else if (dstar_buf[25] == 'B') + i = 1; + else if (dstar_buf[25] == 'C') + i = 2; + + + /*** + WARNING: G2_COUNTER is accessed by both threads. + It should be protected with a MUTEX, + but since this version is NOT for RP2C, but for home-brew + it does not really matter. + Anyway, accessing G2_COUNTER and adding 1 to it, + should be an atomic operation. + ***/ + + memcpy(rptr_buf, "DSTR", 4); + rptr_buf[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); + rptr_buf[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); + rptr_buf[6] = 0x73; + rptr_buf[7] = 0x12; + rptr_buf[8] = 0x00; + rptr_buf[9] = 0x30; + rptr_buf[10] = 0x20; + memcpy(rptr_buf + 11, dstar_buf + 9, 47); + + /* We did not change anything */ + // calcPFCS(rptr_buf, 58); + } else { + rptr_buf[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); + rptr_buf[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); + rptr_buf[9] = 0x13; + memcpy(rptr_buf + 11, dstar_buf + 9, 18); + } + + sendto(srv_sock, (char *)rptr_buf, rlen + 2, 0, + (struct sockaddr *)&toRptr[i].band_addr, + sizeof(struct sockaddr_in)); + + toRptr[i].G2_COUNTER ++; + + req.tv_sec = 0; + req.tv_nsec = PLAY_DELAY * 1000000; + nanosleep(&req, NULL); + } + } + fclose(fp); + if (!strstr(file, "voicemail.dat")) + unlink(file); + traceit("Finished playing\n"); + pthread_exit(NULL); } static void qrgs_and_maps() { - const char *delim = ","; - - char *lat_s = NULL; - double lat = 0.00; - char *lon_s = NULL; - double lon = 0.00; - char *desc1 = NULL; - char *desc2 = NULL; - char *url = NULL; - - char *freq_s = NULL; - double freq = 0.00; - char *shift_s = NULL; - double shift = 0.00; - char *range_s = NULL; - double range = 0.00; - char *agl_s = NULL; - double agl = 0.00; - - char *saveptr = NULL; - - if (QTH[0] != '\0') - { - lat_s = strtok_r(QTH, delim, &saveptr); - lon_s = strtok_r(NULL, delim, &saveptr); - desc1 = strtok_r(NULL, delim, &saveptr); - desc2 = strtok_r(NULL, delim, &saveptr); - url = strtok_r(NULL, delim, &saveptr); - - if (lat_s) - lat = atof(lat_s); - if (lon_s) - lon = atof(lon_s); - - ii->rptrQTH(lat, lon, (desc1)?desc1:"", (desc2)?desc2:"", (url)?url:""); - } - - saveptr = NULL; - - if (QRG_A[0] != '\0') - { - freq_s = strtok_r(QRG_A, delim, &saveptr); - shift_s = strtok_r(NULL, delim, &saveptr); - range_s = strtok_r(NULL, delim, &saveptr); - agl_s = strtok_r(NULL, delim, &saveptr); - - if (freq_s) - freq = atof(freq_s); - if (shift_s) - shift = atof(shift_s); - if (range_s) - range = atof(range_s); - if (agl_s) - agl = atof(agl_s); - - ii->rptrQRG("A", freq, shift, range, agl); - } - - saveptr = NULL; - - if (QRG_B[0] != '\0') - { - freq_s = strtok_r(QRG_B, delim, &saveptr); - shift_s = strtok_r(NULL, delim, &saveptr); - range_s = strtok_r(NULL, delim, &saveptr); - agl_s = strtok_r(NULL, delim, &saveptr); - - if (freq_s) - freq = atof(freq_s); - if (shift_s) - shift = atof(shift_s); - if (range_s) - range = atof(range_s); - if (agl_s) - agl = atof(agl_s); - - ii->rptrQRG("B", freq, shift, range, agl); - } - - saveptr = NULL; - - if (QRG_C[0] != '\0') - { - freq_s = strtok_r(QRG_C, delim, &saveptr); - shift_s = strtok_r(NULL, delim, &saveptr); - range_s = strtok_r(NULL, delim, &saveptr); - agl_s = strtok_r(NULL, delim, &saveptr); - - if (freq_s) - freq = atof(freq_s); - if (shift_s) - shift = atof(shift_s); - if (range_s) - range = atof(range_s); - if (agl_s) - agl = atof(agl_s); - - ii->rptrQRG("C", freq, shift, range, agl); - } - - return; + const char *delim = ","; + + char *lat_s = NULL; + double lat = 0.00; + char *lon_s = NULL; + double lon = 0.00; + char *desc1 = NULL; + char *desc2 = NULL; + char *url = NULL; + + char *freq_s = NULL; + double freq = 0.00; + char *shift_s = NULL; + double shift = 0.00; + char *range_s = NULL; + double range = 0.00; + char *agl_s = NULL; + double agl = 0.00; + + char *saveptr = NULL; + + if (QTH[0] != '\0') { + lat_s = strtok_r(QTH, delim, &saveptr); + lon_s = strtok_r(NULL, delim, &saveptr); + desc1 = strtok_r(NULL, delim, &saveptr); + desc2 = strtok_r(NULL, delim, &saveptr); + url = strtok_r(NULL, delim, &saveptr); + + if (lat_s) + lat = atof(lat_s); + if (lon_s) + lon = atof(lon_s); + + ii->rptrQTH(lat, lon, (desc1)?desc1:"", (desc2)?desc2:"", (url)?url:""); + } + + saveptr = NULL; + + if (QRG_A[0] != '\0') { + freq_s = strtok_r(QRG_A, delim, &saveptr); + shift_s = strtok_r(NULL, delim, &saveptr); + range_s = strtok_r(NULL, delim, &saveptr); + agl_s = strtok_r(NULL, delim, &saveptr); + + if (freq_s) + freq = atof(freq_s); + if (shift_s) + shift = atof(shift_s); + if (range_s) + range = atof(range_s); + if (agl_s) + agl = atof(agl_s); + + ii->rptrQRG("A", freq, shift, range, agl); + } + + saveptr = NULL; + + if (QRG_B[0] != '\0') { + freq_s = strtok_r(QRG_B, delim, &saveptr); + shift_s = strtok_r(NULL, delim, &saveptr); + range_s = strtok_r(NULL, delim, &saveptr); + agl_s = strtok_r(NULL, delim, &saveptr); + + if (freq_s) + freq = atof(freq_s); + if (shift_s) + shift = atof(shift_s); + if (range_s) + range = atof(range_s); + if (agl_s) + agl = atof(agl_s); + + ii->rptrQRG("B", freq, shift, range, agl); + } + + saveptr = NULL; + + if (QRG_C[0] != '\0') { + freq_s = strtok_r(QRG_C, delim, &saveptr); + shift_s = strtok_r(NULL, delim, &saveptr); + range_s = strtok_r(NULL, delim, &saveptr); + agl_s = strtok_r(NULL, delim, &saveptr); + + if (freq_s) + freq = atof(freq_s); + if (shift_s) + shift = atof(shift_s); + if (range_s) + range = atof(range_s); + if (agl_s) + agl = atof(agl_s); + + ii->rptrQRG("C", freq, shift, range, agl); + } + + return; } int main(int argc, char **argv) { - short int i; - struct sigaction act; - bool ok; - char *p = NULL; - - int rc = 0; - - setvbuf(stdout, (char *)NULL, _IOLBF, 0); - - traceit("VERSION %s\n", VERSION); - if (argc != 2) - { - traceit("Example: g2_ircddb g2_ircddb.cfg\n"); - return 1; - } - - /* Used to validate MYCALL input */ - rc = regcomp(&preg, - "^(([1-9][A-Z])|([A-Z][0-9])|([A-Z][A-Z][0-9]))[0-9A-Z]*[A-Z][ ]*[ A-RT-Z]$", - REG_EXTENDED | REG_NOSUB); - if (rc != REG_NOERROR) - { - traceit("The IRC regular expression is NOT valid\n"); - return 1; - } - - act.sa_handler = sigCatch; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - return 1; - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - return 1; - } - if (sigaction(SIGPIPE, &act, 0) != 0) - { - traceit("sigaction-PIPE failed, error=%d\n", errno); - return 1; - } - - RPTR_ID.aprs_host[0] = '\0'; - RPTR_ID.aprs_port = 0; - RPTR_ID.aprs_hash = -1; - RPTR_ID.aprs_interval = 0; - RPTR_ID.aprs_filter[0] = '\0'; - for (i = 0; i < 3; i++) - { - RPTR_ID.lat[i] = 0.00; - RPTR_ID.lon[i] = 0.00; - RPTR_ID.range[i] = 0; - RPTR_ID.desc[i][0] = '\0'; - } - strcpy(RPTR_ID.band[0], "23cm"); - strcpy(RPTR_ID.band[1], "70cm"); - strcpy(RPTR_ID.band[2], "2m"); - - for (i = 0; i < 3; i++) - { - aprs_streamID[i].streamID[0] = 0x00; - aprs_streamID[i].streamID[1] = 0x00; - aprs_streamID[i].last_time = 0; - } - - for (i = 0; i < 3; i++) - { - band_txt[i].streamID[0] = 0x00; - band_txt[i].streamID[1] = 0x00; - band_txt[i].flags[0] = 0x00; - band_txt[i].flags[1] = 0x00; - band_txt[i].flags[2] = 0x00; - band_txt[i].lh_mycall[0] = '\0'; - band_txt[i].lh_sfx[0] = '\0'; - band_txt[i].lh_yrcall[0] = '\0'; - band_txt[i].lh_rpt1[0] = '\0'; - band_txt[i].lh_rpt2[0] = '\0'; - - band_txt[i].last_time = 0; - - band_txt[i].txt[0] = '\0'; - band_txt[i].txt_cnt = 0; - band_txt[i].txt_stats_sent = false; - - band_txt[i].dest_rptr[0] = '\0'; - - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - band_txt[i].gprmc[0] = '\0'; - band_txt[i].gpid[0] = '\0'; - band_txt[i].is_gps_sent = false; - band_txt[i].gps_last_time = 0; - - band_txt[i].num_dv_frames = 0; - band_txt[i].num_dv_silent_frames = 0; - band_txt[i].num_bit_errors = 0; - } - - /* process configuration file */ - rc = read_config(argv[1]); - if (rc != 0) - { - traceit("Failed to process config file %s\n", argv[1]); - return 1; - } - - /* build the repeater callsigns for aprs */ - strcpy(RPTR_ID.rptr[0], OWNER); - p = strchr(RPTR_ID.rptr[0], ' '); - if (!p) - { - traceit("Failed to build repeater callsigns for aprs\n"); - return 1; - } - *p = '\0'; - strcpy(RPTR_ID.rptr[1], RPTR_ID.rptr[0]); - strcpy(RPTR_ID.rptr[2], RPTR_ID.rptr[0]); - strcat(RPTR_ID.rptr[0], "-A"); - strcat(RPTR_ID.rptr[1], "-B"); - strcat(RPTR_ID.rptr[2], "-C"); - traceit("Repeater callsigns: [%s] [%s] [%s]\n", - RPTR_ID.rptr[0], RPTR_ID.rptr[1], RPTR_ID.rptr[2]); - - aprs_init(); - compute_aprs_hash(); - - ok = ::wxInitialize(); - if (!ok) - { - traceit("Failed to initialize wx\n"); - return 1; - } - - ii = new CIRCDDB(IRC_DDB_HOST, IRC_DDB_PORT, owner, IRC_PASS, VERSION, LOCAL_IRC_IP); - ok = ii->open(); - if (!ok) - { - traceit("irc open failed\n"); - ::wxUninitialize(); - return 1; - } - - rc = ii->getConnectionState(); - traceit("Waiting for irc connection status of 2\n"); - i = 0; - while (rc < 2) - { - traceit("irc status=%d\n", rc); - if (rc < 2) - { - i++; - sleep(5); - } - else - break; - - if (!keep_running) - break; - - if (i > 5) - { - traceit("We can not wait any longer...\n"); - break; - } - rc = ii->getConnectionState(); - } - - do - { - /* udp port 40000 must open first */ - rc = g2_open(); - if (rc != 0) - { - traceit("g2_open() failed\n"); - break; - } - - /* Open udp INTERNAL port */ - rc = srv_open(); - if (rc != 0) - { - traceit("srv_open() failed\n"); - break; - } - - /* recording for echotest on local repeater modules */ - for (i = 0; i < 3; i++) - { - recd[i].last_time = 0; - recd[i].streamid[0] = 0x00; - recd[i].streamid[1] = 0x00; - recd[i].fd = -1; - memset(recd[i].file, 0, sizeof(recd[i].file)); - } - - /* recording for voicemail on local repeater modules */ - for (i = 0; i < 3; i++) - { - vm[i].last_time = 0; - vm[i].streamid[0] = 0x00; - vm[i].streamid[1] = 0x00; - vm[i].fd = -1; - memset(vm[i].file, 0, sizeof(vm[i].file)); - - if (i == 0) - snprintf(vm[i].file, FILENAME_MAX, "%s/%c_%s", - ECHOTEST_DIR,'A',"voicemail.dat"); - else - if (i == 1) - snprintf(vm[i].file, FILENAME_MAX, "%s/%c_%s", - ECHOTEST_DIR,'B',"voicemail.dat"); - else - snprintf(vm[i].file, FILENAME_MAX, "%s/%c_%s", - ECHOTEST_DIR,'C',"voicemail.dat"); - - if (access(vm[i].file, F_OK) != 0) - memset(vm[i].file, 0, sizeof(vm[i].file)); - else - traceit("Loaded voicemail file: %s for mod %d\n", - vm[i].file, i); - } - - /* the repeater modules run on these ports */ - for (i = 0; i < 3; i++) - { - memset(&toRptr[i],0,sizeof(toRptr[i])); - - memset(toRptr[i].saved_hdr, 0, sizeof(toRptr[i].saved_hdr)); - toRptr[i].saved_adr = 0; - - toRptr[i].streamid[0] = '\0'; - toRptr[i].streamid[1] = '\0'; - toRptr[i].adr = 0; - - toRptr[i].band_addr.sin_family = AF_INET; - toRptr[i].band_addr.sin_addr.s_addr = inet_addr(TO_RPTR_IP[i]); - toRptr[i].band_addr.sin_port = htons(TO_RPTR_PORT[i]); - - toRptr[i].last_time = 0; - toRptr[i].G2_COUNTER = 0; - - toRptr[i].sequence = 0x00; - } - - /* - Initialize the end_of_audio that will be sent to the local repeater - when audio from remote G2 has timed out - */ - memcpy(end_of_audio, "DSTR", 4); - end_of_audio[6] = 0x73; - end_of_audio[7] = 0x12; - end_of_audio[8] = 0x00; - end_of_audio[9] = 0x13; - end_of_audio[10] = 0x20; - end_of_audio[11] = 0x00; - end_of_audio[12] = 0x01; - memset(end_of_audio + 17, '\0', 9); - end_of_audio[26] = 0x70; - end_of_audio[27] = 0x4f; - end_of_audio[28] = 0x93; - - /* to remote systems */ - for (i = 0; i < 3; i++) - { - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].streamid[0] = '\0'; - to_remote_g2[i].streamid[1] = '\0'; - to_remote_g2[i].last_time = 0; - } - - /* where to send packets to g2_link */ - memset(&plug,0,sizeof(struct sockaddr_in)); - plug.sin_family = AF_INET; - plug.sin_port = htons(TO_G2_LINK_PORT); - plug.sin_addr.s_addr = inet_addr(TO_G2_LINK_IP); - - traceit("g2_ircddb...entering processing loop\n"); - - if (SEND_QRGS_MAPS) - qrgs_and_maps(); - - runit(); - traceit("Leaving processing loop...\n"); - - } while (false); - - if (srv_sock != -1) - { - close(srv_sock); - traceit("Closed G2_INTERNAL_PORT\n"); - } - - if (g2_sock != -1) - { - close(g2_sock); - traceit("Closed G2_EXTERNAL_PORT\n"); - } - - if (aprs_sock != -1) - { - close(aprs_sock); - traceit("Closed APRS\n"); - } - - for (i = 0; i < 3; i++) - { - recd[i].last_time = 0; - recd[i].streamid[0] = 0x00; - recd[i].streamid[1] = 0x00; - if (recd[i].fd >= 0) - { - close(recd[i].fd); - unlink(recd[i].file); - } - } - - ii->close(); - ::wxUninitialize(); - traceit("g2_ircddb exiting\n"); - return rc; + short int i; + struct sigaction act; + bool ok; + char *p = NULL; + + int rc = 0; + + setvbuf(stdout, (char *)NULL, _IOLBF, 0); + + traceit("VERSION %s\n", VERSION); + if (argc != 2) { + traceit("Example: g2_ircddb g2_ircddb.cfg\n"); + return 1; + } + + /* Used to validate MYCALL input */ + rc = regcomp(&preg, + "^(([1-9][A-Z])|([A-Z][0-9])|([A-Z][A-Z][0-9]))[0-9A-Z]*[A-Z][ ]*[ A-RT-Z]$", + REG_EXTENDED | REG_NOSUB); + if (rc != REG_NOERROR) { + traceit("The IRC regular expression is NOT valid\n"); + return 1; + } + + act.sa_handler = sigCatch; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + return 1; + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + return 1; + } + if (sigaction(SIGPIPE, &act, 0) != 0) { + traceit("sigaction-PIPE failed, error=%d\n", errno); + return 1; + } + + RPTR_ID.aprs_host[0] = '\0'; + RPTR_ID.aprs_port = 0; + RPTR_ID.aprs_hash = -1; + RPTR_ID.aprs_interval = 0; + RPTR_ID.aprs_filter[0] = '\0'; + for (i = 0; i < 3; i++) { + RPTR_ID.lat[i] = 0.00; + RPTR_ID.lon[i] = 0.00; + RPTR_ID.range[i] = 0; + RPTR_ID.desc[i][0] = '\0'; + } + strcpy(RPTR_ID.band[0], "23cm"); + strcpy(RPTR_ID.band[1], "70cm"); + strcpy(RPTR_ID.band[2], "2m"); + + for (i = 0; i < 3; i++) { + aprs_streamID[i].streamID[0] = 0x00; + aprs_streamID[i].streamID[1] = 0x00; + aprs_streamID[i].last_time = 0; + } + + for (i = 0; i < 3; i++) { + band_txt[i].streamID[0] = 0x00; + band_txt[i].streamID[1] = 0x00; + band_txt[i].flags[0] = 0x00; + band_txt[i].flags[1] = 0x00; + band_txt[i].flags[2] = 0x00; + band_txt[i].lh_mycall[0] = '\0'; + band_txt[i].lh_sfx[0] = '\0'; + band_txt[i].lh_yrcall[0] = '\0'; + band_txt[i].lh_rpt1[0] = '\0'; + band_txt[i].lh_rpt2[0] = '\0'; + + band_txt[i].last_time = 0; + + band_txt[i].txt[0] = '\0'; + band_txt[i].txt_cnt = 0; + band_txt[i].txt_stats_sent = false; + + band_txt[i].dest_rptr[0] = '\0'; + + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + band_txt[i].gprmc[0] = '\0'; + band_txt[i].gpid[0] = '\0'; + band_txt[i].is_gps_sent = false; + band_txt[i].gps_last_time = 0; + + band_txt[i].num_dv_frames = 0; + band_txt[i].num_dv_silent_frames = 0; + band_txt[i].num_bit_errors = 0; + } + + /* process configuration file */ + rc = read_config(argv[1]); + if (rc != 0) { + traceit("Failed to process config file %s\n", argv[1]); + return 1; + } + + /* build the repeater callsigns for aprs */ + strcpy(RPTR_ID.rptr[0], OWNER); + p = strchr(RPTR_ID.rptr[0], ' '); + if (!p) { + traceit("Failed to build repeater callsigns for aprs\n"); + return 1; + } + *p = '\0'; + strcpy(RPTR_ID.rptr[1], RPTR_ID.rptr[0]); + strcpy(RPTR_ID.rptr[2], RPTR_ID.rptr[0]); + strcat(RPTR_ID.rptr[0], "-A"); + strcat(RPTR_ID.rptr[1], "-B"); + strcat(RPTR_ID.rptr[2], "-C"); + traceit("Repeater callsigns: [%s] [%s] [%s]\n", + RPTR_ID.rptr[0], RPTR_ID.rptr[1], RPTR_ID.rptr[2]); + + aprs_init(); + compute_aprs_hash(); + + ok = ::wxInitialize(); + if (!ok) { + traceit("Failed to initialize wx\n"); + return 1; + } + + ii = new CIRCDDB(IRC_DDB_HOST, IRC_DDB_PORT, owner, IRC_PASS, VERSION, LOCAL_IRC_IP); + ok = ii->open(); + if (!ok) { + traceit("irc open failed\n"); + ::wxUninitialize(); + return 1; + } + + rc = ii->getConnectionState(); + traceit("Waiting for irc connection status of 2\n"); + i = 0; + while (rc < 2) { + traceit("irc status=%d\n", rc); + if (rc < 2) { + i++; + sleep(5); + } else + break; + + if (!keep_running) + break; + + if (i > 5) { + traceit("We can not wait any longer...\n"); + break; + } + rc = ii->getConnectionState(); + } + + do { + /* udp port 40000 must open first */ + rc = g2_open(); + if (rc != 0) { + traceit("g2_open() failed\n"); + break; + } + + /* Open udp INTERNAL port */ + rc = srv_open(); + if (rc != 0) { + traceit("srv_open() failed\n"); + break; + } + + /* recording for echotest on local repeater modules */ + for (i = 0; i < 3; i++) { + recd[i].last_time = 0; + recd[i].streamid[0] = 0x00; + recd[i].streamid[1] = 0x00; + recd[i].fd = -1; + memset(recd[i].file, 0, sizeof(recd[i].file)); + } + + /* recording for voicemail on local repeater modules */ + for (i = 0; i < 3; i++) { + vm[i].last_time = 0; + vm[i].streamid[0] = 0x00; + vm[i].streamid[1] = 0x00; + vm[i].fd = -1; + memset(vm[i].file, 0, sizeof(vm[i].file)); + + if (i == 0) + snprintf(vm[i].file, FILENAME_MAX, "%s/%c_%s", + ECHOTEST_DIR,'A',"voicemail.dat"); + else if (i == 1) + snprintf(vm[i].file, FILENAME_MAX, "%s/%c_%s", + ECHOTEST_DIR,'B',"voicemail.dat"); + else + snprintf(vm[i].file, FILENAME_MAX, "%s/%c_%s", + ECHOTEST_DIR,'C',"voicemail.dat"); + + if (access(vm[i].file, F_OK) != 0) + memset(vm[i].file, 0, sizeof(vm[i].file)); + else + traceit("Loaded voicemail file: %s for mod %d\n", + vm[i].file, i); + } + + /* the repeater modules run on these ports */ + for (i = 0; i < 3; i++) { + memset(&toRptr[i],0,sizeof(toRptr[i])); + + memset(toRptr[i].saved_hdr, 0, sizeof(toRptr[i].saved_hdr)); + toRptr[i].saved_adr = 0; + + toRptr[i].streamid[0] = '\0'; + toRptr[i].streamid[1] = '\0'; + toRptr[i].adr = 0; + + toRptr[i].band_addr.sin_family = AF_INET; + toRptr[i].band_addr.sin_addr.s_addr = inet_addr(TO_RPTR_IP[i]); + toRptr[i].band_addr.sin_port = htons(TO_RPTR_PORT[i]); + + toRptr[i].last_time = 0; + toRptr[i].G2_COUNTER = 0; + + toRptr[i].sequence = 0x00; + } + + /* + Initialize the end_of_audio that will be sent to the local repeater + when audio from remote G2 has timed out + */ + memcpy(end_of_audio, "DSTR", 4); + end_of_audio[6] = 0x73; + end_of_audio[7] = 0x12; + end_of_audio[8] = 0x00; + end_of_audio[9] = 0x13; + end_of_audio[10] = 0x20; + end_of_audio[11] = 0x00; + end_of_audio[12] = 0x01; + memset(end_of_audio + 17, '\0', 9); + end_of_audio[26] = 0x70; + end_of_audio[27] = 0x4f; + end_of_audio[28] = 0x93; + + /* to remote systems */ + for (i = 0; i < 3; i++) { + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].streamid[0] = '\0'; + to_remote_g2[i].streamid[1] = '\0'; + to_remote_g2[i].last_time = 0; + } + + /* where to send packets to g2_link */ + memset(&plug,0,sizeof(struct sockaddr_in)); + plug.sin_family = AF_INET; + plug.sin_port = htons(TO_G2_LINK_PORT); + plug.sin_addr.s_addr = inet_addr(TO_G2_LINK_IP); + + traceit("g2_ircddb...entering processing loop\n"); + + if (SEND_QRGS_MAPS) + qrgs_and_maps(); + + runit(); + traceit("Leaving processing loop...\n"); + + } while (false); + + if (srv_sock != -1) { + close(srv_sock); + traceit("Closed G2_INTERNAL_PORT\n"); + } + + if (g2_sock != -1) { + close(g2_sock); + traceit("Closed G2_EXTERNAL_PORT\n"); + } + + if (aprs_sock != -1) { + close(aprs_sock); + traceit("Closed APRS\n"); + } + + for (i = 0; i < 3; i++) { + recd[i].last_time = 0; + recd[i].streamid[0] = 0x00; + recd[i].streamid[1] = 0x00; + if (recd[i].fd >= 0) { + close(recd[i].fd); + unlink(recd[i].file); + } + } + + ii->close(); + ::wxUninitialize(); + traceit("g2_ircddb exiting\n"); + return rc; } static void aprs_init() { - short int rptr_idx; - - /* Initialize the statistics on the APRS packets */ - for (rptr_idx = 0; rptr_idx < 3; rptr_idx++) - { - aprs_pack[rptr_idx].al = al_none; - aprs_pack[rptr_idx].data[0] = '\0'; - aprs_pack[rptr_idx].len = 0; - aprs_pack[rptr_idx].buf[0] = '\0'; - aprs_pack[rptr_idx].sl = sl_first; - aprs_pack[rptr_idx].is_sent = false; - } - - /* Initialize the APRS host */ - memset(&aprs_addr,0,sizeof(struct sockaddr_in)); - aprs_addr_len = sizeof(aprs_addr); - - return; + short int rptr_idx; + + /* Initialize the statistics on the APRS packets */ + for (rptr_idx = 0; rptr_idx < 3; rptr_idx++) { + aprs_pack[rptr_idx].al = al_none; + aprs_pack[rptr_idx].data[0] = '\0'; + aprs_pack[rptr_idx].len = 0; + aprs_pack[rptr_idx].buf[0] = '\0'; + aprs_pack[rptr_idx].sl = sl_first; + aprs_pack[rptr_idx].is_sent = false; + } + + /* Initialize the APRS host */ + memset(&aprs_addr,0,sizeof(struct sockaddr_in)); + aprs_addr_len = sizeof(aprs_addr); + + return; } // This is called when header comes in from repeater static void aprs_select_band(short int rptr_idx, unsigned char *streamID) { - if ((rptr_idx < 0) || (rptr_idx > 2)) - { - traceit("ERROR in aprs_select_band, invalid mod %d\n", rptr_idx); - return; - } - - /* lock on the streamID */ - aprs_streamID[rptr_idx].streamID[0] = streamID[0]; - aprs_streamID[rptr_idx].streamID[1] = streamID[1]; - // aprs_streamID[rptr_idx].last_time = 0; - - aprs_reset(rptr_idx); - return; + if ((rptr_idx < 0) || (rptr_idx > 2)) { + traceit("ERROR in aprs_select_band, invalid mod %d\n", rptr_idx); + return; + } + + /* lock on the streamID */ + aprs_streamID[rptr_idx].streamID[0] = streamID[0]; + aprs_streamID[rptr_idx].streamID[1] = streamID[1]; + // aprs_streamID[rptr_idx].last_time = 0; + + aprs_reset(rptr_idx); + return; } // This is called when data(text) comes in from repeater @@ -4452,673 +3853,582 @@ static void aprs_select_band(short int rptr_idx, unsigned char *streamID) // in the repeater data // Paramter seq is the byte at pos# 16(counting from zero) in the repeater data static void aprs_process_text(unsigned char *streamID, - unsigned char seq, - unsigned char *buf, + unsigned char seq, + unsigned char *buf, unsigned int len) { - bool done = false; - unsigned char aprs_data[200]; - unsigned int aprs_len; - char *p = NULL; - char *hdr = NULL; - char *aud = NULL; - char aprs_buf[1024]; - int rc; - time_t tnow = 0; - - short int i; - short int rptr_idx = -1; - - len = len; - - for (i = 0; i < 3; i++) - { - if (memcmp(streamID, aprs_streamID[i].streamID, 2) == 0) - { - rptr_idx = i; - break; - } - } - - if ((rptr_idx < 0) || (rptr_idx > 2)) - { - // traceit("ERROR in aprs_process_text: rptr_idx %d is invalid\n", rptr_idx); - return; - } - - if ((seq & 0x40) == 0x40) - return; - - if ((seq & 0x1f) == 0x00) - { - aprs_sync_it(rptr_idx); - return; - } - - done = aprs_write_data(rptr_idx, buf + 9); - if (!done) - return; - - aprs_len = aprs_get_data(rptr_idx, aprs_data, 200); - aprs_data[aprs_len] = '\0'; - - time(&tnow); - if ((tnow - aprs_streamID[rptr_idx].last_time) < 30) - return; - - if (aprs_sock == -1) - return; - - p = strchr((char*)aprs_data, ':'); - if (!p) - { - aprs_reset(rptr_idx); - return; - } - *p = '\0'; - - - hdr = (char *)aprs_data; - aud = p + 1; - if (strchr(hdr, 'q') != NULL) - return; - - p = strchr(aud, '\r'); - *p = '\0'; - - sprintf(aprs_buf, "%s,qAR,%s:%s\r\n", hdr, RPTR_ID.rptr[rptr_idx], aud); - // traceit("GPS-A=%s", aprs_buf); - rc = writen(aprs_buf, strlen(aprs_buf)); - if (rc == -1) - { - if ((errno == EPIPE) || - (errno == ECONNRESET) || - (errno == ETIMEDOUT) || - (errno == ECONNABORTED) || - (errno == ESHUTDOWN) || - (errno == EHOSTUNREACH) || - (errno == ENETRESET) || - (errno == ENETDOWN) || - (errno == ENETUNREACH) || - (errno == EHOSTDOWN) || - (errno == ENOTCONN)) - { - traceit("aprs_process_text: APRS_HOST closed connection,error=%d\n",errno); - close(aprs_sock); - aprs_sock = -1; - } - else /* if it is WOULDBLOCK, we will not go into a loop here */ - traceit("aprs_process_text: send error=%d\n", errno); - } - - time(&aprs_streamID[rptr_idx].last_time); - - return; + bool done = false; + unsigned char aprs_data[200]; + unsigned int aprs_len; + char *p = NULL; + char *hdr = NULL; + char *aud = NULL; + char aprs_buf[1024]; + int rc; + time_t tnow = 0; + + short int i; + short int rptr_idx = -1; + + len = len; + + for (i = 0; i < 3; i++) { + if (memcmp(streamID, aprs_streamID[i].streamID, 2) == 0) { + rptr_idx = i; + break; + } + } + + if ((rptr_idx < 0) || (rptr_idx > 2)) { + // traceit("ERROR in aprs_process_text: rptr_idx %d is invalid\n", rptr_idx); + return; + } + + if ((seq & 0x40) == 0x40) + return; + + if ((seq & 0x1f) == 0x00) { + aprs_sync_it(rptr_idx); + return; + } + + done = aprs_write_data(rptr_idx, buf + 9); + if (!done) + return; + + aprs_len = aprs_get_data(rptr_idx, aprs_data, 200); + aprs_data[aprs_len] = '\0'; + + time(&tnow); + if ((tnow - aprs_streamID[rptr_idx].last_time) < 30) + return; + + if (aprs_sock == -1) + return; + + p = strchr((char*)aprs_data, ':'); + if (!p) { + aprs_reset(rptr_idx); + return; + } + *p = '\0'; + + + hdr = (char *)aprs_data; + aud = p + 1; + if (strchr(hdr, 'q') != NULL) + return; + + p = strchr(aud, '\r'); + *p = '\0'; + + sprintf(aprs_buf, "%s,qAR,%s:%s\r\n", hdr, RPTR_ID.rptr[rptr_idx], aud); + // traceit("GPS-A=%s", aprs_buf); + rc = writen(aprs_buf, strlen(aprs_buf)); + if (rc == -1) { + if ((errno == EPIPE) || + (errno == ECONNRESET) || + (errno == ETIMEDOUT) || + (errno == ECONNABORTED) || + (errno == ESHUTDOWN) || + (errno == EHOSTUNREACH) || + (errno == ENETRESET) || + (errno == ENETDOWN) || + (errno == ENETUNREACH) || + (errno == EHOSTDOWN) || + (errno == ENOTCONN)) { + traceit("aprs_process_text: APRS_HOST closed connection,error=%d\n",errno); + close(aprs_sock); + aprs_sock = -1; + } else /* if it is WOULDBLOCK, we will not go into a loop here */ + traceit("aprs_process_text: send error=%d\n", errno); + } + + time(&aprs_streamID[rptr_idx].last_time); + + return; } static bool aprs_write_data(short int rptr_idx, unsigned char *data) { - if ((rptr_idx < 0) || (rptr_idx > 2)) - { - traceit("ERROR in aprs_write_data: rptr_idx %d is invalid\n", rptr_idx); - return false; - } - - if (aprs_pack[rptr_idx].is_sent) - return false; - - switch (aprs_pack[rptr_idx].sl) - { - case sl_first: - aprs_pack[rptr_idx].buf[0] = data[0] ^ 0x70; - aprs_pack[rptr_idx].buf[1] = data[1] ^ 0x4f; - aprs_pack[rptr_idx].buf[2] = data[2] ^ 0x93; - aprs_pack[rptr_idx].sl = sl_second; - return false; - - case sl_second: - aprs_pack[rptr_idx].buf[3] = data[0] ^ 0x70; - aprs_pack[rptr_idx].buf[4] = data[1] ^ 0x4f; - aprs_pack[rptr_idx].buf[5] = data[2] ^ 0x93; - aprs_pack[rptr_idx].sl = sl_first; - break; - } - - if ((aprs_pack[rptr_idx].buf[0] & 0xf0) != 0x30) - return false; - - return aprs_add_data(rptr_idx, aprs_pack[rptr_idx].buf + 1); + if ((rptr_idx < 0) || (rptr_idx > 2)) { + traceit("ERROR in aprs_write_data: rptr_idx %d is invalid\n", rptr_idx); + return false; + } + + if (aprs_pack[rptr_idx].is_sent) + return false; + + switch (aprs_pack[rptr_idx].sl) { + case sl_first: + aprs_pack[rptr_idx].buf[0] = data[0] ^ 0x70; + aprs_pack[rptr_idx].buf[1] = data[1] ^ 0x4f; + aprs_pack[rptr_idx].buf[2] = data[2] ^ 0x93; + aprs_pack[rptr_idx].sl = sl_second; + return false; + + case sl_second: + aprs_pack[rptr_idx].buf[3] = data[0] ^ 0x70; + aprs_pack[rptr_idx].buf[4] = data[1] ^ 0x4f; + aprs_pack[rptr_idx].buf[5] = data[2] ^ 0x93; + aprs_pack[rptr_idx].sl = sl_first; + break; + } + + if ((aprs_pack[rptr_idx].buf[0] & 0xf0) != 0x30) + return false; + + return aprs_add_data(rptr_idx, aprs_pack[rptr_idx].buf + 1); } static void aprs_reset(short int rptr_idx) { - if ((rptr_idx < 0) || (rptr_idx > 2)) - { - traceit("ERROR in aprs_reset: rptr_idx %d is invalid\n", rptr_idx); - return; - } - - aprs_pack[rptr_idx].al = al_none; - aprs_pack[rptr_idx].len = 0; - aprs_pack[rptr_idx].sl = sl_first; - aprs_pack[rptr_idx].is_sent = false; - - return; + if ((rptr_idx < 0) || (rptr_idx > 2)) { + traceit("ERROR in aprs_reset: rptr_idx %d is invalid\n", rptr_idx); + return; + } + + aprs_pack[rptr_idx].al = al_none; + aprs_pack[rptr_idx].len = 0; + aprs_pack[rptr_idx].sl = sl_first; + aprs_pack[rptr_idx].is_sent = false; + + return; } static void aprs_sync_it(short int rptr_idx) { - if ((rptr_idx < 0) || (rptr_idx > 2)) - { - traceit("ERROR in aprs_sync_it: rptr_idx %d is invalid\n", rptr_idx); - return; - } - - aprs_pack[rptr_idx].sl = sl_first; - return; + if ((rptr_idx < 0) || (rptr_idx > 2)) { + traceit("ERROR in aprs_sync_it: rptr_idx %d is invalid\n", rptr_idx); + return; + } + + aprs_pack[rptr_idx].sl = sl_first; + return; } static bool aprs_add_data(short int rptr_idx, unsigned char *data) { - unsigned int i; - unsigned char c; - bool ok; - - if ((rptr_idx < 0) || (rptr_idx > 2)) - { - traceit("ERROR in aprs_add_data: rptr_idx %d is invalid\n", rptr_idx); - return false; - } - - for (i = 0; i < 5; i++) - { - c = data[i]; - - if ((aprs_pack[rptr_idx].al == al_none) && (c == '$')) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_$1; - } - else - if ((aprs_pack[rptr_idx].al == al_$1) && (c == '$')) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_$2; - } - else - if ((aprs_pack[rptr_idx].al == al_$2) && (c == 'C')) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_c1; - } - else - if ((aprs_pack[rptr_idx].al == al_c1) && (c == 'R')) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_r1; - } - else - if ((aprs_pack[rptr_idx].al == al_r1) && (c == 'C')) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_c2; - } - else - if (aprs_pack[rptr_idx].al == al_c2) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_csum1; - } - else - if (aprs_pack[rptr_idx].al == al_csum1) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_csum2; - } - else - if (aprs_pack[rptr_idx].al == al_csum2) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_csum3; - } - else - if (aprs_pack[rptr_idx].al == al_csum3) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_csum4; - } - else - if ((aprs_pack[rptr_idx].al == al_csum4) && (c == ',')) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - aprs_pack[rptr_idx].al = al_data; - } - else - if ((aprs_pack[rptr_idx].al == al_data) && (c != '\r')) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - - if (aprs_pack[rptr_idx].len >= 300) - { - traceit("ERROR in aprs_add_data: Expected END of APRS data\n"); - aprs_pack[rptr_idx].len = 0; - aprs_pack[rptr_idx].al = al_none; - } - } - else - if ((aprs_pack[rptr_idx].al == al_data) && (c == '\r')) - { - aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; - aprs_pack[rptr_idx].len++; - - - ok = aprs_check_data(rptr_idx); - if (ok) - { - aprs_pack[rptr_idx].al = al_end; - return true; - } - else - { - traceit("BAD checksum in APRS data\n"); - aprs_pack[rptr_idx].al = al_none; - aprs_pack[rptr_idx].len = 0; - } - } - else - { - aprs_pack[rptr_idx].al = al_none; - aprs_pack[rptr_idx].len = 0; - } - } - return false; + unsigned int i; + unsigned char c; + bool ok; + + if ((rptr_idx < 0) || (rptr_idx > 2)) { + traceit("ERROR in aprs_add_data: rptr_idx %d is invalid\n", rptr_idx); + return false; + } + + for (i = 0; i < 5; i++) { + c = data[i]; + + if ((aprs_pack[rptr_idx].al == al_none) && (c == '$')) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_$1; + } else if ((aprs_pack[rptr_idx].al == al_$1) && (c == '$')) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_$2; + } else if ((aprs_pack[rptr_idx].al == al_$2) && (c == 'C')) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_c1; + } else if ((aprs_pack[rptr_idx].al == al_c1) && (c == 'R')) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_r1; + } else if ((aprs_pack[rptr_idx].al == al_r1) && (c == 'C')) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_c2; + } else if (aprs_pack[rptr_idx].al == al_c2) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_csum1; + } else if (aprs_pack[rptr_idx].al == al_csum1) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_csum2; + } else if (aprs_pack[rptr_idx].al == al_csum2) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_csum3; + } else if (aprs_pack[rptr_idx].al == al_csum3) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_csum4; + } else if ((aprs_pack[rptr_idx].al == al_csum4) && (c == ',')) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + aprs_pack[rptr_idx].al = al_data; + } else if ((aprs_pack[rptr_idx].al == al_data) && (c != '\r')) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + + if (aprs_pack[rptr_idx].len >= 300) { + traceit("ERROR in aprs_add_data: Expected END of APRS data\n"); + aprs_pack[rptr_idx].len = 0; + aprs_pack[rptr_idx].al = al_none; + } + } else if ((aprs_pack[rptr_idx].al == al_data) && (c == '\r')) { + aprs_pack[rptr_idx].data[aprs_pack[rptr_idx].len] = c; + aprs_pack[rptr_idx].len++; + + + ok = aprs_check_data(rptr_idx); + if (ok) { + aprs_pack[rptr_idx].al = al_end; + return true; + } else { + traceit("BAD checksum in APRS data\n"); + aprs_pack[rptr_idx].al = al_none; + aprs_pack[rptr_idx].len = 0; + } + } else { + aprs_pack[rptr_idx].al = al_none; + aprs_pack[rptr_idx].len = 0; + } + } + return false; } static unsigned int aprs_get_data(short int rptr_idx, unsigned char *data, unsigned int len) { - unsigned int l; + unsigned int l; - if ((rptr_idx < 0) || (rptr_idx > 2)) - { - traceit("ERROR in aprs_get_data: rptr_idx %d is invalid\n", rptr_idx); - return 0; - } + if ((rptr_idx < 0) || (rptr_idx > 2)) { + traceit("ERROR in aprs_get_data: rptr_idx %d is invalid\n", rptr_idx); + return 0; + } - l = aprs_pack[rptr_idx].len - 10; + l = aprs_pack[rptr_idx].len - 10; - if (l > len) - l = len; + if (l > len) + l = len; - memcpy(data, aprs_pack[rptr_idx].data + 10, l); + memcpy(data, aprs_pack[rptr_idx].data + 10, l); - aprs_pack[rptr_idx].al = al_none; - aprs_pack[rptr_idx].len = 0; - aprs_pack[rptr_idx].is_sent = true; + aprs_pack[rptr_idx].al = al_none; + aprs_pack[rptr_idx].len = 0; + aprs_pack[rptr_idx].is_sent = true; - return l; + return l; } static bool aprs_check_data(short int rptr_idx) { - unsigned int my_sum; - char buf[5]; + unsigned int my_sum; + char buf[5]; - if ((rptr_idx < 0) || (rptr_idx > 2)) - { - traceit("ERROR in aprs_check_data: rptr_idx %d is invalid\n", rptr_idx); - return false; - } - my_sum = aprs_calc_crc(aprs_pack[rptr_idx].data + 10, - aprs_pack[rptr_idx].len - 10); + if ((rptr_idx < 0) || (rptr_idx > 2)) { + traceit("ERROR in aprs_check_data: rptr_idx %d is invalid\n", rptr_idx); + return false; + } + my_sum = aprs_calc_crc(aprs_pack[rptr_idx].data + 10, + aprs_pack[rptr_idx].len - 10); - sprintf(buf, "%04X", my_sum); + sprintf(buf, "%04X", my_sum); - return (memcmp(buf, - aprs_pack[rptr_idx].data + 5, - 4) == 0); + return (memcmp(buf, + aprs_pack[rptr_idx].data + 5, + 4) == 0); } static unsigned int aprs_calc_crc(unsigned char* buf, unsigned int len) { - unsigned int my_crc = 0xffff; - unsigned int i,j; - unsigned char c; - bool xor_val; + unsigned int my_crc = 0xffff; + unsigned int i,j; + unsigned char c; + bool xor_val; - if (!buf) - return 0; + if (!buf) + return 0; - if (len <= 0) - return 0; + if (len <= 0) + return 0; - for (j = 0; j < len; j++) - { - c = buf[j]; + for (j = 0; j < len; j++) { + c = buf[j]; - for (i = 0; i < 8; i++) - { - xor_val = (((my_crc ^ c) & 0x01) == 0x01); - my_crc >>= 1; + for (i = 0; i < 8; i++) { + xor_val = (((my_crc ^ c) & 0x01) == 0x01); + my_crc >>= 1; - if (xor_val) - my_crc ^= 0x8408; + if (xor_val) + my_crc ^= 0x8408; - c >>= 1; - } - } - return (~my_crc & 0xffff); + c >>= 1; + } + } + return (~my_crc & 0xffff); } static void gps_send(short int rptr_idx) { - time_t tnow = 0; - char *p = NULL; - bool ok = false; - static char old_mycall[CALL_SIZE + 1] = { " " }; - - if ((rptr_idx < 0) || (rptr_idx > 2)) - { - traceit("ERROR in gps_send: rptr_idx %d is invalid\n", rptr_idx); - return; - } - - if (band_txt[rptr_idx].gprmc[0] == '\0') - { - band_txt[rptr_idx].gpid[0] = '\0'; - traceit("missing GPS ID\n"); - return; - } - if (band_txt[rptr_idx].gpid[0] == '\0') - { - band_txt[rptr_idx].gprmc[0] = '\0'; - traceit("Missing GPSRMC\n"); - return; - } - if (memcmp(band_txt[rptr_idx].gpid, band_txt[rptr_idx].lh_mycall, CALL_SIZE) != 0) - { - traceit("MYCALL [%s] does not match first 8 characters of GPS ID [%.8s]\n", - band_txt[rptr_idx].lh_mycall, band_txt[rptr_idx].gpid); - band_txt[rptr_idx].gprmc[0] = '\0'; - band_txt[rptr_idx].gpid[0] = '\0'; - return; - } - - /* if new station, reset last time */ - if (strcmp(old_mycall, band_txt[rptr_idx].lh_mycall) != 0) - { - strcpy(old_mycall, band_txt[rptr_idx].lh_mycall); - band_txt[rptr_idx].gps_last_time = 0; - } - - /* do NOT process often */ - time(&tnow); - if ((tnow - band_txt[rptr_idx].gps_last_time) < 31) - return; - - traceit("GPRMC=[%s]\n", band_txt[rptr_idx].gprmc); - traceit("GPS id=[%s]\n",band_txt[rptr_idx].gpid); - - p = strrchr(band_txt[rptr_idx].gprmc, '*'); - if (!p) - { - /* BAD news, something went wrong */ - traceit("Missing asterisk before checksum in GPRMC\n"); - band_txt[rptr_idx].gprmc[0] = '\0'; - band_txt[rptr_idx].gpid[0] = '\0'; - return; - } - else - { - *p = '\0'; - /* verify csum in GPRMC */ - ok = verify_gps_csum(band_txt[rptr_idx].gprmc + 1, p + 1); - if (!ok) - { - traceit("csum in GPRMC not good\n"); - band_txt[rptr_idx].gprmc[0] = '\0'; - band_txt[rptr_idx].gpid[0] = '\0'; - return; - } - } - - p = strrchr(band_txt[rptr_idx].gpid, '*'); - if (!p) - { - /* BAD news, something went wrong */ - traceit("Missing asterisk before checksum in GPS id\n"); - band_txt[rptr_idx].gprmc[0] = '\0'; - band_txt[rptr_idx].gpid[0] = '\0'; - return; - } - else - { - *p = '\0'; - /* verify csum in GPS id */ - ok = verify_gps_csum(band_txt[rptr_idx].gpid, p + 1); - if (!ok) - { - traceit("csum in GPS id not good\n"); - band_txt[rptr_idx].gprmc[0] = '\0'; - band_txt[rptr_idx].gpid[0] = '\0'; - return; - } - } - - /* now convert GPS into APRS and send it */ - build_aprs_from_gps_and_send(rptr_idx); - - band_txt[rptr_idx].is_gps_sent = true; - time(&(band_txt[rptr_idx].gps_last_time)); - return; + time_t tnow = 0; + char *p = NULL; + bool ok = false; + static char old_mycall[CALL_SIZE + 1] = { " " }; + + if ((rptr_idx < 0) || (rptr_idx > 2)) { + traceit("ERROR in gps_send: rptr_idx %d is invalid\n", rptr_idx); + return; + } + + if (band_txt[rptr_idx].gprmc[0] == '\0') { + band_txt[rptr_idx].gpid[0] = '\0'; + traceit("missing GPS ID\n"); + return; + } + if (band_txt[rptr_idx].gpid[0] == '\0') { + band_txt[rptr_idx].gprmc[0] = '\0'; + traceit("Missing GPSRMC\n"); + return; + } + if (memcmp(band_txt[rptr_idx].gpid, band_txt[rptr_idx].lh_mycall, CALL_SIZE) != 0) { + traceit("MYCALL [%s] does not match first 8 characters of GPS ID [%.8s]\n", + band_txt[rptr_idx].lh_mycall, band_txt[rptr_idx].gpid); + band_txt[rptr_idx].gprmc[0] = '\0'; + band_txt[rptr_idx].gpid[0] = '\0'; + return; + } + + /* if new station, reset last time */ + if (strcmp(old_mycall, band_txt[rptr_idx].lh_mycall) != 0) { + strcpy(old_mycall, band_txt[rptr_idx].lh_mycall); + band_txt[rptr_idx].gps_last_time = 0; + } + + /* do NOT process often */ + time(&tnow); + if ((tnow - band_txt[rptr_idx].gps_last_time) < 31) + return; + + traceit("GPRMC=[%s]\n", band_txt[rptr_idx].gprmc); + traceit("GPS id=[%s]\n",band_txt[rptr_idx].gpid); + + p = strrchr(band_txt[rptr_idx].gprmc, '*'); + if (!p) { + /* BAD news, something went wrong */ + traceit("Missing asterisk before checksum in GPRMC\n"); + band_txt[rptr_idx].gprmc[0] = '\0'; + band_txt[rptr_idx].gpid[0] = '\0'; + return; + } else { + *p = '\0'; + /* verify csum in GPRMC */ + ok = verify_gps_csum(band_txt[rptr_idx].gprmc + 1, p + 1); + if (!ok) { + traceit("csum in GPRMC not good\n"); + band_txt[rptr_idx].gprmc[0] = '\0'; + band_txt[rptr_idx].gpid[0] = '\0'; + return; + } + } + + p = strrchr(band_txt[rptr_idx].gpid, '*'); + if (!p) { + /* BAD news, something went wrong */ + traceit("Missing asterisk before checksum in GPS id\n"); + band_txt[rptr_idx].gprmc[0] = '\0'; + band_txt[rptr_idx].gpid[0] = '\0'; + return; + } else { + *p = '\0'; + /* verify csum in GPS id */ + ok = verify_gps_csum(band_txt[rptr_idx].gpid, p + 1); + if (!ok) { + traceit("csum in GPS id not good\n"); + band_txt[rptr_idx].gprmc[0] = '\0'; + band_txt[rptr_idx].gpid[0] = '\0'; + return; + } + } + + /* now convert GPS into APRS and send it */ + build_aprs_from_gps_and_send(rptr_idx); + + band_txt[rptr_idx].is_gps_sent = true; + time(&(band_txt[rptr_idx].gps_last_time)); + return; } static void build_aprs_from_gps_and_send(short int rptr_idx) { - char buf[512]; - char *p = NULL; - const char *delim = ","; - int rc = 0; - - char *saveptr = NULL; - - /* breakdown of GPRMC */ - char *GPRMC = NULL; - char *time_utc = NULL; - char *nav = NULL; - char *lat_str = NULL; - char *lat_NS = NULL; - char *lon_str = NULL; - char *lon_EW = NULL; - /*** dont care about the rest */ - - strcpy(buf, band_txt[rptr_idx].lh_mycall); - p = strchr(buf, ' '); - if (p) - { - if (band_txt[rptr_idx].lh_mycall[7] != ' ') - { - *p = '-'; - *(p + 1) = band_txt[rptr_idx].lh_mycall[7]; - *(p + 2) = '>'; - *(p + 3) = '\0'; - } - else - { - *p = '>'; - *(p + 1) = '\0'; - } - } - else - strcat(buf, ">"); - - strcat(buf, "APDPRS,DSTAR*,qAR,"); - strcat(buf, RPTR_ID.rptr[rptr_idx]); - strcat(buf, ":!"); - - GPRMC = strtok_r(band_txt[rptr_idx].gprmc, delim, &saveptr); - time_utc = strtok_r(NULL, delim, &saveptr); - nav = strtok_r(NULL, delim, &saveptr); - lat_str = strtok_r(NULL, delim, &saveptr); - lat_NS = strtok_r(NULL, delim, &saveptr); - lon_str = strtok_r(NULL, delim, &saveptr); - lon_EW = strtok_r(NULL, delim, &saveptr); - - if (lat_str && lat_NS) - { - if ((*lat_NS != 'N') && (*lat_NS != 'S')) - { - traceit("Invalid North or South indicator in latitude\n"); - return; - } - if (strlen(lat_str) != 9) - { - traceit("Invalid latitude\n"); - return; - } - if (lat_str[4] != '.') - { - traceit("Invalid latitude\n"); - return; - } - lat_str[7] = '\0'; - strcat(buf, lat_str); - strcat(buf, lat_NS); - } - else - { - traceit("Invalid latitude\n"); - return; - } - /* secondary table */ - strcat(buf, "\\"); - - if (lon_str && lon_EW) - { - if ((*lon_EW != 'E') && (*lon_EW != 'W')) - { - traceit("Invalid East or West indicator in longitude\n"); - return; - } - if (strlen(lon_str) != 10) - { - traceit("Invalid longitude\n"); - return; - } - if (lon_str[5] != '.') - { - traceit("Invalid longitude\n"); - return; - } - lon_str[8] = '\0'; - strcat(buf, lon_str); - strcat(buf, lon_EW); - } - else - { - traceit("Invalid longitude\n"); - return; - } - - /* Just this symbolcode only */ - strcat(buf, "k"); - strncat(buf, band_txt[rptr_idx].gpid + 13, 32); - - // traceit("Built APRS from old GPS mode=[%s]\n", buf); - strcat(buf, "\r\n"); - - rc = writen(buf, strlen(buf)); - if (rc == -1) - { - if ((errno == EPIPE) || - (errno == ECONNRESET) || - (errno == ETIMEDOUT) || - (errno == ECONNABORTED) || - (errno == ESHUTDOWN) || - (errno == EHOSTUNREACH) || - (errno == ENETRESET) || - (errno == ENETDOWN) || - (errno == ENETUNREACH) || - (errno == EHOSTDOWN) || - (errno == ENOTCONN)) - { - traceit("build_aprs_from_gps_and_send: APRS_HOST closed connection,error=%d\n",errno); - close(aprs_sock); - aprs_sock = -1; - } - else - traceit("build_aprs_from_gps_and_send: send error=%d\n", errno); - } - return; + char buf[512]; + char *p = NULL; + const char *delim = ","; + int rc = 0; + + char *saveptr = NULL; + + /* breakdown of GPRMC */ + //char *GPRMC = NULL; + //char *time_utc = NULL; + //char *nav = NULL; + char *lat_str = NULL; + char *lat_NS = NULL; + char *lon_str = NULL; + char *lon_EW = NULL; + /*** dont care about the rest */ + + strcpy(buf, band_txt[rptr_idx].lh_mycall); + p = strchr(buf, ' '); + if (p) { + if (band_txt[rptr_idx].lh_mycall[7] != ' ') { + *p = '-'; + *(p + 1) = band_txt[rptr_idx].lh_mycall[7]; + *(p + 2) = '>'; + *(p + 3) = '\0'; + } else { + *p = '>'; + *(p + 1) = '\0'; + } + } else + strcat(buf, ">"); + + strcat(buf, "APDPRS,DSTAR*,qAR,"); + strcat(buf, RPTR_ID.rptr[rptr_idx]); + strcat(buf, ":!"); + + //GPRMC = + strtok_r(band_txt[rptr_idx].gprmc, delim, &saveptr); + //time_utc = + strtok_r(NULL, delim, &saveptr); + //nav = + strtok_r(NULL, delim, &saveptr); + lat_str = strtok_r(NULL, delim, &saveptr); + lat_NS = strtok_r(NULL, delim, &saveptr); + lon_str = strtok_r(NULL, delim, &saveptr); + lon_EW = strtok_r(NULL, delim, &saveptr); + + if (lat_str && lat_NS) { + if ((*lat_NS != 'N') && (*lat_NS != 'S')) { + traceit("Invalid North or South indicator in latitude\n"); + return; + } + if (strlen(lat_str) != 9) { + traceit("Invalid latitude\n"); + return; + } + if (lat_str[4] != '.') { + traceit("Invalid latitude\n"); + return; + } + lat_str[7] = '\0'; + strcat(buf, lat_str); + strcat(buf, lat_NS); + } else { + traceit("Invalid latitude\n"); + return; + } + /* secondary table */ + strcat(buf, "\\"); + + if (lon_str && lon_EW) { + if ((*lon_EW != 'E') && (*lon_EW != 'W')) { + traceit("Invalid East or West indicator in longitude\n"); + return; + } + if (strlen(lon_str) != 10) { + traceit("Invalid longitude\n"); + return; + } + if (lon_str[5] != '.') { + traceit("Invalid longitude\n"); + return; + } + lon_str[8] = '\0'; + strcat(buf, lon_str); + strcat(buf, lon_EW); + } else { + traceit("Invalid longitude\n"); + return; + } + + /* Just this symbolcode only */ + strcat(buf, "k"); + strncat(buf, band_txt[rptr_idx].gpid + 13, 32); + + // traceit("Built APRS from old GPS mode=[%s]\n", buf); + strcat(buf, "\r\n"); + + rc = writen(buf, strlen(buf)); + if (rc == -1) { + if ((errno == EPIPE) || + (errno == ECONNRESET) || + (errno == ETIMEDOUT) || + (errno == ECONNABORTED) || + (errno == ESHUTDOWN) || + (errno == EHOSTUNREACH) || + (errno == ENETRESET) || + (errno == ENETDOWN) || + (errno == ENETUNREACH) || + (errno == EHOSTDOWN) || + (errno == ENOTCONN)) { + traceit("build_aprs_from_gps_and_send: APRS_HOST closed connection,error=%d\n",errno); + close(aprs_sock); + aprs_sock = -1; + } else + traceit("build_aprs_from_gps_and_send: send error=%d\n", errno); + } + return; } static bool verify_gps_csum(char *gps_text, char *csum_text) { - short int len; - short int i; - char c; - short computed_csum = 0; - char computed_csum_text[16]; - char *p = NULL; - - len = strlen(gps_text); - for (i = 0; i < len; i++) - { - c = gps_text[i]; - if (computed_csum == 0) - computed_csum = (char)c; - else - computed_csum = computed_csum ^ ((char)c); - } - sprintf(computed_csum_text, "%02X", computed_csum); - // traceit("computed_csum_text=[%s]\n", computed_csum_text); - - p = strchr(csum_text, ' '); - if (p) - *p = '\0'; - - if (strcmp(computed_csum_text, csum_text) == 0) - return true; - else - return false; + short int len; + short int i; + char c; + short computed_csum = 0; + char computed_csum_text[16]; + char *p = NULL; + + len = strlen(gps_text); + for (i = 0; i < len; i++) { + c = gps_text[i]; + if (computed_csum == 0) + computed_csum = (char)c; + else + computed_csum = computed_csum ^ ((char)c); + } + sprintf(computed_csum_text, "%02X", computed_csum); + // traceit("computed_csum_text=[%s]\n", computed_csum_text); + + p = strchr(csum_text, ' '); + if (p) + *p = '\0'; + + if (strcmp(computed_csum_text, csum_text) == 0) + return true; + else + return false; } static ssize_t writen(char *buffer, size_t n) { - ssize_t num_written = 0; - size_t tot_written = 0; - char *buf; - - buf = buffer; - for (tot_written = 0; tot_written < n;) - { - num_written = write(aprs_sock, buf, n - tot_written); - if (num_written <= 0) - { - if ((num_written == -1) && (errno == EINTR)) - continue; - else - return num_written; - } - tot_written += num_written; - buf += num_written; - } - return tot_written; + ssize_t num_written = 0; + size_t tot_written = 0; + char *buf; + + buf = buffer; + for (tot_written = 0; tot_written < n;) { + num_written = write(aprs_sock, buf, n - tot_written); + if (num_written <= 0) { + if ((num_written == -1) && (errno == EINTR)) + continue; + else + return num_written; + } + tot_written += num_written; + buf += num_written; + } + return tot_written; } diff --git a/g2_link.cpp b/g2_link.cpp index a035153..68ed22b 100644 --- a/g2_link.cpp +++ b/g2_link.cpp @@ -7,12 +7,12 @@ * 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, + * 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 + * 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 + * 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. */ @@ -94,27 +94,26 @@ static long RF_INACTIVITY_TIMER[3] = { 3, 3, 3 }; static unsigned char REF_ACK[3] = { 3, 96, 0 }; -/* +/* This is the data payload in the map: inbound_list This is for inbound dongles */ -struct inbound -{ - /* the callsign of the remote */ - char call[CALL_SIZE + 1]; +struct inbound { + /* the callsign of the remote */ + char call[CALL_SIZE + 1]; - /* IP and port of remote */ - struct sockaddr_in sin; + /* IP and port of remote */ + struct sockaddr_in sin; - /* if countdown expires, the connection is terminated */ - short countdown; + /* if countdown expires, the connection is terminated */ + short countdown; - /* This user talked on this module */ - char mod; /* A B C */ + /* This user talked on this module */ + char mod; /* A B C */ - /* dvap, dvdongle, ... */ - char client; + /* dvap, dvdongle, ... */ + char client; }; /* the Key in this inbound_list map is the unique IP address of the remote */ @@ -131,63 +130,60 @@ static link_unlink_user_type link_unlink_user; typedef map dt_lh_type; static dt_lh_type dt_lh_list; -/* +/* index 0 is from_mod=A, index 1 is from_mod=B, - index 2 is from_mod=C + index 2 is from_mod=C */ -static struct -{ - char to_call[CALL_SIZE + 1]; - struct sockaddr_in toDst4; - char from_mod; - char to_mod; - short countdown; - bool is_connected; - unsigned char in_streamid[2]; /* incoming from remote systems */ - unsigned char out_streamid[2]; /* outgoing to remote systems */ +static struct { + char to_call[CALL_SIZE + 1]; + struct sockaddr_in toDst4; + char from_mod; + char to_mod; + short countdown; + bool is_connected; + unsigned char in_streamid[2]; /* incoming from remote systems */ + unsigned char out_streamid[2]; /* outgoing to remote systems */ } to_remote_g2[3]; /* broadcast for data arriving from xrf to local rptr */ -static struct -{ - unsigned char xrf_streamid[2]; /* streamid from xrf */ - unsigned char rptr_streamid[2][2]; /* generated streamid to rptr(s) */ +static struct { + unsigned char xrf_streamid[2]; /* streamid from xrf */ + unsigned char rptr_streamid[2][2]; /* generated streamid to rptr(s) */ } brd_from_xrf; static unsigned char from_xrf_torptr_brd[56]; static short brd_from_xrf_idx = 0; /* broadcast for data arriving from local rptr to xrf */ -static struct -{ - unsigned char from_rptr_streamid[2]; - unsigned char to_rptr_streamid[2][2]; +static struct { + unsigned char from_rptr_streamid[2]; + unsigned char to_rptr_streamid[2][2]; } brd_from_rptr; static unsigned char fromrptr_torptr_brd[56]; static short brd_from_rptr_idx = 0; -/* +/* index 0 is local mod=A, index 1 is local mod=B, index 2 is local mod=C */ -static struct -{ - unsigned char streamid[2]; - time_t last_time; /* last time RF user talked */ +static struct { + unsigned char streamid[2]; + time_t last_time; /* last time RF user talked */ } tracing[3] = { { {0,0}, 0 }, - { {0,0}, 0 }, - { {0,0}, 0 } }; + { {0,0}, 0 }, + { {0,0}, 0 } +}; /* input from remote */ static int xrf_g2_sock = -1; static int ref_g2_sock = -1; static int dcs_g2_sock = -1; static unsigned char dcs_buf[1000]; -static unsigned char readBuffer2[1024]; +static unsigned char readBuffer2[1024]; static struct sockaddr_in fromDst4; -/* - After we receive it from remote g2, +/* + After we receive it from remote g2, we must feed it to our local repeater. */ static struct sockaddr_in toLocalg2; @@ -206,46 +202,45 @@ static bool keep_running = true; static regex_t preg; const char* G2_html = "" - "" - "" - "REPEATER G2_IRCDDB Gateway v3.09+" - "" - ""; - -static unsigned short crc_tabccitt[256] = -{ - 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, - 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, - 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, - 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, - 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, - 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, - 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, - 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, - 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, - 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, - 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, - 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, - 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, - 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, - 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, - 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, - 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, - 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, - 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, - 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, - 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, - 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, - 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, - 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, - 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, - 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, - 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, - 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, - 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, - 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, - 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, - 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 + "" + "" + "REPEATER G2_IRCDDB Gateway v3.09+" + "" + ""; + +static unsigned short crc_tabccitt[256] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 }; /* the map of remotes */ @@ -265,12 +260,12 @@ static char *p_tmp2 = NULL; /* END: TEXT crap */ /* this is used for the "dashboard and QSO_DETAILS" to avoid processing multiple headers */ -static struct -{ - unsigned char sid[2]; +static struct { + unsigned char sid[2]; } old_sid[3] = { { {0x00, 0x00} }, - { {0x00, 0x00} }, - { {0x00, 0x00} } }; + { {0x00, 0x00} }, + { {0x00, 0x00} } +}; static bool load_gwys(char *filename); static void calcPFCS(unsigned char *packet, int len); @@ -293,4850 +288,4255 @@ static void *rptr_ack_run(void *arg); static bool resolve_rmt(char *name, int type, struct sockaddr_in *addr) { - struct addrinfo hints; - struct addrinfo *res; - struct addrinfo *rp; - int rc = 0; - bool found = false; - - memset(&hints, 0x00, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; - hints.ai_socktype = type; - - rc = getaddrinfo(name, NULL, &hints, &res); - if (rc != 0) - { - traceit("getaddrinfo return error code %d for [%s]\n", rc, name); - return false; - } - - for (rp = res; rp != NULL; rp = rp->ai_next) - { - if ((rp->ai_family == AF_INET) && - (rp->ai_socktype == type)) - { - memcpy(addr, rp->ai_addr, sizeof(struct sockaddr_in)); - found = true; - break; - } - } - freeaddrinfo(res); - return found; + struct addrinfo hints; + struct addrinfo *res; + struct addrinfo *rp; + int rc = 0; + bool found = false; + + memset(&hints, 0x00, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = type; + + rc = getaddrinfo(name, NULL, &hints, &res); + if (rc != 0) { + traceit("getaddrinfo return error code %d for [%s]\n", rc, name); + return false; + } + + for (rp = res; rp != NULL; rp = rp->ai_next) { + if ((rp->ai_family == AF_INET) && + (rp->ai_socktype == type)) { + memcpy(addr, rp->ai_addr, sizeof(struct sockaddr_in)); + found = true; + break; + } + } + freeaddrinfo(res); + return found; } /* send keepalive to donglers */ static void send_heartbeat() { - inbound_type::iterator pos; - inbound *inbound_ptr; - bool removed = false; - - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - sendto(ref_g2_sock,(char *)REF_ACK,3,0, - (struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - - if (inbound_ptr->countdown >= 0) - inbound_ptr->countdown --; - - if (inbound_ptr->countdown < 0) - { - removed = true; - traceit("call=%s timeout, removing %s, users=%d\n", - inbound_ptr->call, - pos->first.c_str(), - inbound_list.size() - 1); - - free(pos->second); - pos->second = NULL; - inbound_list.erase(pos); - } - } - if (removed) - print_status_file(); + inbound_type::iterator pos; + inbound *inbound_ptr; + bool removed = false; + + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + sendto(ref_g2_sock,(char *)REF_ACK,3,0, + (struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + + if (inbound_ptr->countdown >= 0) + inbound_ptr->countdown --; + + if (inbound_ptr->countdown < 0) { + removed = true; + traceit("call=%s timeout, removing %s, users=%d\n", + inbound_ptr->call, + pos->first.c_str(), + inbound_list.size() - 1); + + free(pos->second); + pos->second = NULL; + inbound_list.erase(pos); + } + } + if (removed) + print_status_file(); } static void rptr_ack(short i) { - pthread_t rptr_ack_thread; - pthread_attr_t attr; - int rc = 0; - static char mod_and_RADIO_ID[3][22]; - - struct tm tmp; - time_t t; - char outstr[200]; - - memset(mod_and_RADIO_ID[i], ' ', 21); - mod_and_RADIO_ID[i][21] = '\0'; - - if (i == 0) - mod_and_RADIO_ID[i][0] = 'A'; - else - if (i == 1) - mod_and_RADIO_ID[i][0] = 'B'; - else - if (i == 2) - mod_and_RADIO_ID[i][0] = 'C'; - - if (to_remote_g2[i].is_connected) - { - memcpy(mod_and_RADIO_ID[i] + 1, "LINKED TO ", 10); - memcpy(mod_and_RADIO_ID[i] + 11, to_remote_g2[i].to_call, CALL_SIZE); - mod_and_RADIO_ID[i][11 + CALL_SIZE] = to_remote_g2[i].to_mod; - } - else - if (to_remote_g2[i].to_call[0] != '\0') - { - memcpy(mod_and_RADIO_ID[i] + 1, "TRYING ", 10); - memcpy(mod_and_RADIO_ID[i] + 11, to_remote_g2[i].to_call, CALL_SIZE); - mod_and_RADIO_ID[i][11 + CALL_SIZE] = to_remote_g2[i].to_mod; - } - else - { - time(&t); - if (!localtime_r(&t,&tmp)) - memcpy(mod_and_RADIO_ID[i] + 1, "NOT LINKED", 10); - else - { - if (strftime(outstr, sizeof(outstr), "%Y%m%d %H:%M " ,&tmp) == 0) - memcpy(mod_and_RADIO_ID[i] + 1, "NOT LINKED", 10); - else - memcpy(mod_and_RADIO_ID[i] + 1, outstr, 15); - } - } - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&rptr_ack_thread, &attr, rptr_ack_run, (void *)(mod_and_RADIO_ID[i])); - if (rc != 0) - traceit("failed to start rptr_ack thread for mod %c\n", mod_and_RADIO_ID[i][0]); - pthread_attr_destroy(&attr); - return; + pthread_t rptr_ack_thread; + pthread_attr_t attr; + int rc = 0; + static char mod_and_RADIO_ID[3][22]; + + struct tm tmp; + time_t t; + char outstr[200]; + + memset(mod_and_RADIO_ID[i], ' ', 21); + mod_and_RADIO_ID[i][21] = '\0'; + + if (i == 0) + mod_and_RADIO_ID[i][0] = 'A'; + else if (i == 1) + mod_and_RADIO_ID[i][0] = 'B'; + else if (i == 2) + mod_and_RADIO_ID[i][0] = 'C'; + + if (to_remote_g2[i].is_connected) { + memcpy(mod_and_RADIO_ID[i] + 1, "LINKED TO ", 10); + memcpy(mod_and_RADIO_ID[i] + 11, to_remote_g2[i].to_call, CALL_SIZE); + mod_and_RADIO_ID[i][11 + CALL_SIZE] = to_remote_g2[i].to_mod; + } else if (to_remote_g2[i].to_call[0] != '\0') { + memcpy(mod_and_RADIO_ID[i] + 1, "TRYING ", 10); + memcpy(mod_and_RADIO_ID[i] + 11, to_remote_g2[i].to_call, CALL_SIZE); + mod_and_RADIO_ID[i][11 + CALL_SIZE] = to_remote_g2[i].to_mod; + } else { + time(&t); + if (!localtime_r(&t,&tmp)) + memcpy(mod_and_RADIO_ID[i] + 1, "NOT LINKED", 10); + else { + if (strftime(outstr, sizeof(outstr), "%Y%m%d %H:%M " ,&tmp) == 0) + memcpy(mod_and_RADIO_ID[i] + 1, "NOT LINKED", 10); + else + memcpy(mod_and_RADIO_ID[i] + 1, outstr, 15); + } + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&rptr_ack_thread, &attr, rptr_ack_run, (void *)(mod_and_RADIO_ID[i])); + if (rc != 0) + traceit("failed to start rptr_ack thread for mod %c\n", mod_and_RADIO_ID[i][0]); + pthread_attr_destroy(&attr); + return; } static void *rptr_ack_run(void *arg) { - char from_mod = *((char *)arg); - char RADIO_ID[21]; - memcpy(RADIO_ID, (char *)arg + 1, 21); - unsigned char rptr_ack[56]; - struct timespec nanos; - unsigned int aseed; - time_t tnow = 0; - char silence[12] = - { - 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8, - 0x70,0x4f,0x93 - }; - struct sigaction act; - - act.sa_handler = sigCatch; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - traceit("rptr_ack thread exiting...\n"); - pthread_exit(NULL); - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - traceit("rptr_ack thread exiting...\n"); - pthread_exit(NULL); - } - - time(&tnow); - aseed = tnow + pthread_self(); - - u_int16_t streamid_raw = (::rand_r(&aseed) % 65535U) + 1U; - - sleep(DELAY_BEFORE); - - traceit("sending ACK+text, mod:[%c], RADIO_ID=[%s]\n", from_mod, RADIO_ID); - - memcpy(rptr_ack,"DSVT", 4); - rptr_ack[4] = 0x10; - rptr_ack[5] = 0x00; - rptr_ack[6] = 0x00; - rptr_ack[7] = 0x00; - - rptr_ack[8] = 0x20; - rptr_ack[9] = 0x00; - rptr_ack[10] = 0x01; - rptr_ack[11] = 0x00; - - rptr_ack[12] = streamid_raw / 256U; - rptr_ack[13] = streamid_raw % 256U; - rptr_ack[14] = 0x80; - rptr_ack[15] = 0x01; /* we do not want to set this to 0x01 */ - rptr_ack[16] = 0x00; - rptr_ack[17] = 0x00; - - memcpy(rptr_ack + 18, OWNER, 8); - rptr_ack[25] = from_mod; - - memcpy(rptr_ack + 26, OWNER, 8); - rptr_ack[33] = 'G'; - - memcpy(rptr_ack + 34, "CQCQCQ ", 8); - - memcpy(rptr_ack + 42, OWNER, 8); - rptr_ack[49] = from_mod; - - memcpy(rptr_ack + 50, "RPTR", 4); - calcPFCS(rptr_ack,56); - (void)sendto(rptr_sock,(char *)rptr_ack,56,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[4] = 0x20; - memcpy((char *)rptr_ack + 15, silence, 9); - - /* start sending silence + announcement text */ - - rptr_ack[14] = 0x00; - rptr_ack[24] = 0x55; - rptr_ack[25] = 0x2d; - rptr_ack[26] = 0x16; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[14] = 0x01; - rptr_ack[24] = '@' ^ 0x70; - rptr_ack[25] = RADIO_ID[0] ^ 0x4f; - rptr_ack[26] = RADIO_ID[1] ^ 0x93; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[14] = 0x02; - rptr_ack[24] = RADIO_ID[2] ^ 0x70; - rptr_ack[25] = RADIO_ID[3] ^ 0x4f; - rptr_ack[26] = RADIO_ID[4] ^ 0x93; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[14] = 0x03; - rptr_ack[24] = 'A' ^ 0x70; - rptr_ack[25] = RADIO_ID[5] ^ 0x4f; - rptr_ack[26] = RADIO_ID[6] ^ 0x93; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[14] = 0x04; - rptr_ack[24] = RADIO_ID[7] ^ 0x70; - rptr_ack[25] = RADIO_ID[8] ^ 0x4f; - rptr_ack[26] = RADIO_ID[9] ^ 0x93; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[14] = 0x05; - rptr_ack[24] = 'B' ^ 0x70; - rptr_ack[25] = RADIO_ID[10] ^ 0x4f; - rptr_ack[26] = RADIO_ID[11] ^ 0x93; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[14] = 0x06; - rptr_ack[24] = RADIO_ID[12] ^ 0x70; - rptr_ack[25] = RADIO_ID[13] ^ 0x4f; - rptr_ack[26] = RADIO_ID[14] ^ 0x93; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[14] = 0x07; - rptr_ack[24] = 'C' ^ 0x70; - rptr_ack[25] = RADIO_ID[15] ^ 0x4f; - rptr_ack[26] = RADIO_ID[16] ^ 0x93; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[14] = 0x08; - rptr_ack[24] = RADIO_ID[17] ^ 0x70; - rptr_ack[25] = RADIO_ID[18] ^ 0x4f; - rptr_ack[26] = RADIO_ID[19] ^ 0x93; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - - rptr_ack[14] = 0x09 | 0x40; - memset((char *)rptr_ack + 15, 0, 9); - rptr_ack[24] = 0x70; - rptr_ack[25] = 0x4f; - rptr_ack[26] = 0x93; - (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); - traceit("finished sending ACK+text to mod:[%c]\n", from_mod); - pthread_exit(NULL); + char from_mod = *((char *)arg); + char RADIO_ID[21]; + memcpy(RADIO_ID, (char *)arg + 1, 21); + unsigned char rptr_ack[56]; + struct timespec nanos; + unsigned int aseed; + time_t tnow = 0; + unsigned char silence[12] = { 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8,0x70,0x4f,0x93 }; + struct sigaction act; + + act.sa_handler = sigCatch; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + traceit("rptr_ack thread exiting...\n"); + pthread_exit(NULL); + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + traceit("rptr_ack thread exiting...\n"); + pthread_exit(NULL); + } + + time(&tnow); + aseed = tnow + pthread_self(); + + u_int16_t streamid_raw = (::rand_r(&aseed) % 65535U) + 1U; + + sleep(DELAY_BEFORE); + + traceit("sending ACK+text, mod:[%c], RADIO_ID=[%s]\n", from_mod, RADIO_ID); + + memcpy(rptr_ack,"DSVT", 4); + rptr_ack[4] = 0x10; + rptr_ack[5] = 0x00; + rptr_ack[6] = 0x00; + rptr_ack[7] = 0x00; + + rptr_ack[8] = 0x20; + rptr_ack[9] = 0x00; + rptr_ack[10] = 0x01; + rptr_ack[11] = 0x00; + + rptr_ack[12] = streamid_raw / 256U; + rptr_ack[13] = streamid_raw % 256U; + rptr_ack[14] = 0x80; + rptr_ack[15] = 0x01; /* we do not want to set this to 0x01 */ + rptr_ack[16] = 0x00; + rptr_ack[17] = 0x00; + + memcpy(rptr_ack + 18, OWNER, 8); + rptr_ack[25] = from_mod; + + memcpy(rptr_ack + 26, OWNER, 8); + rptr_ack[33] = 'G'; + + memcpy(rptr_ack + 34, "CQCQCQ ", 8); + + memcpy(rptr_ack + 42, OWNER, 8); + rptr_ack[49] = from_mod; + + memcpy(rptr_ack + 50, "RPTR", 4); + calcPFCS(rptr_ack,56); + (void)sendto(rptr_sock,(char *)rptr_ack,56,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[4] = 0x20; + memcpy((char *)rptr_ack + 15, silence, 9); + + /* start sending silence + announcement text */ + + rptr_ack[14] = 0x00; + rptr_ack[24] = 0x55; + rptr_ack[25] = 0x2d; + rptr_ack[26] = 0x16; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[14] = 0x01; + rptr_ack[24] = '@' ^ 0x70; + rptr_ack[25] = RADIO_ID[0] ^ 0x4f; + rptr_ack[26] = RADIO_ID[1] ^ 0x93; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[14] = 0x02; + rptr_ack[24] = RADIO_ID[2] ^ 0x70; + rptr_ack[25] = RADIO_ID[3] ^ 0x4f; + rptr_ack[26] = RADIO_ID[4] ^ 0x93; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[14] = 0x03; + rptr_ack[24] = 'A' ^ 0x70; + rptr_ack[25] = RADIO_ID[5] ^ 0x4f; + rptr_ack[26] = RADIO_ID[6] ^ 0x93; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[14] = 0x04; + rptr_ack[24] = RADIO_ID[7] ^ 0x70; + rptr_ack[25] = RADIO_ID[8] ^ 0x4f; + rptr_ack[26] = RADIO_ID[9] ^ 0x93; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[14] = 0x05; + rptr_ack[24] = 'B' ^ 0x70; + rptr_ack[25] = RADIO_ID[10] ^ 0x4f; + rptr_ack[26] = RADIO_ID[11] ^ 0x93; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[14] = 0x06; + rptr_ack[24] = RADIO_ID[12] ^ 0x70; + rptr_ack[25] = RADIO_ID[13] ^ 0x4f; + rptr_ack[26] = RADIO_ID[14] ^ 0x93; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[14] = 0x07; + rptr_ack[24] = 'C' ^ 0x70; + rptr_ack[25] = RADIO_ID[15] ^ 0x4f; + rptr_ack[26] = RADIO_ID[16] ^ 0x93; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[14] = 0x08; + rptr_ack[24] = RADIO_ID[17] ^ 0x70; + rptr_ack[25] = RADIO_ID[18] ^ 0x4f; + rptr_ack[26] = RADIO_ID[19] ^ 0x93; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + + rptr_ack[14] = 0x09 | 0x40; + memset((char *)rptr_ack + 15, 0, 9); + rptr_ack[24] = 0x70; + rptr_ack[25] = 0x4f; + rptr_ack[26] = 0x93; + (void)sendto(rptr_sock,(char *)rptr_ack,27,0,(struct sockaddr *)&toLocalg2,sizeof(toLocalg2)); + traceit("finished sending ACK+text to mod:[%c]\n", from_mod); + pthread_exit(NULL); } static void print_status_file() { - struct tm tm1; - time_t tnow; - FILE *statusfp = NULL; - short i; - inbound *inbound_ptr; - inbound_type::iterator pos; - - statusfp = fopen(STATUS_FILE, "w"); - if (!statusfp) - traceit("Failed to create status file %s\n", STATUS_FILE); - else - { - setvbuf(statusfp, (char *)NULL, _IOLBF, 0); - - time(&tnow); - localtime_r(&tnow, &tm1); - - /* print connected donglers */ - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - fprintf(statusfp, - "%c,%s,%c,%s,%02d%02d%02d,%02d:%02d:%02d\n", - 'p', - inbound_ptr->call, - 'p', - pos->first.c_str(), - tm1.tm_mon+1,tm1.tm_mday,tm1.tm_year % 100, - tm1.tm_hour,tm1.tm_min,tm1.tm_sec); - } - - /* print linked repeaters-reflectors */ - for (i = 0; i < 3; i++) - { - if (to_remote_g2[i].is_connected) - { - fprintf(statusfp, - "%c,%s,%c,%s,%02d%02d%02d,%02d:%02d:%02d\n", - to_remote_g2[i].from_mod, - to_remote_g2[i].to_call, - to_remote_g2[i].to_mod, - inet_ntoa(to_remote_g2[i].toDst4.sin_addr), - tm1.tm_mon+1,tm1.tm_mday,tm1.tm_year % 100, - tm1.tm_hour,tm1.tm_min,tm1.tm_sec); - } - } - fclose(statusfp); - } + struct tm tm1; + time_t tnow; + FILE *statusfp = NULL; + short i; + inbound *inbound_ptr; + inbound_type::iterator pos; + + statusfp = fopen(STATUS_FILE, "w"); + if (!statusfp) + traceit("Failed to create status file %s\n", STATUS_FILE); + else { + setvbuf(statusfp, (char *)NULL, _IOLBF, 0); + + time(&tnow); + localtime_r(&tnow, &tm1); + + /* print connected donglers */ + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + fprintf(statusfp, + "%c,%s,%c,%s,%02d%02d%02d,%02d:%02d:%02d\n", + 'p', + inbound_ptr->call, + 'p', + pos->first.c_str(), + tm1.tm_mon+1,tm1.tm_mday,tm1.tm_year % 100, + tm1.tm_hour,tm1.tm_min,tm1.tm_sec); + } + + /* print linked repeaters-reflectors */ + for (i = 0; i < 3; i++) { + if (to_remote_g2[i].is_connected) { + fprintf(statusfp, + "%c,%s,%c,%s,%02d%02d%02d,%02d:%02d:%02d\n", + to_remote_g2[i].from_mod, + to_remote_g2[i].to_call, + to_remote_g2[i].to_mod, + inet_ntoa(to_remote_g2[i].toDst4.sin_addr), + tm1.tm_mon+1,tm1.tm_mday,tm1.tm_year % 100, + tm1.tm_hour,tm1.tm_min,tm1.tm_sec); + } + } + fclose(statusfp); + } } /* Open text file of repeaters, reflectors */ static bool load_gwys(char *filename) { - FILE *fp = NULL; - char inbuf[1024]; - char *p = NULL; - const char *delim = " "; - - char *tok; - char call[CALL_SIZE + 1]; - char host[MAXHOSTNAMELEN + 1]; - char port[5 + 1]; - - /* host + space + port + NULL */ - char payload[MAXHOSTNAMELEN + 1 + 5 + 1]; - unsigned short j; - - gwy_list_type::iterator gwy_pos; - pair gwy_insert_pair; - - traceit("Trying to open file %s\n", filename); - fp = fopen(filename, "r"); - if (fp == NULL) - { - traceit("Failed to open file %s\n", filename); - return false; - } - traceit("Opened file %s OK\n", filename); - - while (fgets(inbuf, 1020, fp) != NULL) - { - p = strchr(inbuf, '\r'); - if (p) - *p = '\0'; - - p = strchr(inbuf, '\n'); - if (p) - *p = '\0'; - - p = strchr(inbuf, '#'); - if (p) - { - traceit("Comment line:[%s]\n", inbuf); - continue; - } - - /* get the call */ - tok = strtok(inbuf, delim); - if (!tok) - continue; - if ((strlen(tok) > CALL_SIZE) || (strlen(tok) < 3)) - { - traceit("Invalid call [%s]\n", tok); - continue; - } - memset(call, ' ', CALL_SIZE); - call[CALL_SIZE] = '\0'; - memcpy(call, tok, strlen(tok)); - for (j = 0; j < strlen(call); j++) - call[j] = toupper(call[j]); - if (strcmp(call, OWNER) == 0) - { - traceit("Call [%s] will not be loaded\n", call); - continue; - } - - /* get the host */ - tok = strtok(NULL, delim); - if (!tok) - { - traceit("Call [%s] has no host\n", call); - continue; - } - strncpy(host,tok,MAXHOSTNAMELEN); - host[MAXHOSTNAMELEN] = '\0'; - if (strcmp(host, "0.0.0.0") == 0) - { - traceit("call %s has invalid host %s\n", call, host); - continue; - } - - /* get the port */ - tok = strtok(NULL, delim); - if (!tok) - { - traceit("Call [%s] has no port\n", call); - continue; - } - if (strlen(tok) > 5) - { - traceit("call %s has invalid port [%s]\n", call, tok); - continue; - } - strcpy(port, tok); - - /* at this point, we have: call host port */ - /* copy the payload(host port) */ - sprintf(payload, "%s %s", host, port); - - gwy_pos = gwy_list.find(call); - if (gwy_pos == gwy_list.end()) - { - gwy_insert_pair = gwy_list.insert(pair(call,payload)); - if (gwy_insert_pair.second) - traceit("Added Call=[%s], payload=[%s]\n",call, payload); - else - traceit("Failed to add: Call=[%s], payload=[%s]\n",call, payload); - } - else - traceit("Call [%s] is duplicate\n", call); - } - fclose(fp); - - traceit("Added %d gateways\n", gwy_list.size()); - return true; + FILE *fp = NULL; + char inbuf[1024]; + char *p = NULL; + const char *delim = " "; + + char *tok; + char call[CALL_SIZE + 1]; + char host[MAXHOSTNAMELEN + 1]; + char port[5 + 1]; + + /* host + space + port + NULL */ + char payload[MAXHOSTNAMELEN + 1 + 5 + 1]; + unsigned short j; + + gwy_list_type::iterator gwy_pos; + pair gwy_insert_pair; + + traceit("Trying to open file %s\n", filename); + fp = fopen(filename, "r"); + if (fp == NULL) { + traceit("Failed to open file %s\n", filename); + return false; + } + traceit("Opened file %s OK\n", filename); + + while (fgets(inbuf, 1020, fp) != NULL) { + p = strchr(inbuf, '\r'); + if (p) + *p = '\0'; + + p = strchr(inbuf, '\n'); + if (p) + *p = '\0'; + + p = strchr(inbuf, '#'); + if (p) { + traceit("Comment line:[%s]\n", inbuf); + continue; + } + + /* get the call */ + tok = strtok(inbuf, delim); + if (!tok) + continue; + if ((strlen(tok) > CALL_SIZE) || (strlen(tok) < 3)) { + traceit("Invalid call [%s]\n", tok); + continue; + } + memset(call, ' ', CALL_SIZE); + call[CALL_SIZE] = '\0'; + memcpy(call, tok, strlen(tok)); + for (j = 0; j < strlen(call); j++) + call[j] = toupper(call[j]); + if (strcmp(call, OWNER) == 0) { + traceit("Call [%s] will not be loaded\n", call); + continue; + } + + /* get the host */ + tok = strtok(NULL, delim); + if (!tok) { + traceit("Call [%s] has no host\n", call); + continue; + } + strncpy(host,tok,MAXHOSTNAMELEN); + host[MAXHOSTNAMELEN] = '\0'; + if (strcmp(host, "0.0.0.0") == 0) { + traceit("call %s has invalid host %s\n", call, host); + continue; + } + + /* get the port */ + tok = strtok(NULL, delim); + if (!tok) { + traceit("Call [%s] has no port\n", call); + continue; + } + if (strlen(tok) > 5) { + traceit("call %s has invalid port [%s]\n", call, tok); + continue; + } + strcpy(port, tok); + + /* at this point, we have: call host port */ + /* copy the payload(host port) */ + sprintf(payload, "%s %s", host, port); + + gwy_pos = gwy_list.find(call); + if (gwy_pos == gwy_list.end()) { + gwy_insert_pair = gwy_list.insert(pair(call,payload)); + if (gwy_insert_pair.second) + traceit("Added Call=[%s], payload=[%s]\n",call, payload); + else + traceit("Failed to add: Call=[%s], payload=[%s]\n",call, payload); + } else + traceit("Call [%s] is duplicate\n", call); + } + fclose(fp); + + traceit("Added %d gateways\n", gwy_list.size()); + return true; } /* compute checksum */ static void calcPFCS(unsigned char *packet, int len) { - unsigned short crc_dstar_ffff = 0xffff; - unsigned short tmp, short_c; - short int i; - short int low; - short int high; - - if (len == 56) - { - low = 15; - high = 54; - } - else - if (len == 58) - { - low = 17; - high = 56; - } - else - return; - - for (i = low; i < high ; i++) - { - short_c = 0x00ff & (unsigned short)packet[i]; - tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; - crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; - } - crc_dstar_ffff = ~crc_dstar_ffff; - tmp = crc_dstar_ffff; - - if (len == 56) - { - packet[54] = (unsigned char)(crc_dstar_ffff & 0xff); - packet[55] = (unsigned char)((tmp >> 8) & 0xff); - } - else - { - packet[56] = (unsigned char)(crc_dstar_ffff & 0xff); - packet[57] = (unsigned char)((tmp >> 8) & 0xff); - } - return; + unsigned short crc_dstar_ffff = 0xffff; + unsigned short tmp, short_c; + short int i; + short int low; + short int high; + + if (len == 56) { + low = 15; + high = 54; + } else if (len == 58) { + low = 17; + high = 56; + } else + return; + + for (i = low; i < high ; i++) { + short_c = 0x00ff & (unsigned short)packet[i]; + tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; + crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; + } + crc_dstar_ffff = ~crc_dstar_ffff; + tmp = crc_dstar_ffff; + + if (len == 56) { + packet[54] = (unsigned char)(crc_dstar_ffff & 0xff); + packet[55] = (unsigned char)((tmp >> 8) & 0xff); + } else { + packet[56] = (unsigned char)(crc_dstar_ffff & 0xff); + packet[57] = (unsigned char)((tmp >> 8) & 0xff); + } + return; } /* log the event */ static void traceit(const char *fmt,...) { - time_t ltime; - struct tm mytm; - const short BFSZ = 1094; - char buf[BFSZ]; + time_t ltime; + struct tm mytm; + const short BFSZ = 1094; + char buf[BFSZ]; - time(<ime); - localtime_r(<ime,&mytm); + time(<ime); + localtime_r(<ime,&mytm); - snprintf(buf,BFSZ - 1,"%02d%02d%02d at %02d:%02d:%02d:", - mytm.tm_mon+1,mytm.tm_mday,mytm.tm_year % 100, - mytm.tm_hour,mytm.tm_min,mytm.tm_sec); + snprintf(buf,BFSZ - 1,"%02d%02d%02d at %02d:%02d:%02d:", + mytm.tm_mon+1,mytm.tm_mday,mytm.tm_year % 100, + mytm.tm_hour,mytm.tm_min,mytm.tm_sec); - va_list args; - va_start(args,fmt); - vsnprintf(buf + strlen(buf), BFSZ - strlen(buf) - 1, fmt, args); - va_end(args); + va_list args; + va_start(args,fmt); + vsnprintf(buf + strlen(buf), BFSZ - strlen(buf) - 1, fmt, args); + va_end(args); - fprintf(stdout, "%s", buf); + fprintf(stdout, "%s", buf); - return; + return; } /* process configuration file */ static bool read_config(char *cfgFile) { - bool admin_found = false; - bool link_unlink_user_found = false; - unsigned short i = 0; - short int valid_params = 26; - short int params = 0; - - admin_type::iterator pos; - link_unlink_user_type::iterator link_unlink_user_pos; - - FILE *cnf = NULL; - char inbuf[1024]; - char *p = NULL; - char *ptr; - short int j; - - cnf = fopen(cfgFile, "r"); - if (!cnf) - { - traceit("Failed to open file %s\n", cfgFile); - return false; - } - - traceit("Reading file %s\n", cfgFile); - while (fgets(inbuf, 1020, cnf) != NULL) - { - if (strchr(inbuf, '#')) - continue; - - p = strchr(inbuf, '\r'); - if (p) - *p = '\0'; - p = strchr(inbuf, '\n'); - if (p) - *p = '\0'; - - p = strchr(inbuf, '='); - if (!p) - continue; - *p = '\0'; - - if (strcmp(inbuf,"LOGIN_CALL") == 0) - { - memset(LOGIN_CALL,' ', sizeof(LOGIN_CALL)); - LOGIN_CALL[CALL_SIZE] = '\0'; - - /* no spaces after the equal sign */ - if (p[1] == ' ') - traceit("LOGIN_CALL: no spaces after the equal sign\n"); - else - { - /* take up to 8 characters, throw away the rest */ - p[CALL_SIZE + 1] = '\0'; - - /* valid length? */ - if ((strlen(p + 1) < 3) || (strlen(p + 1) > CALL_SIZE)) - traceit("LOGIN_CALL value [%s] invalid\n", p + 1); - else - { - memcpy(LOGIN_CALL, p + 1, strlen(p + 1)); - - /* uppercase it */ - for (j = 0; j < CALL_SIZE; j++) - LOGIN_CALL[j] = toupper(LOGIN_CALL[j]); - - traceit("LOGIN_CALL=[%s]\n",LOGIN_CALL); - params ++; - } - } - } - else - if (strcmp(inbuf,"ONLY_ADMIN_LOGIN") == 0) - { - if (*(p + 1) == 'Y') - ONLY_ADMIN_LOGIN = true; - else - ONLY_ADMIN_LOGIN = false; - traceit("ONLY_ADMIN_LOGIN=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"ONLY_LINK_UNLINK") == 0) - { - if (*(p + 1) == 'Y') - ONLY_LINK_UNLINK = true; - else - ONLY_LINK_UNLINK = false; - traceit("ONLY_LINK_UNLINK=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"ADMIN") == 0) - { - if (!admin_found) - { - admin_found = true; - params ++; - } - - memset(ADMIN,' ', CALL_SIZE); - ADMIN[CALL_SIZE] = '\0'; - - if ( (strlen(p + 1) < 1) || (strlen(p + 1) > CALL_SIZE) ) - traceit("ADMIN value [%s] invalid\n", p + 1); - else - { - memcpy(ADMIN, p + 1, strlen(p + 1)); - - for (i = 0; i < strlen(ADMIN); i++) - ADMIN[i] = toupper(ADMIN[i]); - - traceit("ADMIN=[%s]\n",ADMIN); - - /* check for duplicates */ - pos = admin.find(ADMIN); - if (pos != admin.end()) - traceit("[%s] already an administrator\n", ADMIN); - else - { - if (admin.insert(ADMIN).second) - traceit("[%s] is now an administrator\n", ADMIN); - else - traceit("failed to add [%s] as an administrator\n", ADMIN); - } - } - } - else - if (strcmp(inbuf,"LINK_UNLINK_USER") == 0) - { - if (!link_unlink_user_found) - { - link_unlink_user_found = true; - params ++; - } - - memset(LINK_UNLINK_USER,' ', CALL_SIZE); - LINK_UNLINK_USER[CALL_SIZE] = '\0'; - - if ( (strlen(p + 1) < 1) || (strlen(p + 1) > CALL_SIZE) ) - traceit("LINK_UNLINK_USER value [%s] invalid\n", p + 1); - else - { - memcpy(LINK_UNLINK_USER, p + 1, strlen(p + 1)); - - for (i = 0; i < strlen(LINK_UNLINK_USER); i++) - LINK_UNLINK_USER[i] = toupper(LINK_UNLINK_USER[i]); - - traceit("LINK_UNLINK_USER=[%s]\n",LINK_UNLINK_USER); - - /* check for duplicates */ - link_unlink_user_pos = link_unlink_user.find(LINK_UNLINK_USER); - if (link_unlink_user_pos != link_unlink_user.end()) - traceit("[%s] already in link_unlink_user list\n", LINK_UNLINK_USER); - else - { - if (link_unlink_user.insert(LINK_UNLINK_USER).second) - traceit("[%s] added to link_unlink_user list\n", LINK_UNLINK_USER); - else - traceit("failed to add [%s] to link_unlink_user list\n", LINK_UNLINK_USER); - } - } - } - else - if (strcmp(inbuf,"OWNER") == 0) - { - memset(OWNER,' ', sizeof(OWNER)); - OWNER[CALL_SIZE] = '\0'; - - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if ((strlen(p + 1) < 3) || (strlen(p + 1) > (CALL_SIZE - 2))) - traceit("OWNER value [%s] invalid\n", p + 1); - else - { - memcpy(OWNER, p + 1, strlen(p + 1)); - - /* uppercase it */ - for (j = 0; j < CALL_SIZE; j++) - OWNER[j] = toupper(OWNER[j]); - - traceit("OWNER=[%s]\n",OWNER); - params ++; - } - } - else - if (strcmp(inbuf,"RMT_XRF_PORT") == 0) - { - RMT_XRF_PORT = atoi(p + 1); - traceit("RMT_XRF_PORT=[%d]\n",RMT_XRF_PORT); - params ++; - } - else - if (strcmp(inbuf,"RMT_DCS_PORT") == 0) - { - RMT_DCS_PORT = atoi(p + 1); - traceit("RMT_DCS_PORT=[%d]\n",RMT_DCS_PORT); - params ++; - } - else - if (strcmp(inbuf,"RMT_REF_PORT") == 0) - { - RMT_REF_PORT = atoi(p + 1); - traceit("RMT_REF_PORT=[%d]\n",RMT_REF_PORT); - params ++; - } - else - if (strcmp(inbuf,"MY_G2_LINK_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("MY_G2_LINK_IP value [%s] invalid\n", p + 1); - else - { - strncpy(MY_G2_LINK_IP, p + 1, IP_SIZE); - MY_G2_LINK_IP[IP_SIZE] = '\0'; - traceit("MY_G2_LINK_IP=[%s]\n", MY_G2_LINK_IP); - params ++; - } - } - else - if (strcmp(inbuf,"MY_G2_LINK_PORT") == 0) - { - MY_G2_LINK_PORT = atoi(p + 1); - traceit("MY_G2_LINK_PORT=[%d]\n",MY_G2_LINK_PORT); - params ++; - } - else - if (strcmp(inbuf,"TO_G2_EXTERNAL_IP") == 0) - { - ptr = strchr(p + 1, ' '); - if (ptr) - *ptr = '\0'; - - if (strlen(p + 1) < 1) - traceit("TO_G2_EXTERNAL_IP value [%s] invalid\n", p + 1); - else - { - strncpy(TO_G2_EXTERNAL_IP, p + 1, IP_SIZE); - TO_G2_EXTERNAL_IP[IP_SIZE] = '\0'; - traceit("TO_G2_EXTERNAL_IP=[%s]\n", TO_G2_EXTERNAL_IP); - params ++; - } - } - else - if (strcmp(inbuf,"TO_G2_EXTERNAL_PORT") == 0) - { - TO_G2_EXTERNAL_PORT = atoi(p + 1); - traceit("TO_G2_EXTERNAL_PORT=[%d]\n",TO_G2_EXTERNAL_PORT); - params ++; - } - else - if (strcmp(inbuf,"QSO_DETAILS") == 0) - { - if (*(p + 1) == 'Y') - QSO_DETAILS = true; - else - QSO_DETAILS = false; - traceit("QSO_DETAILS=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"GWYS") == 0) - { - memset(GWYS, '\0', sizeof(GWYS)); - strncpy(GWYS, p + 1,FILENAME_MAX); - traceit("GWYS=[%s]\n", GWYS); - params ++; - } - else - if (strcmp(inbuf,"STATUS_FILE") == 0) - { - memset(STATUS_FILE, '\0', sizeof(STATUS_FILE)); - strncpy(STATUS_FILE, p + 1,FILENAME_MAX); - traceit("STATUS_FILE=[%s]\n",STATUS_FILE); - params ++; - } - else - if (strcmp(inbuf,"DELAY_BETWEEN") == 0) - { - DELAY_BETWEEN = atoi(p + 1); - if (DELAY_BETWEEN <= 0) - DELAY_BETWEEN = 20; - traceit("DELAY_BETWEEN=[%d]\n",DELAY_BETWEEN); - params ++; - } - else - if (strcmp(inbuf,"RPTR_ACK") == 0) - { - if (*(p + 1) == 'Y') - RPTR_ACK = true; - else - RPTR_ACK = false; - traceit("RPTR_ACK=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"ANNOUNCE") == 0) - { - if (*(p + 1) == 'Y') - ANNOUNCE = true; - else - ANNOUNCE = false; - traceit("ANNOUNCE=[%c]\n", *(p + 1)); - params ++; - } - else - if (strcmp(inbuf,"ANNOUNCE_DIR") == 0) - { - memset(ANNOUNCE_DIR, '\0', sizeof(ANNOUNCE_DIR)); - strncpy(ANNOUNCE_DIR, p + 1, FILENAME_MAX); - traceit("ANNOUNCE_DIR=[%s]\n", ANNOUNCE_DIR); - params ++; - } - else - if (strcmp(inbuf,"DELAY_BEFORE") == 0) - { - DELAY_BEFORE = atoi(p + 1); - if (DELAY_BEFORE <= 0) - DELAY_BEFORE = 1; - traceit("DELAY_BEFORE=[%d]\n",DELAY_BEFORE); - params ++; - } - else - if (strcmp(inbuf,"LINK_AT_STARTUP") == 0) - { - memset(LINK_AT_STARTUP, '\0', sizeof(LINK_AT_STARTUP)); - strncpy(LINK_AT_STARTUP, p + 1, CALL_SIZE); - traceit("LINK_AT_STARTUP=[%s]\n", LINK_AT_STARTUP); - params ++; - } - else - if (strcmp(inbuf,"MAX_DONGLES") == 0) - { - MAX_DONGLES = atoi(p + 1); - traceit("MAX_DONGLES=[%d]\n",MAX_DONGLES); - SAVED_MAX_DONGLES = MAX_DONGLES; - params ++; - } - else - if (strcmp(inbuf,"RF_INACTIVITY_TIMER_A") == 0) - { - RF_INACTIVITY_TIMER[0] = atol(p + 1); - if (RF_INACTIVITY_TIMER[0] < 0) - RF_INACTIVITY_TIMER[0] = 10; - traceit("RF_INACTIVITY_TIMER_A=[%ld]\n",RF_INACTIVITY_TIMER[0]); - RF_INACTIVITY_TIMER[0] = RF_INACTIVITY_TIMER[0] * 60; - params ++; - } - else - if (strcmp(inbuf,"RF_INACTIVITY_TIMER_B") == 0) - { - RF_INACTIVITY_TIMER[1] = atol(p + 1); - if (RF_INACTIVITY_TIMER[1] < 0) - RF_INACTIVITY_TIMER[1] = 10; - traceit("RF_INACTIVITY_TIMER_B=[%ld]\n",RF_INACTIVITY_TIMER[1]); - RF_INACTIVITY_TIMER[1] = RF_INACTIVITY_TIMER[1] * 60; - params ++; - } - else - if (strcmp(inbuf,"RF_INACTIVITY_TIMER_C") == 0) - { - RF_INACTIVITY_TIMER[2] = atol(p + 1); - if (RF_INACTIVITY_TIMER[2] < 0) - RF_INACTIVITY_TIMER[2] = 10; - traceit("RF_INACTIVITY_TIMER_C=[%ld]\n",RF_INACTIVITY_TIMER[2]); - RF_INACTIVITY_TIMER[2] = RF_INACTIVITY_TIMER[2] * 60; - params ++; - } - } - fclose(cnf); - - if (params != valid_params) - { - traceit("Configuration file %s invalid\n",cfgFile); - return false; - } - - return true; + bool admin_found = false; + bool link_unlink_user_found = false; + unsigned short i = 0; + short int valid_params = 26; + short int params = 0; + + admin_type::iterator pos; + link_unlink_user_type::iterator link_unlink_user_pos; + + FILE *cnf = NULL; + char inbuf[1024]; + char *p = NULL; + char *ptr; + short int j; + + cnf = fopen(cfgFile, "r"); + if (!cnf) { + traceit("Failed to open file %s\n", cfgFile); + return false; + } + + traceit("Reading file %s\n", cfgFile); + while (fgets(inbuf, 1020, cnf) != NULL) { + if (strchr(inbuf, '#')) + continue; + + p = strchr(inbuf, '\r'); + if (p) + *p = '\0'; + p = strchr(inbuf, '\n'); + if (p) + *p = '\0'; + + p = strchr(inbuf, '='); + if (!p) + continue; + *p = '\0'; + + if (strcmp(inbuf,"LOGIN_CALL") == 0) { + memset(LOGIN_CALL,' ', sizeof(LOGIN_CALL)); + LOGIN_CALL[CALL_SIZE] = '\0'; + + /* no spaces after the equal sign */ + if (p[1] == ' ') + traceit("LOGIN_CALL: no spaces after the equal sign\n"); + else { + /* take up to 8 characters, throw away the rest */ + p[CALL_SIZE + 1] = '\0'; + + /* valid length? */ + if ((strlen(p + 1) < 3) || (strlen(p + 1) > CALL_SIZE)) + traceit("LOGIN_CALL value [%s] invalid\n", p + 1); + else { + memcpy(LOGIN_CALL, p + 1, strlen(p + 1)); + + /* uppercase it */ + for (j = 0; j < CALL_SIZE; j++) + LOGIN_CALL[j] = toupper(LOGIN_CALL[j]); + + traceit("LOGIN_CALL=[%s]\n",LOGIN_CALL); + params ++; + } + } + } else if (strcmp(inbuf,"ONLY_ADMIN_LOGIN") == 0) { + if (*(p + 1) == 'Y') + ONLY_ADMIN_LOGIN = true; + else + ONLY_ADMIN_LOGIN = false; + traceit("ONLY_ADMIN_LOGIN=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"ONLY_LINK_UNLINK") == 0) { + if (*(p + 1) == 'Y') + ONLY_LINK_UNLINK = true; + else + ONLY_LINK_UNLINK = false; + traceit("ONLY_LINK_UNLINK=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"ADMIN") == 0) { + if (!admin_found) { + admin_found = true; + params ++; + } + + memset(ADMIN,' ', CALL_SIZE); + ADMIN[CALL_SIZE] = '\0'; + + if ( (strlen(p + 1) < 1) || (strlen(p + 1) > CALL_SIZE) ) + traceit("ADMIN value [%s] invalid\n", p + 1); + else { + memcpy(ADMIN, p + 1, strlen(p + 1)); + + for (i = 0; i < strlen(ADMIN); i++) + ADMIN[i] = toupper(ADMIN[i]); + + traceit("ADMIN=[%s]\n",ADMIN); + + /* check for duplicates */ + pos = admin.find(ADMIN); + if (pos != admin.end()) + traceit("[%s] already an administrator\n", ADMIN); + else { + if (admin.insert(ADMIN).second) + traceit("[%s] is now an administrator\n", ADMIN); + else + traceit("failed to add [%s] as an administrator\n", ADMIN); + } + } + } else if (strcmp(inbuf,"LINK_UNLINK_USER") == 0) { + if (!link_unlink_user_found) { + link_unlink_user_found = true; + params ++; + } + + memset(LINK_UNLINK_USER,' ', CALL_SIZE); + LINK_UNLINK_USER[CALL_SIZE] = '\0'; + + if ( (strlen(p + 1) < 1) || (strlen(p + 1) > CALL_SIZE) ) + traceit("LINK_UNLINK_USER value [%s] invalid\n", p + 1); + else { + memcpy(LINK_UNLINK_USER, p + 1, strlen(p + 1)); + + for (i = 0; i < strlen(LINK_UNLINK_USER); i++) + LINK_UNLINK_USER[i] = toupper(LINK_UNLINK_USER[i]); + + traceit("LINK_UNLINK_USER=[%s]\n",LINK_UNLINK_USER); + + /* check for duplicates */ + link_unlink_user_pos = link_unlink_user.find(LINK_UNLINK_USER); + if (link_unlink_user_pos != link_unlink_user.end()) + traceit("[%s] already in link_unlink_user list\n", LINK_UNLINK_USER); + else { + if (link_unlink_user.insert(LINK_UNLINK_USER).second) + traceit("[%s] added to link_unlink_user list\n", LINK_UNLINK_USER); + else + traceit("failed to add [%s] to link_unlink_user list\n", LINK_UNLINK_USER); + } + } + } else if (strcmp(inbuf,"OWNER") == 0) { + memset(OWNER,' ', sizeof(OWNER)); + OWNER[CALL_SIZE] = '\0'; + + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if ((strlen(p + 1) < 3) || (strlen(p + 1) > (CALL_SIZE - 2))) + traceit("OWNER value [%s] invalid\n", p + 1); + else { + memcpy(OWNER, p + 1, strlen(p + 1)); + + /* uppercase it */ + for (j = 0; j < CALL_SIZE; j++) + OWNER[j] = toupper(OWNER[j]); + + traceit("OWNER=[%s]\n",OWNER); + params ++; + } + } else if (strcmp(inbuf,"RMT_XRF_PORT") == 0) { + RMT_XRF_PORT = atoi(p + 1); + traceit("RMT_XRF_PORT=[%d]\n",RMT_XRF_PORT); + params ++; + } else if (strcmp(inbuf,"RMT_DCS_PORT") == 0) { + RMT_DCS_PORT = atoi(p + 1); + traceit("RMT_DCS_PORT=[%d]\n",RMT_DCS_PORT); + params ++; + } else if (strcmp(inbuf,"RMT_REF_PORT") == 0) { + RMT_REF_PORT = atoi(p + 1); + traceit("RMT_REF_PORT=[%d]\n",RMT_REF_PORT); + params ++; + } else if (strcmp(inbuf,"MY_G2_LINK_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("MY_G2_LINK_IP value [%s] invalid\n", p + 1); + else { + strncpy(MY_G2_LINK_IP, p + 1, IP_SIZE); + MY_G2_LINK_IP[IP_SIZE] = '\0'; + traceit("MY_G2_LINK_IP=[%s]\n", MY_G2_LINK_IP); + params ++; + } + } else if (strcmp(inbuf,"MY_G2_LINK_PORT") == 0) { + MY_G2_LINK_PORT = atoi(p + 1); + traceit("MY_G2_LINK_PORT=[%d]\n",MY_G2_LINK_PORT); + params ++; + } else if (strcmp(inbuf,"TO_G2_EXTERNAL_IP") == 0) { + ptr = strchr(p + 1, ' '); + if (ptr) + *ptr = '\0'; + + if (strlen(p + 1) < 1) + traceit("TO_G2_EXTERNAL_IP value [%s] invalid\n", p + 1); + else { + strncpy(TO_G2_EXTERNAL_IP, p + 1, IP_SIZE); + TO_G2_EXTERNAL_IP[IP_SIZE] = '\0'; + traceit("TO_G2_EXTERNAL_IP=[%s]\n", TO_G2_EXTERNAL_IP); + params ++; + } + } else if (strcmp(inbuf,"TO_G2_EXTERNAL_PORT") == 0) { + TO_G2_EXTERNAL_PORT = atoi(p + 1); + traceit("TO_G2_EXTERNAL_PORT=[%d]\n",TO_G2_EXTERNAL_PORT); + params ++; + } else if (strcmp(inbuf,"QSO_DETAILS") == 0) { + if (*(p + 1) == 'Y') + QSO_DETAILS = true; + else + QSO_DETAILS = false; + traceit("QSO_DETAILS=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"GWYS") == 0) { + memset(GWYS, '\0', sizeof(GWYS)); + strncpy(GWYS, p + 1,FILENAME_MAX); + traceit("GWYS=[%s]\n", GWYS); + params ++; + } else if (strcmp(inbuf,"STATUS_FILE") == 0) { + memset(STATUS_FILE, '\0', sizeof(STATUS_FILE)); + strncpy(STATUS_FILE, p + 1,FILENAME_MAX); + traceit("STATUS_FILE=[%s]\n",STATUS_FILE); + params ++; + } else if (strcmp(inbuf,"DELAY_BETWEEN") == 0) { + DELAY_BETWEEN = atoi(p + 1); + if (DELAY_BETWEEN <= 0) + DELAY_BETWEEN = 20; + traceit("DELAY_BETWEEN=[%d]\n",DELAY_BETWEEN); + params ++; + } else if (strcmp(inbuf,"RPTR_ACK") == 0) { + if (*(p + 1) == 'Y') + RPTR_ACK = true; + else + RPTR_ACK = false; + traceit("RPTR_ACK=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"ANNOUNCE") == 0) { + if (*(p + 1) == 'Y') + ANNOUNCE = true; + else + ANNOUNCE = false; + traceit("ANNOUNCE=[%c]\n", *(p + 1)); + params ++; + } else if (strcmp(inbuf,"ANNOUNCE_DIR") == 0) { + memset(ANNOUNCE_DIR, '\0', sizeof(ANNOUNCE_DIR)); + strncpy(ANNOUNCE_DIR, p + 1, FILENAME_MAX); + traceit("ANNOUNCE_DIR=[%s]\n", ANNOUNCE_DIR); + params ++; + } else if (strcmp(inbuf,"DELAY_BEFORE") == 0) { + DELAY_BEFORE = atoi(p + 1); + if (DELAY_BEFORE <= 0) + DELAY_BEFORE = 1; + traceit("DELAY_BEFORE=[%d]\n",DELAY_BEFORE); + params ++; + } else if (strcmp(inbuf,"LINK_AT_STARTUP") == 0) { + memset(LINK_AT_STARTUP, '\0', sizeof(LINK_AT_STARTUP)); + strncpy(LINK_AT_STARTUP, p + 1, CALL_SIZE); + traceit("LINK_AT_STARTUP=[%s]\n", LINK_AT_STARTUP); + params ++; + } else if (strcmp(inbuf,"MAX_DONGLES") == 0) { + MAX_DONGLES = atoi(p + 1); + traceit("MAX_DONGLES=[%d]\n",MAX_DONGLES); + SAVED_MAX_DONGLES = MAX_DONGLES; + params ++; + } else if (strcmp(inbuf,"RF_INACTIVITY_TIMER_A") == 0) { + RF_INACTIVITY_TIMER[0] = atol(p + 1); + if (RF_INACTIVITY_TIMER[0] < 0) + RF_INACTIVITY_TIMER[0] = 10; + traceit("RF_INACTIVITY_TIMER_A=[%ld]\n",RF_INACTIVITY_TIMER[0]); + RF_INACTIVITY_TIMER[0] = RF_INACTIVITY_TIMER[0] * 60; + params ++; + } else if (strcmp(inbuf,"RF_INACTIVITY_TIMER_B") == 0) { + RF_INACTIVITY_TIMER[1] = atol(p + 1); + if (RF_INACTIVITY_TIMER[1] < 0) + RF_INACTIVITY_TIMER[1] = 10; + traceit("RF_INACTIVITY_TIMER_B=[%ld]\n",RF_INACTIVITY_TIMER[1]); + RF_INACTIVITY_TIMER[1] = RF_INACTIVITY_TIMER[1] * 60; + params ++; + } else if (strcmp(inbuf,"RF_INACTIVITY_TIMER_C") == 0) { + RF_INACTIVITY_TIMER[2] = atol(p + 1); + if (RF_INACTIVITY_TIMER[2] < 0) + RF_INACTIVITY_TIMER[2] = 10; + traceit("RF_INACTIVITY_TIMER_C=[%ld]\n",RF_INACTIVITY_TIMER[2]); + RF_INACTIVITY_TIMER[2] = RF_INACTIVITY_TIMER[2] * 60; + params ++; + } + } + fclose(cnf); + + if (params != valid_params) { + traceit("Configuration file %s invalid\n",cfgFile); + return false; + } + + return true; } /* create our server */ static bool srv_open() { - struct sockaddr_in sin; - short i; - - /* create our XRF gateway socket */ - xrf_g2_sock = socket(PF_INET,SOCK_DGRAM,0); - if (xrf_g2_sock == -1) - { - traceit("Failed to create gateway socket for XRF,errno=%d\n",errno); - return false; - } - fcntl(xrf_g2_sock,F_SETFL,O_NONBLOCK); - - memset(&sin,0,sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr(MY_G2_LINK_IP); - sin.sin_port = htons(RMT_XRF_PORT); - if (bind(xrf_g2_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) - { - traceit("Failed to bind gateway socket on port %d for XRF, errno=%d\n", - RMT_XRF_PORT ,errno); - close(xrf_g2_sock); - xrf_g2_sock = -1; - return false; - } - - /* create the dcs socket */ - dcs_g2_sock = socket(PF_INET,SOCK_DGRAM,0); - if (dcs_g2_sock == -1) - { - traceit("Failed to create gateway socket for DCS,errno=%d\n",errno); - close(xrf_g2_sock); - xrf_g2_sock = -1; - return false; - } - fcntl(dcs_g2_sock,F_SETFL,O_NONBLOCK); - - /* socket for REF */ - ref_g2_sock = socket(PF_INET,SOCK_DGRAM,0); - if (ref_g2_sock == -1) - { - traceit("Failed to create gateway socket for REF, errno=%d\n",errno); - close(dcs_g2_sock); - dcs_g2_sock = -1; - close(xrf_g2_sock); - xrf_g2_sock = -1; - return false; - } - fcntl(ref_g2_sock,F_SETFL,O_NONBLOCK); - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr(MY_G2_LINK_IP); - sin.sin_port = htons(RMT_REF_PORT); - if (bind(ref_g2_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) - { - traceit("Failed to bind gateway socket on port %d for REF, errno=%d\n", - RMT_REF_PORT ,errno); - close(dcs_g2_sock); - dcs_g2_sock = -1; - close(xrf_g2_sock); - xrf_g2_sock = -1; - close(ref_g2_sock); - ref_g2_sock = -1; - return false; - } - - /* create our repeater socket */ - rptr_sock = socket(PF_INET,SOCK_DGRAM,0); - if (rptr_sock == -1) - { - traceit("Failed to create repeater socket,errno=%d\n",errno); - close(dcs_g2_sock); - dcs_g2_sock = -1; - close(xrf_g2_sock); - xrf_g2_sock = -1; - close(ref_g2_sock); - ref_g2_sock = -1; - return false; - } - fcntl(rptr_sock,F_SETFL,O_NONBLOCK); - - memset(&sin,0,sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr(MY_G2_LINK_IP); - sin.sin_port = htons(MY_G2_LINK_PORT); - if (bind(rptr_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) - { - traceit("Failed to bind repeater socket on port %d, errno=%d\n", - MY_G2_LINK_PORT,errno); - close(dcs_g2_sock); - dcs_g2_sock = -1; - close(rptr_sock); - rptr_sock = -1; - close(xrf_g2_sock); - xrf_g2_sock = -1; - close(ref_g2_sock); - ref_g2_sock = -1; - return false; - } - - /* the local G2 external runs on this IP and port */ - memset(&toLocalg2,0,sizeof(struct sockaddr_in)); - toLocalg2.sin_family = AF_INET; - toLocalg2.sin_addr.s_addr = inet_addr(TO_G2_EXTERNAL_IP); - toLocalg2.sin_port = htons(TO_G2_EXTERNAL_PORT); - - /* initialize all remote links */ - for (i = 0; i < 3; i++) - { - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - to_remote_g2[i].out_streamid[0] = 0x00; - to_remote_g2[i].out_streamid[1] = 0x00; - } - return true; -} + struct sockaddr_in sin; + short i; + + /* create our XRF gateway socket */ + xrf_g2_sock = socket(PF_INET,SOCK_DGRAM,0); + if (xrf_g2_sock == -1) { + traceit("Failed to create gateway socket for XRF,errno=%d\n",errno); + return false; + } + fcntl(xrf_g2_sock,F_SETFL,O_NONBLOCK); + + memset(&sin,0,sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(MY_G2_LINK_IP); + sin.sin_port = htons(RMT_XRF_PORT); + if (bind(xrf_g2_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) { + traceit("Failed to bind gateway socket on port %d for XRF, errno=%d\n", + RMT_XRF_PORT ,errno); + close(xrf_g2_sock); + xrf_g2_sock = -1; + return false; + } + + /* create the dcs socket */ + dcs_g2_sock = socket(PF_INET,SOCK_DGRAM,0); + if (dcs_g2_sock == -1) { + traceit("Failed to create gateway socket for DCS,errno=%d\n",errno); + close(xrf_g2_sock); + xrf_g2_sock = -1; + return false; + } + fcntl(dcs_g2_sock,F_SETFL,O_NONBLOCK); + + /* socket for REF */ + ref_g2_sock = socket(PF_INET,SOCK_DGRAM,0); + if (ref_g2_sock == -1) { + traceit("Failed to create gateway socket for REF, errno=%d\n",errno); + close(dcs_g2_sock); + dcs_g2_sock = -1; + close(xrf_g2_sock); + xrf_g2_sock = -1; + return false; + } + fcntl(ref_g2_sock,F_SETFL,O_NONBLOCK); + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(MY_G2_LINK_IP); + sin.sin_port = htons(RMT_REF_PORT); + if (bind(ref_g2_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) { + traceit("Failed to bind gateway socket on port %d for REF, errno=%d\n", + RMT_REF_PORT ,errno); + close(dcs_g2_sock); + dcs_g2_sock = -1; + close(xrf_g2_sock); + xrf_g2_sock = -1; + close(ref_g2_sock); + ref_g2_sock = -1; + return false; + } + + /* create our repeater socket */ + rptr_sock = socket(PF_INET,SOCK_DGRAM,0); + if (rptr_sock == -1) { + traceit("Failed to create repeater socket,errno=%d\n",errno); + close(dcs_g2_sock); + dcs_g2_sock = -1; + close(xrf_g2_sock); + xrf_g2_sock = -1; + close(ref_g2_sock); + ref_g2_sock = -1; + return false; + } + fcntl(rptr_sock,F_SETFL,O_NONBLOCK); + + memset(&sin,0,sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(MY_G2_LINK_IP); + sin.sin_port = htons(MY_G2_LINK_PORT); + if (bind(rptr_sock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) != 0) { + traceit("Failed to bind repeater socket on port %d, errno=%d\n", + MY_G2_LINK_PORT,errno); + close(dcs_g2_sock); + dcs_g2_sock = -1; + close(rptr_sock); + rptr_sock = -1; + close(xrf_g2_sock); + xrf_g2_sock = -1; + close(ref_g2_sock); + ref_g2_sock = -1; + return false; + } + + /* the local G2 external runs on this IP and port */ + memset(&toLocalg2,0,sizeof(struct sockaddr_in)); + toLocalg2.sin_family = AF_INET; + toLocalg2.sin_addr.s_addr = inet_addr(TO_G2_EXTERNAL_IP); + toLocalg2.sin_port = htons(TO_G2_EXTERNAL_PORT); + + /* initialize all remote links */ + for (i = 0; i < 3; i++) { + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + to_remote_g2[i].out_streamid[0] = 0x00; + to_remote_g2[i].out_streamid[1] = 0x00; + } + return true; +} /* destroy our server */ static void srv_close() { - if (xrf_g2_sock != -1) - { - close(xrf_g2_sock); - traceit("Closed RMT_XRF_PORT\n"); - } - - if (dcs_g2_sock != -1) - { - close(dcs_g2_sock); - traceit("Closed RMT_DCS_PORT\n"); - } - - if (rptr_sock != -1) - { - close(rptr_sock); - traceit("Closed MY_G2_LINK_PORT\n"); - } - - if (ref_g2_sock != -1) - { - close(ref_g2_sock); - traceit("Closed RMT_REF_PORT\n"); - } - - return; + if (xrf_g2_sock != -1) { + close(xrf_g2_sock); + traceit("Closed RMT_XRF_PORT\n"); + } + + if (dcs_g2_sock != -1) { + close(dcs_g2_sock); + traceit("Closed RMT_DCS_PORT\n"); + } + + if (rptr_sock != -1) { + close(rptr_sock); + traceit("Closed MY_G2_LINK_PORT\n"); + } + + if (ref_g2_sock != -1) { + close(ref_g2_sock); + traceit("Closed RMT_REF_PORT\n"); + } + + return; } /* find the repeater IP by callsign and link to it */ static void g2link(char from_mod, char *call, char to_mod) { - short i,j, counter; - - char linked_remote_system[CALL_SIZE + 1]; - char *space_p = 0; - char notify_msg[64]; - - char host[MAXHOSTNAMELEN + 1]; - char port_s[5 + 1]; - int port_i; - - /* host + space + port + NULL */ - char payload[MAXHOSTNAMELEN + 1 + 5 + 1]; - char *p = NULL; - - gwy_list_type::iterator gwy_pos; - char link_request[519]; - - bool ok = false; - - memset(link_request, 0, sizeof(link_request)); - - host[0] = '\0'; - port_s[0] = '\0'; - payload[0] = '\0'; - - if (from_mod == 'A') - i = 0; - else - if (from_mod == 'B') - i = 1; - else - if (from_mod == 'C') - i = 2; - else - { - traceit("from_mod %c invalid\n", from_mod); - return; - } - - memset(&to_remote_g2[i], 0, sizeof(to_remote_g2[i])); - - strcpy(to_remote_g2[i].to_call, call); - to_remote_g2[i].to_mod = to_mod; - - if ((memcmp(call, "REF", 3) == 0) || - (memcmp(call, "DCS", 3) == 0)) - { - for (counter = 0; counter < 3; counter++) - { - if (counter != i) - { - if ( (to_remote_g2[counter].to_call[0] != '\0') && - (strcmp(to_remote_g2[counter].to_call,to_remote_g2[i].to_call) == 0) && - (to_remote_g2[counter].to_mod == to_remote_g2[i].to_mod) ) - break; - } - } - to_remote_g2[i].to_call[0] = '\0'; - to_remote_g2[i].to_mod = ' '; - - if (counter < 3) - { - traceit("Another mod(%c) is already linked to %s %c\n", - to_remote_g2[counter].from_mod, - to_remote_g2[counter].to_call, - to_remote_g2[counter].to_mod); - - return; - } - } - - gwy_pos = gwy_list.find(call); - if (gwy_pos == gwy_list.end()) - { - traceit("%s not found in gwy list\n", call); - return; - } - - strcpy(payload, gwy_pos->second.c_str()); - - /* extract host and port */ - p = strchr(payload, ' '); - if (!p) - { - traceit("Invalid payload [%s] for call [%s]\n", payload, call); - return; - } - *p = '\0'; - - strcpy(host, payload); - strcpy(port_s, p + 1); - port_i = atoi(port_s); - - if (host[0] != '\0') - { - ok = resolve_rmt(host, SOCK_DGRAM, &(to_remote_g2[i].toDst4)); - if (!ok) - { - traceit("Call %s is host %s but could not resolve to IP\n", - call, host); - memset(&to_remote_g2[i], 0, sizeof(to_remote_g2[i])); - return; - } - - strcpy(to_remote_g2[i].to_call, call); - to_remote_g2[i].toDst4.sin_family = AF_INET; - to_remote_g2[i].toDst4.sin_port = htons(port_i); - to_remote_g2[i].from_mod = from_mod; - to_remote_g2[i].to_mod = to_mod; - to_remote_g2[i].countdown = TIMEOUT; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - - /* is it XRF? */ - if (port_i == RMT_XRF_PORT) - { - strcpy(link_request, OWNER); - link_request[8] = from_mod; - link_request[9] = to_mod; - link_request[10] = '\0'; - - traceit("sending link request from mod %c to link with: [%s] mod %c [%s]\n", - to_remote_g2[i].from_mod, - to_remote_g2[i].to_call, to_remote_g2[i].to_mod, payload); - - for (j = 0; j < 5; j++) - sendto(xrf_g2_sock,link_request, CALL_SIZE + 3,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - else - if (port_i == RMT_DCS_PORT) - { - strcpy(link_request, OWNER); - link_request[8] = from_mod; - link_request[9] = to_mod; - link_request[10] = '\0'; - memcpy(link_request + 11, to_remote_g2[i].to_call, 8); - strcpy(link_request + 19, G2_html); - - traceit("sending link request from mod %c to link with: [%s] mod %c [%s]\n", - to_remote_g2[i].from_mod, - to_remote_g2[i].to_call, to_remote_g2[i].to_mod, payload); + short i,j, counter; + + char linked_remote_system[CALL_SIZE + 1]; + char *space_p = 0; + char notify_msg[64]; + + char host[MAXHOSTNAMELEN + 1]; + char port_s[5 + 1]; + int port_i; + + /* host + space + port + NULL */ + char payload[MAXHOSTNAMELEN + 1 + 5 + 1]; + char *p = NULL; + + gwy_list_type::iterator gwy_pos; + char link_request[519]; + + bool ok = false; + + memset(link_request, 0, sizeof(link_request)); + + host[0] = '\0'; + port_s[0] = '\0'; + payload[0] = '\0'; + + if (from_mod == 'A') + i = 0; + else if (from_mod == 'B') + i = 1; + else if (from_mod == 'C') + i = 2; + else { + traceit("from_mod %c invalid\n", from_mod); + return; + } + + memset(&to_remote_g2[i], 0, sizeof(to_remote_g2[i])); + + strcpy(to_remote_g2[i].to_call, call); + to_remote_g2[i].to_mod = to_mod; + + if ((memcmp(call, "REF", 3) == 0) || + (memcmp(call, "DCS", 3) == 0)) { + for (counter = 0; counter < 3; counter++) { + if (counter != i) { + if ( (to_remote_g2[counter].to_call[0] != '\0') && + (strcmp(to_remote_g2[counter].to_call,to_remote_g2[i].to_call) == 0) && + (to_remote_g2[counter].to_mod == to_remote_g2[i].to_mod) ) + break; + } + } + to_remote_g2[i].to_call[0] = '\0'; + to_remote_g2[i].to_mod = ' '; + + if (counter < 3) { + traceit("Another mod(%c) is already linked to %s %c\n", + to_remote_g2[counter].from_mod, + to_remote_g2[counter].to_call, + to_remote_g2[counter].to_mod); + + return; + } + } + + gwy_pos = gwy_list.find(call); + if (gwy_pos == gwy_list.end()) { + traceit("%s not found in gwy list\n", call); + return; + } + + strcpy(payload, gwy_pos->second.c_str()); + + /* extract host and port */ + p = strchr(payload, ' '); + if (!p) { + traceit("Invalid payload [%s] for call [%s]\n", payload, call); + return; + } + *p = '\0'; + + strcpy(host, payload); + strcpy(port_s, p + 1); + port_i = atoi(port_s); + + if (host[0] != '\0') { + ok = resolve_rmt(host, SOCK_DGRAM, &(to_remote_g2[i].toDst4)); + if (!ok) { + traceit("Call %s is host %s but could not resolve to IP\n", + call, host); + memset(&to_remote_g2[i], 0, sizeof(to_remote_g2[i])); + return; + } + + strcpy(to_remote_g2[i].to_call, call); + to_remote_g2[i].toDst4.sin_family = AF_INET; + to_remote_g2[i].toDst4.sin_port = htons(port_i); + to_remote_g2[i].from_mod = from_mod; + to_remote_g2[i].to_mod = to_mod; + to_remote_g2[i].countdown = TIMEOUT; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + + /* is it XRF? */ + if (port_i == RMT_XRF_PORT) { + strcpy(link_request, OWNER); + link_request[8] = from_mod; + link_request[9] = to_mod; + link_request[10] = '\0'; + + traceit("sending link request from mod %c to link with: [%s] mod %c [%s]\n", + to_remote_g2[i].from_mod, + to_remote_g2[i].to_call, to_remote_g2[i].to_mod, payload); + + for (j = 0; j < 5; j++) + sendto(xrf_g2_sock,link_request, CALL_SIZE + 3,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } else if (port_i == RMT_DCS_PORT) { + strcpy(link_request, OWNER); + link_request[8] = from_mod; + link_request[9] = to_mod; + link_request[10] = '\0'; + memcpy(link_request + 11, to_remote_g2[i].to_call, 8); + strcpy(link_request + 19, G2_html); + + traceit("sending link request from mod %c to link with: [%s] mod %c [%s]\n", + to_remote_g2[i].from_mod, + to_remote_g2[i].to_call, to_remote_g2[i].to_mod, payload); // Login form 5 to 1 - for (j = 0; j < 1; j++) - sendto(dcs_g2_sock,link_request, 519,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - else - if (port_i == RMT_REF_PORT) - { - for (counter = 0; counter < 3; counter++) - { - if (counter != i) - { - if ( (to_remote_g2[counter].to_call[0] != '\0') && - (strcmp(to_remote_g2[counter].to_call,to_remote_g2[i].to_call) == 0) ) - break; - } - } - if (counter > 2) - { - traceit("sending link command from mod %c to: [%s] mod %c [%s]\n", - to_remote_g2[i].from_mod, - to_remote_g2[i].to_call, to_remote_g2[i].to_mod, payload); - - queryCommand[0] = 5; - queryCommand[1] = 0; - queryCommand[2] = 24; - queryCommand[3] = 0; - queryCommand[4] = 1; - - for (j = 0; j < 1; j++) - sendto(ref_g2_sock,(char *)queryCommand,5,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - else - { - if (to_remote_g2[counter].is_connected) - { - to_remote_g2[i].is_connected = true; - traceit("Local module %c is also connected to %s %c\n", - from_mod, call, to_mod); - - print_status_file(); - tracing[i].last_time = time(NULL); - - // announce it here - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - } - else - traceit("status from %s %c pending\n", to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - } - } - } - return; + for (j = 0; j < 1; j++) + sendto(dcs_g2_sock,link_request, 519,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } else if (port_i == RMT_REF_PORT) { + for (counter = 0; counter < 3; counter++) { + if (counter != i) { + if ( (to_remote_g2[counter].to_call[0] != '\0') && + (strcmp(to_remote_g2[counter].to_call,to_remote_g2[i].to_call) == 0) ) + break; + } + } + if (counter > 2) { + traceit("sending link command from mod %c to: [%s] mod %c [%s]\n", + to_remote_g2[i].from_mod, + to_remote_g2[i].to_call, to_remote_g2[i].to_mod, payload); + + queryCommand[0] = 5; + queryCommand[1] = 0; + queryCommand[2] = 24; + queryCommand[3] = 0; + queryCommand[4] = 1; + + for (j = 0; j < 1; j++) + sendto(ref_g2_sock,(char *)queryCommand,5,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } else { + if (to_remote_g2[counter].is_connected) { + to_remote_g2[i].is_connected = true; + traceit("Local module %c is also connected to %s %c\n", + from_mod, call, to_mod); + + print_status_file(); + tracing[i].last_time = time(NULL); + + // announce it here + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + } else + traceit("status from %s %c pending\n", to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + } + } + } + return; } /* signal catching function */ static void sigCatch(int signum) { - /* do NOT do any serious work here */ - if ((signum == SIGTERM) || (signum == SIGINT)) - keep_running = false; - return; + /* do NOT do any serious work here */ + if ((signum == SIGTERM) || (signum == SIGINT)) + keep_running = false; + return; } static void runit() { - socklen_t fromlen; - int recvlen; - int recvlen2; - short i,j,k; - char temp_repeater[CALL_SIZE + 1]; - time_t tnow = 0, hb = 0; - int rc = 0; - - char *p = NULL; - - char notify_msg[64]; - char *space_p = 0; - char linked_remote_system[CALL_SIZE + 1]; - char unlink_request[CALL_SIZE + 3]; - - char system_cmd[FILENAME_MAX + 1]; - int max_nfds = 0; - - char tmp1[CALL_SIZE + 1]; - char tmp2[36]; // 8 for rpt1 + 24 for time_t in string format - dt_lh_type::iterator dt_lh_pos; - dt_lh_type::reverse_iterator r_dt_lh_pos; - - gwy_list_type::iterator gwy_pos; - - char call[CALL_SIZE + 1]; - char ip[IP_SIZE + 1]; - inbound *inbound_ptr; - inbound_type::iterator pos; - pair insert_pair; - bool found = false; - set::iterator it; - - char cmd_2_dcs[23]; - unsigned char dcs_seq[3] = { 0x00, 0x00, 0x00 }; - struct { - char mycall[9]; - char sfx[5]; - unsigned int dcs_rptr_seq; - } rptr_2_dcs[3] = { {" ", " ", 0}, - {" ", " ", 0}, - {" ", " ", 0} }; - struct { - char mycall[9]; - char sfx[5]; - unsigned int dcs_rptr_seq; - } ref_2_dcs[3] = { {" ", " ", 0}, - {" ", " ", 0}, - {" ", " ", 0} }; - struct { - char mycall[9]; - char sfx[5]; - unsigned int dcs_rptr_seq; - } xrf_2_dcs[3] = { {" ", " ", 0}, - {" ", " ", 0}, - {" ", " ", 0} }; - - u_int16_t streamid_raw; - - char source_stn[9]; - - memset(notify_msg, '\0', sizeof(notify_msg)); - time(&hb); - - if (xrf_g2_sock > max_nfds) - max_nfds = xrf_g2_sock; - if (ref_g2_sock > max_nfds) - max_nfds = ref_g2_sock; - if (rptr_sock > max_nfds) - max_nfds = rptr_sock; - if (dcs_g2_sock > max_nfds) - max_nfds = dcs_g2_sock; - - traceit("xrf=%d, dcs=%d, ref=%d, rptr=%d, MAX+1=%d\n", - xrf_g2_sock, dcs_g2_sock, ref_g2_sock, rptr_sock, max_nfds + 1); - - if (strlen(LINK_AT_STARTUP) >= 8) - { - if ((LINK_AT_STARTUP[0] == 'A') || - (LINK_AT_STARTUP[0] == 'B') || - (LINK_AT_STARTUP[0] == 'C')) - { - memset(temp_repeater, ' ', CALL_SIZE); - memcpy(temp_repeater, LINK_AT_STARTUP + 1, 6); - temp_repeater[CALL_SIZE] = '\0'; - g2link(LINK_AT_STARTUP[0], temp_repeater, LINK_AT_STARTUP[7]); - } - memset(LINK_AT_STARTUP, '\0', sizeof(LINK_AT_STARTUP)); - } - - while (keep_running) - { - time(&tnow); - if ((tnow - hb) > 0) - { - /* send heartbeat to connected donglers */ - send_heartbeat(); - - /* send heartbeat to linked XRF repeaters/reflectors */ - if (to_remote_g2[0].toDst4.sin_port == htons(RMT_XRF_PORT)) - sendto(xrf_g2_sock,OWNER, CALL_SIZE + 1, 0, - (struct sockaddr *)&(to_remote_g2[0].toDst4), - sizeof(to_remote_g2[0].toDst4)); - - if ((to_remote_g2[1].toDst4.sin_port == htons(RMT_XRF_PORT)) && - (strcmp(to_remote_g2[1].to_call, to_remote_g2[0].to_call) != 0)) - sendto(xrf_g2_sock,OWNER, CALL_SIZE + 1, 0, - (struct sockaddr *)&(to_remote_g2[1].toDst4), - sizeof(to_remote_g2[1].toDst4)); - - if ((to_remote_g2[2].toDst4.sin_port == htons(RMT_XRF_PORT)) && - (strcmp(to_remote_g2[2].to_call, to_remote_g2[0].to_call) != 0) && - (strcmp(to_remote_g2[2].to_call, to_remote_g2[1].to_call) != 0)) - sendto(xrf_g2_sock,OWNER, CALL_SIZE + 1, 0, - (struct sockaddr *)&(to_remote_g2[2].toDst4), - sizeof(to_remote_g2[2].toDst4)); - - /* send heartbeat to linked DCS reflectors */ - if (to_remote_g2[0].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - strcpy(cmd_2_dcs, OWNER); cmd_2_dcs[7] = to_remote_g2[0].from_mod; - memcpy(cmd_2_dcs + 9, to_remote_g2[0].to_call, 8); cmd_2_dcs[16] = to_remote_g2[0].to_mod; - sendto(dcs_g2_sock, cmd_2_dcs, 17, 0, - (struct sockaddr *)&(to_remote_g2[0].toDst4), - sizeof(to_remote_g2[0].toDst4)); - } - if (to_remote_g2[1].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - strcpy(cmd_2_dcs, OWNER); cmd_2_dcs[7] = to_remote_g2[1].from_mod; - memcpy(cmd_2_dcs + 9, to_remote_g2[1].to_call, 8); cmd_2_dcs[16] = to_remote_g2[1].to_mod; - sendto(dcs_g2_sock, cmd_2_dcs, 17, 0, - (struct sockaddr *)&(to_remote_g2[1].toDst4), - sizeof(to_remote_g2[1].toDst4)); - } - if (to_remote_g2[2].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - strcpy(cmd_2_dcs, OWNER); cmd_2_dcs[7] = to_remote_g2[2].from_mod; - memcpy(cmd_2_dcs + 9, to_remote_g2[2].to_call, 8); cmd_2_dcs[16] = to_remote_g2[2].to_mod; - sendto(dcs_g2_sock, cmd_2_dcs, 17, 0, - (struct sockaddr *)&(to_remote_g2[2].toDst4), - sizeof(to_remote_g2[2].toDst4)); - } - - /* send heartbeat to linked REF reflectors */ - if (to_remote_g2[0].is_connected && - (to_remote_g2[0].toDst4.sin_port == htons(RMT_REF_PORT))) - sendto(ref_g2_sock,(char *)REF_ACK,3,0, - (struct sockaddr *)&(to_remote_g2[0].toDst4), - sizeof(to_remote_g2[0].toDst4)); - - if (to_remote_g2[1].is_connected && - (to_remote_g2[1].toDst4.sin_port == htons(RMT_REF_PORT)) && - (strcmp(to_remote_g2[1].to_call, to_remote_g2[0].to_call) != 0)) - sendto(ref_g2_sock,(char *)REF_ACK,3,0, - (struct sockaddr *)&(to_remote_g2[1].toDst4), - sizeof(to_remote_g2[1].toDst4)); - - if (to_remote_g2[2].is_connected && - (to_remote_g2[2].toDst4.sin_port == htons(RMT_REF_PORT)) && - (strcmp(to_remote_g2[2].to_call, to_remote_g2[0].to_call) != 0) && - (strcmp(to_remote_g2[2].to_call, to_remote_g2[1].to_call) != 0)) - sendto(ref_g2_sock,(char *)REF_ACK,3,0, - (struct sockaddr *)&(to_remote_g2[2].toDst4), - sizeof(to_remote_g2[2].toDst4)); - - for (i = 0; i < 3; i++) - { - /* check for timeouts from remote */ - if (to_remote_g2[i].to_call[0] != '\0') - { - if (to_remote_g2[i].countdown >= 0) - to_remote_g2[i].countdown--; - - if (to_remote_g2[i].countdown < 0) - { - /* maybe remote system has changed IP */ - traceit("Unlinked from [%s] mod %c, TIMEOUT...\n", - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - - sprintf(notify_msg, "%c_unlinked.dat_UNLINKED_TIMEOUT", to_remote_g2[i].from_mod); - audio_notify(notify_msg); - - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - - print_status_file(); - - } - } - - /*** check for RF inactivity ***/ - if (to_remote_g2[i].is_connected) - { - if (((tnow - tracing[i].last_time) > RF_INACTIVITY_TIMER[i]) && (RF_INACTIVITY_TIMER[i] > 0)) - { - tracing[i].last_time = 0; - - traceit("Unlinked from [%s] mod %c, local RF inactivity...\n", - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) - { - queryCommand[0] = 5; - queryCommand[1] = 0; - queryCommand[2] = 24; - queryCommand[3] = 0; - queryCommand[4] = 0; - sendto(ref_g2_sock,(char *)queryCommand,5,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - - /* zero out any other entries here that match that system */ - for (j = 0; j < 3; j++) - { - if (j != i) - { - if ((to_remote_g2[j].toDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[j].toDst4.sin_port == htons(RMT_REF_PORT))) - { - to_remote_g2[j].to_call[0] = '\0'; - memset(&(to_remote_g2[j].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[j].from_mod = ' '; - to_remote_g2[j].to_mod = ' '; - to_remote_g2[j].countdown = 0; - to_remote_g2[j].is_connected = false; - to_remote_g2[j].in_streamid[0] = 0x00; - to_remote_g2[j].in_streamid[1] = 0x00; - } - } - } - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) - { - strcpy(unlink_request, OWNER); - unlink_request[8] = to_remote_g2[i].from_mod; - unlink_request[9] = ' '; - unlink_request[10] = '\0'; - - for (j = 0; j < 5; j++) - sendto(xrf_g2_sock,unlink_request, CALL_SIZE + 3,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - strcpy(cmd_2_dcs, OWNER); - cmd_2_dcs[8] = to_remote_g2[i].from_mod; - cmd_2_dcs[9] = ' '; - cmd_2_dcs[10] = '\0'; - memcpy(cmd_2_dcs + 11, to_remote_g2[i].to_call, 8); - - for (j = 0; j < 2; j++) - sendto(dcs_g2_sock, cmd_2_dcs, 19 ,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - - sprintf(notify_msg, "%c_unlinked.dat_UNLINKED_TIMEOUT", to_remote_g2[i].from_mod); - audio_notify(notify_msg); - - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - - print_status_file(); - } - } - } - time(&hb); - } - - FD_ZERO(&fdset); - FD_SET(xrf_g2_sock,&fdset); - FD_SET(dcs_g2_sock,&fdset); - FD_SET(ref_g2_sock,&fdset); - FD_SET(rptr_sock,&fdset); - tv.tv_sec = 0; - tv.tv_usec = 20000; - (void)select(max_nfds + 1,&fdset,0,0,&tv); - - if (FD_ISSET(xrf_g2_sock, &fdset)) - { - fromlen = sizeof(struct sockaddr_in); - recvlen2 = recvfrom(xrf_g2_sock,(char *)readBuffer2,100, - 0,(struct sockaddr *)&fromDst4,&fromlen); - - strncpy(ip, inet_ntoa(fromDst4.sin_addr),IP_SIZE); - ip[IP_SIZE] = '\0'; - strncpy(call, (char *)readBuffer2,CALL_SIZE); - call[CALL_SIZE] = '\0'; - - /* a packet of length (CALL_SIZE + 1) is a keepalive from a repeater/reflector */ - /* If it is from a dongle, it is either a keepalive or a request to connect */ - - if (recvlen2 == (CALL_SIZE + 1)) - { - found = false; - /* Find out if it is a keepalive from a repeater */ - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) - { - found = true; - if (!to_remote_g2[i].is_connected) - { - tracing[i].last_time = time(NULL); - - to_remote_g2[i].is_connected = true; - traceit("Connected from: %.*s\n", recvlen2 - 1, readBuffer2); - print_status_file(); - - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - - } - to_remote_g2[i].countdown = TIMEOUT; - } - } - } - else - /* A packet of length (CALL_SIZE + 6) is either an ACK or a NAK from repeater-reflector */ - /* Because we sent a request before asking to link */ - if (recvlen2 == (CALL_SIZE + 6)) - { - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) - { - if ((memcmp((char *)readBuffer2 + 10, "ACK", 3) == 0) && - (to_remote_g2[i].from_mod == readBuffer2[8])) - { - if (!to_remote_g2[i].is_connected) - { - tracing[i].last_time = time(NULL); - - to_remote_g2[i].is_connected = true; - traceit("Connected from: [%s] %c\n", - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - print_status_file(); - - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - } - } - else - if ((memcmp((char *)readBuffer2 + 10, "NAK", 3) == 0) && - (to_remote_g2[i].from_mod == readBuffer2[8])) - { - traceit("Link module %c to [%s] %c is rejected\n", - to_remote_g2[i].from_mod, to_remote_g2[i].to_call, - to_remote_g2[i].to_mod); - - sprintf(notify_msg, "%c_failed_linked.dat_FAILED_TO_LINK", - to_remote_g2[i].from_mod); - audio_notify(notify_msg); - - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - - print_status_file(); - } - } - } - } - else - /* - A packet of length (CALL_SIZE + 3) is a request - from a remote repeater to link-unlink with our repeater - */ - if (recvlen2 == CALL_SIZE + 3) - { - /* Check our linked repeaters/reflectors */ - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) - { - if (to_remote_g2[i].to_mod == readBuffer2[8]) - { - /* unlink request from remote repeater that we know */ - if (readBuffer2[9] == ' ') - { - traceit("Received: %.*s\n", recvlen2 - 1, readBuffer2); - traceit("Module %c to [%s] %c is unlinked\n", - to_remote_g2[i].from_mod, - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - - sprintf(notify_msg, "%c_unlinked.dat_UNLINKED", to_remote_g2[i].from_mod); - audio_notify(notify_msg); - - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - - print_status_file(); - } - else - /* link request from a remote repeater that we know */ - if ( - ((i == 0) && (readBuffer2[9] == 'A')) || - ((i == 1) && (readBuffer2[9] == 'B')) || - ((i == 2) && (readBuffer2[9] == 'C')) - ) - { - - /* - I HAVE TO ADD CODE here to PREVENT the REMOTE NODE - from LINKING one of their remote modules to - more than one of our local modules - */ - - traceit("Received: %.*s\n", recvlen2 - 1, readBuffer2); - - strncpy(to_remote_g2[i].to_call, (char *)readBuffer2,CALL_SIZE); - to_remote_g2[i].to_call[CALL_SIZE] = '\0'; - memcpy(&(to_remote_g2[i].toDst4), &fromDst4, sizeof(struct sockaddr_in)); - to_remote_g2[i].toDst4.sin_port = htons(RMT_XRF_PORT); - to_remote_g2[i].to_mod = readBuffer2[8]; - to_remote_g2[i].countdown = TIMEOUT; - to_remote_g2[i].is_connected = true; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - - traceit("Module %c to [%s] %c linked\n", - readBuffer2[9], - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - - tracing[i].last_time = time(NULL); - - print_status_file(); - - /* send back an ACK */ - memcpy(readBuffer2 + 10, "ACK", 4); - sendto(xrf_g2_sock, (char *)readBuffer2, CALL_SIZE + 6, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - - if (to_remote_g2[i].from_mod != readBuffer2[9]) - { - to_remote_g2[i].from_mod = readBuffer2[9]; - - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - } - } - } - } - } - - /* link request from remote repeater that is not yet linked to our system */ - /* find out which of our local modules the remote repeater is interested in */ - i = -1; - if (readBuffer2[9] == 'A') - i = 0; - else - if (readBuffer2[9] == 'B') - i = 1; - else - if (readBuffer2[9] == 'C') - i = 2; - - /* Is this repeater listed in gwys.txt? */ - gwy_pos = gwy_list.find(call); - if (gwy_pos == gwy_list.end()) - { - /* We did NOT find this repeater in gwys.txt, reject the incoming link request */ - traceit("Incoming link from %s,%s but not found in gwys.txt\n",call,ip); - i = -1; - } - else - { - rc = regexec(&preg, call, 0, NULL, 0); - if (rc != 0) - { - traceit("Invalid repeater %s,%s requesting to link\n", call, ip); - i = -1; - } - } - - if (i >= 0) - { - /* Is the local repeater module linked to anything ? */ - if (to_remote_g2[i].to_mod == ' ') - { - if ((readBuffer2[8] == 'A') || (readBuffer2[8] == 'B') || (readBuffer2[8] == 'C') || - (readBuffer2[8] == 'D') || (readBuffer2[8] == 'E')) - { - /* - I HAVE TO ADD CODE here to PREVENT the REMOTE NODE - from LINKING one of their remote modules to - more than one of our local modules - */ - - /* now it can be added as a repeater */ - strcpy(to_remote_g2[i].to_call, call); - to_remote_g2[i].to_call[CALL_SIZE] = '\0'; - memcpy(&(to_remote_g2[i].toDst4), &fromDst4, sizeof(struct sockaddr_in)); - to_remote_g2[i].toDst4.sin_port = htons(RMT_XRF_PORT); - to_remote_g2[i].from_mod = readBuffer2[9]; - to_remote_g2[i].to_mod = readBuffer2[8]; - to_remote_g2[i].countdown = TIMEOUT; - to_remote_g2[i].is_connected = true; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - - print_status_file(); - - tracing[i].last_time = time(NULL); - - traceit("Received: %.*s\n", recvlen2 - 1, readBuffer2); - traceit("Module %c to [%s] %c linked\n", - to_remote_g2[i].from_mod, - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - - /* send back an ACK */ - memcpy(readBuffer2 + 10, "ACK", 4); - sendto(xrf_g2_sock, (char *)readBuffer2, CALL_SIZE + 6, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - } - else - { - if (fromDst4.sin_addr.s_addr != to_remote_g2[i].toDst4.sin_addr.s_addr) - { - /* Our repeater module is linked to another repeater-reflector */ - memcpy(readBuffer2 + 10, "NAK", 4); - fromDst4.sin_port = htons(RMT_XRF_PORT); - sendto(xrf_g2_sock, (char *)readBuffer2, CALL_SIZE + 6, - 0,(struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - } - } - } - } - else - if ( ((recvlen2 == 56) || - (recvlen2 == 27)) && - (memcmp(readBuffer2, "DSVT", 4) == 0) && - ((readBuffer2[4] == 0x10) || - (readBuffer2[4] == 0x20)) && - (readBuffer2[8] == 0x20)) - { - /* reset countdown and protect against hackers */ - - found = false; - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) - { - to_remote_g2[i].countdown = TIMEOUT; - found = true; - } - } - - /* process header */ - - if ((recvlen2 == 56) && found) - { - memset(source_stn, ' ', 9); source_stn[8] = '\0'; - - /* some bad hotspot programs out there using INCORRECT flag */ - if (readBuffer2[15] == 0x40) - readBuffer2[15] = 0x00; - else - if (readBuffer2[15] == 0x48) - readBuffer2[15] = 0x08; - else - if (readBuffer2[15] == 0x60) - readBuffer2[15] = 0x20; - else - if (readBuffer2[15] == 0x68) - readBuffer2[15] = 0x28; - - /* A reflector will send to us its own RPT1 */ - /* A repeater will send to us our RPT1 */ - - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) - { - /* it is a reflector, reflector's rpt1 */ - if ((memcmp(readBuffer2 + 18, to_remote_g2[i].to_call, 7) == 0) && - (readBuffer2[25] == to_remote_g2[i].to_mod)) - { - memcpy(&readBuffer2[18], OWNER, CALL_SIZE); - readBuffer2[25] = to_remote_g2[i].from_mod; - memcpy(&readBuffer2[34], "CQCQCQ ", 8); - - memcpy(source_stn, to_remote_g2[i].to_call, 8); source_stn[7] = to_remote_g2[i].to_mod; - break; - } - else - /* it is a repeater, our rpt1 */ - if ((memcmp(readBuffer2 + 18, OWNER, 7)) && - (readBuffer2[25] == to_remote_g2[i].from_mod)) - { - memcpy(source_stn, to_remote_g2[i].to_call, 8); source_stn[7] = to_remote_g2[i].to_mod; - break; - } - } - } - - /* somebody's crazy idea of having a personal callsign in RPT2 */ - /* we must set it to our gateway callsign */ - memcpy(&readBuffer2[26], OWNER, CALL_SIZE); - readBuffer2[33] = 'G'; - calcPFCS(readBuffer2,56); - - /* At this point, all data have our RPT1 and RPT2 */ - - /* send the data to the repeater/reflector that is linked to our RPT1 */ - i = -1; - if (readBuffer2[25] == 'A') - i = 0; - else - if (readBuffer2[25] == 'B') - i = 1; - else - if (readBuffer2[25] == 'C') - i = 2; - - /* are we sure that RPT1 is our system? */ - if ((memcmp(readBuffer2 + 18, OWNER, 7) == 0) && (i >= 0)) - { - /* Last Heard */ - if (memcmp(old_sid[i].sid, readBuffer2 + 12, 2) != 0) - { - if (QSO_DETAILS) - traceit("START from remote g2: streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s, source=%.8s\n", - readBuffer2[12],readBuffer2[13], - readBuffer2[15], readBuffer2[16], readBuffer2[17], - &readBuffer2[42], - &readBuffer2[50], &readBuffer2[34], - &readBuffer2[18], &readBuffer2[26], - recvlen2,inet_ntoa(fromDst4.sin_addr), source_stn); - - // put user into tmp1 - memcpy(tmp1, readBuffer2 + 42, 8); tmp1[8] = '\0'; - - // delete the user if exists - for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) - { - if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) - { - dt_lh_list.erase(dt_lh_pos); - break; - } - } - /* Limit?, delete oldest user */ - if (dt_lh_list.size() == LH_MAX_SIZE) - { - dt_lh_pos = dt_lh_list.begin(); - dt_lh_list.erase(dt_lh_pos); - } - // add user - time(&tnow); - sprintf(tmp2, "%ld=r%.6s%c%c", tnow, source_stn, source_stn[7], readBuffer2[25]); - dt_lh_list[tmp2] = tmp1; - - memcpy(old_sid[i].sid, readBuffer2 + 12, 2); - } - - /* relay data to our local G2 */ - sendto(rptr_sock, (char *)readBuffer2,56,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - - /* send data to donglers */ - /* no changes here */ - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - if (fromDst4.sin_addr.s_addr != inbound_ptr->sin.sin_addr.s_addr) - { - readBuffer[0] = (unsigned char)(58 & 0xFF); - readBuffer[1] = (unsigned char)(58 >> 8 & 0x1F); - readBuffer[1] = (unsigned char)(readBuffer[1] | 0xFFFFFF80); - memcpy(readBuffer + 2, readBuffer2, 56); - - sendto(ref_g2_sock, (char *)readBuffer, 58, 0, - (struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - } - else - inbound_ptr->mod = readBuffer2[25]; - } - - /* send the data to the repeater/reflector that is linked to our RPT1 */ - - /* Is there another local module linked to the remote same xrf mod ? */ - /* If Yes, then broadcast */ - k = i + 1; - - if (k < 3) - { - brd_from_xrf_idx = 0; - streamid_raw = (readBuffer2[12] * 256U) + readBuffer2[13]; - - /* We can only enter this loop up to 2 times max */ - for (j = k; j < 3; j++) - { - /* it is a remote gateway, not a dongle user */ - if ((fromDst4.sin_addr.s_addr == to_remote_g2[j].toDst4.sin_addr.s_addr) && - /* it is xrf */ - (to_remote_g2[j].toDst4.sin_port == htons(RMT_XRF_PORT)) && - (memcmp(to_remote_g2[j].to_call, "XRF", 3) == 0) && - /* it is the same xrf and xrf module */ - (memcmp(to_remote_g2[j].to_call, to_remote_g2[i].to_call, 8) == 0) && - (to_remote_g2[j].to_mod == to_remote_g2[i].to_mod)) - { - /* send the packet to another module of our local repeater: this is multi-link */ - - /* generate new packet */ - memcpy(from_xrf_torptr_brd, readBuffer2, 56); - - /* different repeater module */ - from_xrf_torptr_brd[25] = to_remote_g2[j].from_mod; - - /* assign new streamid */ - streamid_raw ++; - if (streamid_raw == 0) - streamid_raw ++; - from_xrf_torptr_brd[12] = streamid_raw / 256U; - from_xrf_torptr_brd[13] = streamid_raw % 256U; - - calcPFCS(from_xrf_torptr_brd, 56); - - /* send the data to the local gateway/repeater */ - sendto(rptr_sock, (char *)from_xrf_torptr_brd,56,0, - (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - - /* save streamid for use with the audio packets that will arrive after this header */ - - brd_from_xrf.xrf_streamid[0] = readBuffer2[12]; - brd_from_xrf.xrf_streamid[1] = readBuffer2[13]; - brd_from_xrf.rptr_streamid[brd_from_xrf_idx][0] = from_xrf_torptr_brd[12]; - brd_from_xrf.rptr_streamid[brd_from_xrf_idx][1] = from_xrf_torptr_brd[13]; - brd_from_xrf_idx ++; - } - } - } - - if ((to_remote_g2[i].toDst4.sin_addr.s_addr != fromDst4.sin_addr.s_addr) && - to_remote_g2[i].is_connected) - { - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) - { - if ( /*** (memcmp(readBuffer2 + 42, OWNER, 8) != 0) && ***/ /* block repeater announcements */ - (memcmp(readBuffer2 + 34, "CQCQCQ", 6) == 0) && /* CQ calls only */ - ((readBuffer2[15] == 0x00) || /* normal */ - (readBuffer2[15] == 0x08) || /* EMR */ - (readBuffer2[15] == 0x20) || /* BK */ - (readBuffer2[15] == 0x28)) && /* EMR + BK */ - (memcmp(readBuffer2 + 26, OWNER, 7) == 0) && /* rpt2 must be us */ - (readBuffer2[33] == 'G')) - { - to_remote_g2[i].in_streamid[0] = readBuffer2[12]; - to_remote_g2[i].in_streamid[1] = readBuffer2[13]; - - /* inform XRF about the source */ - readBuffer2[11] = to_remote_g2[i].from_mod; - - memcpy((char *)readBuffer2 + 18, to_remote_g2[i].to_call, CALL_SIZE); - readBuffer2[25] = to_remote_g2[i].to_mod; - memcpy((char *)readBuffer2 + 26, to_remote_g2[i].to_call, CALL_SIZE); - readBuffer2[33] = 'G'; - calcPFCS(readBuffer2, 56); - - sendto(xrf_g2_sock, (char *)readBuffer2, 56, 0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) - { - if ( /*** (memcmp(readBuffer2 + 42, OWNER, 8) != 0) && ***/ /* block repeater announcements */ - (memcmp(readBuffer2 + 34, "CQCQCQ", 6) == 0) && /* CQ calls only */ - ((readBuffer2[15] == 0x00) || /* normal */ - (readBuffer2[15] == 0x08) || /* EMR */ - (readBuffer2[15] == 0x20) || /* BK */ - (readBuffer2[15] == 0x28)) && /* EMR + BK */ - (memcmp(readBuffer2 + 26, OWNER, 7) == 0) && /* rpt2 must be us */ - (readBuffer2[33] == 'G')) - { - to_remote_g2[i].in_streamid[0] = readBuffer2[12]; - to_remote_g2[i].in_streamid[1] = readBuffer2[13]; - - readBuffer[0] = (unsigned char)(58 & 0xFF); - readBuffer[1] = (unsigned char)(58 >> 8 & 0x1F); - readBuffer[1] = (unsigned char)(readBuffer[1] | 0xFFFFFF80); - - memcpy(readBuffer + 2, readBuffer2, 56); - - memset(readBuffer + 20, ' ', CALL_SIZE); - memcpy(readBuffer + 20, to_remote_g2[i].to_call, - strlen(to_remote_g2[i].to_call)); - readBuffer[27] = to_remote_g2[i].to_mod; - memset(readBuffer + 28, ' ', CALL_SIZE); - memcpy(readBuffer + 28, to_remote_g2[i].to_call, - strlen(to_remote_g2[i].to_call)); - readBuffer[35] = 'G'; - memcpy(&readBuffer[36], "CQCQCQ ", 8); - - calcPFCS(readBuffer + 2, 56); - - sendto(ref_g2_sock, (char *)readBuffer, 58, 0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - if ( /*** (memcmp(readBuffer2 + 42, OWNER, 8) != 0) && ***/ /* block repeater announcements */ - (memcmp(readBuffer2 + 34, "CQCQCQ", 6) == 0) && /* CQ calls only */ - ((readBuffer2[15] == 0x00) || /* normal */ - (readBuffer2[15] == 0x08) || /* EMR */ - (readBuffer2[15] == 0x20) || /* BK */ - (readBuffer2[15] == 0x28)) && /* EMR + BK */ - (memcmp(readBuffer2 + 26, OWNER, 7) == 0) && /* rpt2 must be us */ - (readBuffer2[33] == 'G')) - { - to_remote_g2[i].in_streamid[0] = readBuffer2[12]; - to_remote_g2[i].in_streamid[1] = readBuffer2[13]; - - memcpy(xrf_2_dcs[i].mycall, readBuffer2 + 42, 8); - memcpy(xrf_2_dcs[i].sfx, readBuffer2 + 50, 4); - xrf_2_dcs[i].dcs_rptr_seq = 0; - } - } - } - } - } - else - if (found) - { - if ((readBuffer2[14] & 0x40) != 0) - { - for (i = 0; i < 3; i++) - { - if (memcmp(old_sid[i].sid, readBuffer2 + 12, 2) == 0) - { - if (QSO_DETAILS) - traceit("END from remote g2: streamID=%d,%d, %d bytes from IP=%s\n", - readBuffer2[12],readBuffer2[13],recvlen2,inet_ntoa(fromDst4.sin_addr)); - - memset(old_sid[i].sid, 0x00, 2); - - break; - } - } - } - - /* relay data to our local G2 */ - sendto(rptr_sock, (char *)readBuffer2,27,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - - /* send data to donglers */ - /* no changes here */ - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - if (fromDst4.sin_addr.s_addr != inbound_ptr->sin.sin_addr.s_addr) - { - readBuffer[0] = (unsigned char)(29 & 0xFF); - readBuffer[1] = (unsigned char)(29 >> 8 & 0x1F); - readBuffer[1] = (unsigned char)(readBuffer[1] | 0xFFFFFF80); - - memcpy(readBuffer + 2, readBuffer2, 27); - - sendto(ref_g2_sock, (char *)readBuffer, 29, - 0,(struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - } - } - - /* do we have to broadcast ? */ - if (memcmp(brd_from_xrf.xrf_streamid, readBuffer2 + 12, 2) == 0) - { - memcpy(from_xrf_torptr_brd, readBuffer2, 27); - - if ((brd_from_xrf.rptr_streamid[0][0] != 0x00) || - (brd_from_xrf.rptr_streamid[0][1] != 0x00)) - { - from_xrf_torptr_brd[12] = brd_from_xrf.rptr_streamid[0][0]; - from_xrf_torptr_brd[13] = brd_from_xrf.rptr_streamid[0][1]; - sendto(rptr_sock, (char *)from_xrf_torptr_brd,27,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - } - - if ((brd_from_xrf.rptr_streamid[1][0] != 0x00) || - (brd_from_xrf.rptr_streamid[1][1] != 0x00)) - { - from_xrf_torptr_brd[12] = brd_from_xrf.rptr_streamid[1][0]; - from_xrf_torptr_brd[13] = brd_from_xrf.rptr_streamid[1][1]; - sendto(rptr_sock, (char *)from_xrf_torptr_brd,27,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - } - - if ((readBuffer2[14] & 0x40) != 0) - { - brd_from_xrf.xrf_streamid[0] = brd_from_xrf.xrf_streamid[1] = 0x00; - brd_from_xrf.rptr_streamid[0][0] = brd_from_xrf.rptr_streamid[0][1] = 0x00; - brd_from_xrf.rptr_streamid[1][0] = brd_from_xrf.rptr_streamid[1][1] = 0x00; - brd_from_xrf_idx = 0; - } - } - - for (i = 0; i < 3; i++) - { - if ((to_remote_g2[i].is_connected) && - (to_remote_g2[i].toDst4.sin_addr.s_addr != fromDst4.sin_addr.s_addr) && - (memcmp(to_remote_g2[i].in_streamid, readBuffer2 + 12, 2) == 0)) - { - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) - { - /* inform XRF about the source */ - readBuffer2[11] = to_remote_g2[i].from_mod; - - sendto(xrf_g2_sock, (char *)readBuffer2, 27, 0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) - { - readBuffer[0] = (unsigned char)(29 & 0xFF); - readBuffer[1] = (unsigned char)(29 >> 8 & 0x1F); - readBuffer[1] = (unsigned char)(readBuffer[1] | 0xFFFFFF80); - - memcpy(readBuffer + 2, readBuffer2, 27); - - sendto(ref_g2_sock, (char *)readBuffer, 29, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - memset(dcs_buf, 0x00, 600); - dcs_buf[0] = dcs_buf[1] = dcs_buf[2] = '0'; - dcs_buf[3] = '1'; - dcs_buf[4] = dcs_buf[5] = dcs_buf[6] = 0x00; - memcpy(dcs_buf + 7, to_remote_g2[i].to_call, 8); - dcs_buf[14] = to_remote_g2[i].to_mod; - memcpy(dcs_buf + 15, OWNER, 8); - dcs_buf[22] = to_remote_g2[i].from_mod; - memcpy(dcs_buf + 23, "CQCQCQ ", 8); - memcpy(dcs_buf + 31, xrf_2_dcs[i].mycall, 8); - memcpy(dcs_buf + 39, xrf_2_dcs[i].sfx, 4); - dcs_buf[43] = readBuffer2[12]; /* streamid0 */ - dcs_buf[44] = readBuffer2[13]; /* streamid1 */ - dcs_buf[45] = readBuffer2[14]; /* cycle sequence */ - memcpy(dcs_buf + 46, readBuffer2 + 15, 12); - - dcs_buf[58] = (xrf_2_dcs[i].dcs_rptr_seq >> 0) & 0xff; - dcs_buf[59] = (xrf_2_dcs[i].dcs_rptr_seq >> 8) & 0xff; - dcs_buf[60] = (xrf_2_dcs[i].dcs_rptr_seq >> 16) & 0xff; - - xrf_2_dcs[i].dcs_rptr_seq ++; - - dcs_buf[61] = 0x01; - dcs_buf[62] = 0x00; - - sendto(dcs_g2_sock, dcs_buf, 100, 0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - - if ((readBuffer2[14] & 0x40) != 0) - { - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - } - break; - } - } - } - } - FD_CLR (xrf_g2_sock,&fdset); - } - - if (FD_ISSET(ref_g2_sock, &fdset)) - { - fromlen = sizeof(struct sockaddr_in); - recvlen2 = recvfrom(ref_g2_sock,(char *)readBuffer2,100, - 0,(struct sockaddr *)&fromDst4,&fromlen); - - strncpy(ip, inet_ntoa(fromDst4.sin_addr),IP_SIZE); - ip[IP_SIZE] = '\0'; - - found = false; - - /* LH */ - if ((recvlen2 == 4) && - (readBuffer2[0] == 4) && - (readBuffer2[1] == 192) && - (readBuffer2[2] == 7) && - (readBuffer2[3] == 0)) - { - unsigned short j_idx = 0; - unsigned short k_idx = 0; - unsigned char tmp[2]; - - pos = inbound_list.find(ip); - if (pos != inbound_list.end()) - { - inbound_ptr = (inbound *)pos->second; - // traceit("Remote station %s %s requested LH list\n", inbound_ptr->call, ip); - - /* header is 10 bytes */ - - /* reply type */ - readBuffer2[2] = 7; - readBuffer2[3] = 0; - - /* it looks like time_t here */ - time(&tnow); - memcpy((char *)readBuffer2 + 6, (char *)&tnow, sizeof(time_t)); - - for (r_dt_lh_pos = dt_lh_list.rbegin(); r_dt_lh_pos != dt_lh_list.rend(); r_dt_lh_pos++) - { - /* each entry has 24 bytes */ - - /* start at position 10 to bypass the header */ - strcpy((char *)readBuffer2 + 10 + (24 * j_idx), r_dt_lh_pos->second.c_str()); - p = strchr((char *)r_dt_lh_pos->first.c_str(), '='); - if (p) - { - memcpy((char *)readBuffer2 + 18 + (24 * j_idx), p + 2, 8); - - /* if local or local w/gps */ - if ((p[1] == 'l') || (p[1] == 'g')) - readBuffer2[18 + (24 * j_idx) + 6] = *(p + 1); - - *p = '\0'; - tnow = atol(r_dt_lh_pos->first.c_str()); - *p = '='; - memcpy((char *)readBuffer2 + 26 + (24 * j_idx), &tnow, sizeof(time_t)); - } - else - { - memcpy((char *)readBuffer2 + 18 + (24 * j_idx), "ERROR ", 8); - time(&tnow); - memcpy((char *)readBuffer2 + 26 + (24 * j_idx), &tnow, sizeof(time_t)); - } - - readBuffer2[30 + (24 * j_idx)] = 0; - readBuffer2[31 + (24 * j_idx)] = 0; - readBuffer2[32 + (24 * j_idx)] = 0; - readBuffer2[33 + (24 * j_idx)] = 0; - - j_idx++; - - /* process 39 entries at a time */ - if (j_idx == 39) - { - /* 39 * 24 = 936 + 10 header = 946 */ - readBuffer2[0] = 0xb2; - readBuffer2[1] = 0xc3; - - /* 39 entries */ - readBuffer2[4] = 0x27; - readBuffer2[5] = 0x00; - - sendto(ref_g2_sock,(char *)readBuffer2,946,0, - (struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - - j_idx = 0; - } - } - - if (j_idx != 0) - { - k_idx = 10 + (j_idx * 24); - memcpy(tmp, (char *)&k_idx, 2); - readBuffer2[0] = tmp[0]; - readBuffer2[1] = tmp[1] | 0xc0; - - memcpy(tmp, (char *)&j_idx, 2); - readBuffer2[4] = tmp[0]; - readBuffer2[5] = tmp[1]; - - sendto(ref_g2_sock,(char *)readBuffer2, k_idx, 0, - (struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - } - } - } - else - /* linked repeaters request */ - if ((recvlen2 == 4) && - (readBuffer2[0] == 4) && - (readBuffer2[1] == 192) && - (readBuffer2[2] == 5) && - (readBuffer2[3] == 0)) - { - unsigned short i_idx = 0; - unsigned short j_idx = 0; - unsigned short k_idx = 0; - unsigned char tmp[2]; - unsigned short total = 0; - - pos = inbound_list.find(ip); - if (pos != inbound_list.end()) - { - inbound_ptr = (inbound *)pos->second; - // traceit("Remote station %s %s requested linked repeaters list\n", inbound_ptr->call, ip); - - /* header is 8 bytes */ - - /* reply type */ - readBuffer2[2] = 5; - readBuffer2[3] = 1; - - /* we can have up to 3 linked systems */ - total = 3; - memcpy(tmp, (char *)&total, 2); - readBuffer2[6] = tmp[0]; - readBuffer2[7] = tmp[1]; - - for (i = 0, i_idx = 0; i < 3; i++, i_idx++) - { - /* each entry has 20 bytes */ - if (to_remote_g2[i].to_mod != ' ') - { - if (i == 0) - readBuffer2[8 + (20 * j_idx)] = 'A'; - else - if (i == 1) - readBuffer2[8 + (20 * j_idx)] = 'B'; - else - if (i == 2) - readBuffer2[8 + (20 * j_idx)] = 'C'; - - strcpy((char *)readBuffer2 + 9 + (20 * j_idx), to_remote_g2[i].to_call); - readBuffer2[16 + (20 * j_idx)] = to_remote_g2[i].to_mod; - - readBuffer2[17 + (20 * j_idx)] = 0; - readBuffer2[18 + (20 * j_idx)] = 0; - readBuffer2[19 + (20 * j_idx)] = 0; - readBuffer2[20 + (20 * j_idx)] = 0x50; - readBuffer2[21 + (20 * j_idx)] = 0x04; - readBuffer2[22 + (20 * j_idx)] = 0x32; - readBuffer2[23 + (20 * j_idx)] = 0x4d; - readBuffer2[24 + (20 * j_idx)] = 0x9f; - readBuffer2[25 + (20 * j_idx)] = 0xdb; - readBuffer2[26 + (20 * j_idx)] = 0x0e; - readBuffer2[27 + (20 * j_idx)] = 0; - - j_idx++; - - if (j_idx == 39) - { - /* 20 bytes for each user, so 39 * 20 = 780 bytes + 8 bytes header = 788 */ - readBuffer2[0] = 0x14; - readBuffer2[1] = 0xc3; - - k_idx = i_idx - 38; - memcpy(tmp, (char *)&k_idx, 2); - readBuffer2[4] = tmp[0]; - readBuffer2[5] = tmp[1]; - - sendto(ref_g2_sock,(char *)readBuffer2,788,0, - (struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - - j_idx = 0; - } - } - } - - if (j_idx != 0) - { - k_idx = 8 + (j_idx * 20); - memcpy(tmp, (char *)&k_idx, 2); - readBuffer2[0] = tmp[0]; - readBuffer2[1] = tmp[1] | 0xc0; - - if (i_idx > j_idx) - k_idx = i_idx - j_idx; - else - k_idx = 0; - - memcpy(tmp, (char *)&k_idx, 2); - readBuffer2[4] = tmp[0]; - readBuffer2[5] = tmp[1]; - - sendto(ref_g2_sock,(char *)readBuffer2, 8 + (j_idx * 20), 0, - (struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - } - } - } - else - /* connected user list request */ - if ((recvlen2 == 4) && - (readBuffer2[0] == 4) && - (readBuffer2[1] == 192) && - (readBuffer2[2] == 6) && - (readBuffer2[3] == 0)) - { - unsigned short i_idx = 0; - unsigned short j_idx = 0; - unsigned short k_idx = 0; - unsigned char tmp[2]; - unsigned short total = 0; - - pos = inbound_list.find(ip); - if (pos != inbound_list.end()) - { - inbound_ptr = (inbound *)pos->second; - // traceit("Remote station %s %s requested connected user list\n", inbound_ptr->call, ip); - - /* header is 8 bytes */ - - /* reply type */ - readBuffer2[2] = 6; - readBuffer2[3] = 0; - - /* total connected users */ - total = inbound_list.size(); - memcpy(tmp, (char *)&total, 2); - readBuffer2[6] = tmp[0]; - readBuffer2[7] = tmp[1]; - - for (pos = inbound_list.begin(), i_idx = 0; pos != inbound_list.end(); pos++, i_idx++) - { - /* each entry has 20 bytes */ - readBuffer2[8 + (20 * j_idx)] = ' '; - inbound_ptr = (inbound *)pos->second; - - readBuffer2[8 + (20 * j_idx)] = inbound_ptr->mod; - strcpy((char *)readBuffer2 + 9 + (20 * j_idx), inbound_ptr->call); - - readBuffer2[17 + (20 * j_idx)] = 0; - /* readBuffer2[18 + (20 * j_idx)] = 0; */ readBuffer2[18 + (20 * j_idx)] = inbound_ptr->client; - readBuffer2[19 + (20 * j_idx)] = 0; - readBuffer2[20 + (20 * j_idx)] = 0x0d; - readBuffer2[21 + (20 * j_idx)] = 0x4d; - readBuffer2[22 + (20 * j_idx)] = 0x37; - readBuffer2[23 + (20 * j_idx)] = 0x4d; - readBuffer2[24 + (20 * j_idx)] = 0x6f; - readBuffer2[25 + (20 * j_idx)] = 0x98; - readBuffer2[26 + (20 * j_idx)] = 0x04; - readBuffer2[27 + (20 * j_idx)] = 0; - - j_idx++; - - if (j_idx == 39) - { - /* 20 bytes for each user, so 39 * 20 = 788 bytes + 8 bytes header = 788 */ - readBuffer2[0] = 0x14; - readBuffer2[1] = 0xc3; - - k_idx = i_idx - 38; - memcpy(tmp, (char *)&k_idx, 2); - readBuffer2[4] = tmp[0]; - readBuffer2[5] = tmp[1]; - - sendto(ref_g2_sock,(char *)readBuffer2,788,0, - (struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - - j_idx = 0; - } - } - - if (j_idx != 0) - { - k_idx = 8 + (j_idx * 20); - memcpy(tmp, (char *)&k_idx, 2); - readBuffer2[0] = tmp[0]; - readBuffer2[1] = tmp[1] | 0xc0; - - if (i_idx > j_idx) - k_idx = i_idx - j_idx; - else - k_idx = 0; - - memcpy(tmp, (char *)&k_idx, 2); - readBuffer2[4] = tmp[0]; - readBuffer2[5] = tmp[1]; - - sendto(ref_g2_sock,(char *)readBuffer2, 8 + (j_idx * 20), 0, - (struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - } - } - } - else - /* date request */ - if ((recvlen2 == 4) && - (readBuffer2[0] == 4) && - (readBuffer2[1] == 192) && - (readBuffer2[2] == 8) && - (readBuffer2[3] == 0)) - { - time_t ltime; - struct tm tm; - - pos = inbound_list.find(ip); - if (pos != inbound_list.end()) - { - inbound_ptr = (inbound *)pos->second; - // traceit("Remote station %s %s requested date\n", inbound_ptr->call, ip); - - time(<ime); - localtime_r(<ime,&tm); - - readBuffer2[0] = 34; - readBuffer2[1] = 192; - readBuffer2[2] = 8; - readBuffer2[3] = 0; - readBuffer2[4] = 0xb5; - readBuffer2[5] = 0xae; - readBuffer2[6] = 0x37; - readBuffer2[7] = 0x4d; - snprintf((char *)readBuffer2 + 8, 1024 - 1, - "20%02d/%02d/%02d %02d:%02d:%02d %5.5s", - tm.tm_year % 100, tm.tm_mon+1,tm.tm_mday, - tm.tm_hour,tm.tm_min,tm.tm_sec, - (tzname[0] == NULL)?" ":tzname[0]); - - sendto(ref_g2_sock,(char *)readBuffer2,34,0, - (struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - } - } - else - /* version request */ - if ((recvlen2 == 4) && - (readBuffer2[0] == 4) && - (readBuffer2[1] == 192) && - (readBuffer2[2] == 3) && - (readBuffer2[3] == 0)) - { - pos = inbound_list.find(ip); - if (pos != inbound_list.end()) - { - inbound_ptr = (inbound *)pos->second; - // traceit("Remote station %s %s requested version\n", inbound_ptr->call, ip); - - readBuffer2[0] = 9; - readBuffer2[1] = 192; - readBuffer2[2] = 3; - readBuffer2[3] = 0; - strncpy((char *)readBuffer2 + 4, VERSION, 4); - readBuffer2[8] = 0; - - sendto(ref_g2_sock,(char *)readBuffer2,9,0, - (struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - } - } - else - if ((recvlen2 == 5) && - (readBuffer2[0] == 5) && - (readBuffer2[1] == 0) && - (readBuffer2[2] == 24) && - (readBuffer2[3] == 0) && - (readBuffer2[4] == 0)) - { - /* reply with the same DISCONNECT */ - sendto(ref_g2_sock,(char *)readBuffer2,5,0, - (struct sockaddr *)&fromDst4, - sizeof(struct sockaddr_in)); - - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) - { - traceit("Call %s disconnected\n", to_remote_g2[i].to_call); - - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - } - } - - pos = inbound_list.find(ip); - if (pos != inbound_list.end()) - { - inbound_ptr = (inbound *)pos->second; - if (memcmp(inbound_ptr->call, "1NFO", 4) != 0) - traceit("Call %s disconnected\n", inbound_ptr->call); - free(pos->second); - pos->second = NULL; - inbound_list.erase(pos); - } - print_status_file(); - } - - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) - { - found = true; - if ((recvlen2 == 5) && - (readBuffer2[0] == 5) && - (readBuffer2[1] == 0) && - (readBuffer2[2] == 24) && - (readBuffer2[3] == 0) && - (readBuffer2[4] == 1)) - { - traceit("Connected to call %s\n", to_remote_g2[i].to_call); - queryCommand[0] = 28; - queryCommand[1] = 192; - queryCommand[2] = 4; - queryCommand[3] = 0; - - memcpy(queryCommand + 4, LOGIN_CALL, CALL_SIZE); - for (j = 11; j > 3; j--) - { - if (queryCommand[j] == ' ') - queryCommand[j] = '\0'; - else - break; - } - memset(queryCommand + 12, '\0', 8); - memcpy(queryCommand + 20, "DV019999", 8); - - /*** ATTENTION: I should ONLY send once for each distinct - remote IP, so get out of the loop immediately - ***/ - sendto(ref_g2_sock,(char *)queryCommand,28,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - - break; - } - } - } - - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) - { - found = true; - if ((recvlen2 == 8) && - (readBuffer2[0] == 8) && - (readBuffer2[1] == 192) && - (readBuffer2[2] == 4) && - (readBuffer2[3] == 0)) - { - if ((readBuffer2[4] == 79) && - (readBuffer2[5] == 75) && - (readBuffer2[6] == 82)) - { - if (!to_remote_g2[i].is_connected) - { - to_remote_g2[i].is_connected = true; - to_remote_g2[i].countdown = TIMEOUT; - traceit("Login OK to call %s mod %c\n", - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - print_status_file(); - - tracing[i].last_time = time(NULL); - - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - } - } - else - if ((readBuffer2[4] == 70) && - (readBuffer2[5] == 65) && - (readBuffer2[6] == 73) && - (readBuffer2[7] == 76)) - { - traceit("Login failed to call %s mod %c\n", - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - - sprintf(notify_msg, "%c_failed_linked.dat_FAILED_TO_LINK", - to_remote_g2[i].from_mod); - audio_notify(notify_msg); - - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - } - else - if ((readBuffer2[4] == 66) && - (readBuffer2[5] == 85) && - (readBuffer2[6] == 83) && - (readBuffer2[7] == 89)) - { - traceit("Busy or unknown status from call %s mod %c\n", - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - - sprintf(notify_msg, "%c_failed_linked.dat_FAILED_TO_LINK", - to_remote_g2[i].from_mod); - audio_notify(notify_msg); - - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - } - } - } - } - - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) - { - found = true; - if ((recvlen2 == 24) && - (readBuffer2[0] == 24) && - (readBuffer2[1] == 192) && - (readBuffer2[2] == 3) && - (readBuffer2[3] == 0)) - { - j = i; - to_remote_g2[i].countdown = TIMEOUT; - } - } - } - - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) - { - found = true; - if (recvlen2 == 3) - to_remote_g2[i].countdown = TIMEOUT; - } - } - - /* find out if it is a connected dongle */ - pos = inbound_list.find(ip); - if (pos != inbound_list.end()) - { - inbound_ptr = (inbound *)pos->second; - found = true; - inbound_ptr->countdown = TIMEOUT; - /*** ip is same, do not update port - memcpy((char *)&(inbound_ptr->sin),(char *)&fromDst4, sizeof(struct sockaddr_in)); - ***/ - } - - if (!found) - { - /* - The incoming packet is not in the list of outbound repeater connections. - and it is not a connected dongle. - In this case, this must be an INCOMING dongle request - */ - if ((recvlen2 == 5) && - (readBuffer2[0] == 5) && - (readBuffer2[1] == 0) && - (readBuffer2[2] == 24) && - (readBuffer2[3] == 0) && - (readBuffer2[4] == 1)) - { - if ((inbound_list.size() + 1) > MAX_DONGLES) - traceit("Inbound DONGLE-p connection from %s but over the MAX_DONGLES limit of %d\n", - ip, inbound_list.size()); - else - sendto(ref_g2_sock,(char *)readBuffer2,5,0, - (struct sockaddr *)&fromDst4, - sizeof(fromDst4)); - } - else - if ((recvlen2 == 28) && - (readBuffer2[0] == 28) && - (readBuffer2[1] == 192) && - (readBuffer2[2] == 4) && - (readBuffer2[3] == 0)) - { - /* verify callsign */ - memcpy(call, readBuffer2 + 4, CALL_SIZE); - call[CALL_SIZE] = '\0'; - for (i = 7; i > 0; i--) - { - if (call[i] == '\0') - call[i] = ' '; - else - break; - } - - if (memcmp(call, "1NFO", 4) != 0) - traceit("Inbound DONGLE-p CALL=%s, ip=%s, DV=%.8s\n", - call, ip, readBuffer2 + 20); - - if ((inbound_list.size() + 1) > MAX_DONGLES) - traceit("Inbound DONGLE-p connection from %s but over the MAX_DONGLES limit of %d\n", - ip, inbound_list.size()); - else - if (ONLY_ADMIN_LOGIN && (admin.find(call) == admin.end())) - traceit("Incoming call [%s] from %s not an ADMIN\n", call, ip); - else - if (regexec(&preg, call, 0, NULL, 0) != 0) - { - traceit("Invalid dongle callsign: CALL=%s,ip=%s\n", call, ip); - - readBuffer2[0] = 8; - readBuffer2[4] = 70; - readBuffer2[5] = 65; - readBuffer2[6] = 73; - readBuffer2[7] = 76; - - sendto(ref_g2_sock,(char *)readBuffer2,8,0, - (struct sockaddr *)&fromDst4, - sizeof(fromDst4)); - } - else - { - /* add the dongle to the inbound list */ - inbound_ptr = (inbound *)malloc(sizeof(inbound)); - if (inbound_ptr) - { - inbound_ptr->countdown = TIMEOUT; - memcpy((char *)&(inbound_ptr->sin),(char *)&fromDst4, sizeof(struct sockaddr_in)); - strcpy(inbound_ptr->call, call); - - inbound_ptr->mod = ' '; - - if (memcmp(readBuffer2 + 20, "AP", 2) == 0) - inbound_ptr->client = 'A'; /* dvap */ - else - if (memcmp(readBuffer2 + 20, "DV019999", 8) == 0) - inbound_ptr->client = 'H'; /* spot */ - else - inbound_ptr->client = 'D'; /* dongle */ - - insert_pair = inbound_list.insert(pair(ip, inbound_ptr)); - if (insert_pair.second) - { - if (memcmp(inbound_ptr->call, "1NFO", 4) != 0) - traceit("new CALL=%s, DONGLE-p, ip=%s, users=%d\n", - inbound_ptr->call,ip,inbound_list.size()); - - readBuffer2[0] = 8; - readBuffer2[4] = 79; - readBuffer2[5] = 75; - readBuffer2[6] = 82; - readBuffer2[7] = 87; - - sendto(ref_g2_sock,(char *)readBuffer2,8,0, - (struct sockaddr *)&fromDst4, - sizeof(fromDst4)); - - print_status_file(); - - } - else - { - traceit("failed to add CALL=%s,ip=%s\n",inbound_ptr->call,ip); - free(inbound_ptr); - inbound_ptr = NULL; - - readBuffer2[0] = 8; - readBuffer2[4] = 70; - readBuffer2[5] = 65; - readBuffer2[6] = 73; - readBuffer2[7] = 76; - - sendto(ref_g2_sock,(char *)readBuffer2,8,0, - (struct sockaddr *)&fromDst4, - sizeof(fromDst4)); - } - } - else - { - traceit("malloc() failed for call=%s,ip=%s\n",call,ip); - - readBuffer2[0] = 8; - readBuffer2[4] = 70; - readBuffer2[5] = 65; - readBuffer2[6] = 73; - readBuffer2[7] = 76; - - sendto(ref_g2_sock,(char *)readBuffer2,8,0, - (struct sockaddr *)&fromDst4, - sizeof(fromDst4)); - } - } - } - } - - if ( ((recvlen2 == 58) || - (recvlen2 == 29) || - (recvlen2 == 32)) && - (memcmp(readBuffer2 + 2, "DSVT", 4) == 0) && - ((readBuffer2[6] == 0x10) || - (readBuffer2[6] == 0x20)) && - (readBuffer2[10] == 0x20)) - { - /* Is it one of the donglers or repeaters-reflectors */ - found = false; - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) - { - to_remote_g2[i].countdown = TIMEOUT; - found = true; - } - } - if (!found) - { - pos = inbound_list.find(ip); - if (pos != inbound_list.end()) - { - inbound_ptr = (inbound *)pos->second; - inbound_ptr->countdown = TIMEOUT; - found = true; - } - } - - if ((recvlen2 == 58) && found) - { - memset(source_stn, ' ', 9); source_stn[8] = '\0'; - - /* some bad hotspot programs out there using INCORRECT flag */ - if (readBuffer2[17] == 0x40) - readBuffer2[17] = 0x00; - else - if (readBuffer2[17] == 0x48) - readBuffer2[17] = 0x08; - else - if (readBuffer2[17] == 0x60) - readBuffer2[17] = 0x20; - else - if (readBuffer2[17] == 0x68) - readBuffer2[17] = 0x28; - - /* A reflector will send to us its own RPT1 */ - /* A repeater will send to us its own RPT1 */ - /* A dongleR will send to us our RPT1 */ - - /* It is from a repeater-reflector, correct rpt1, rpt2 and re-compute pfcs */ - for (i = 0; i < 3; i++) - { - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) && - ( - ((memcmp(readBuffer2 + 20, to_remote_g2[i].to_call, 7) == 0) && - (readBuffer2[27] == to_remote_g2[i].to_mod)) || - ((memcmp(readBuffer2 + 28, to_remote_g2[i].to_call, 7) == 0) && - (readBuffer2[35] == to_remote_g2[i].to_mod)) - )) - { - memcpy(&readBuffer2[20], OWNER, CALL_SIZE); - readBuffer2[27] = to_remote_g2[i].from_mod; - memcpy(&readBuffer2[36], "CQCQCQ ", 8); - - memcpy(source_stn, to_remote_g2[i].to_call, 8); source_stn[7] = to_remote_g2[i].to_mod; - - break; - } - } - - if (i == 3) - { - pos = inbound_list.find(ip); - if (pos != inbound_list.end()) - { - inbound_ptr = (inbound *)pos->second; - memcpy(source_stn, inbound_ptr->call, 8); - } - } - - /* somebody's crazy idea of having a personal callsign in RPT2 */ - /* we must set it to our gateway callsign */ - memcpy(&readBuffer2[28], OWNER, CALL_SIZE); - readBuffer2[35] = 'G'; - calcPFCS(readBuffer2 + 2,56); - - /* At this point, all data have our RPT1 and RPT2 */ - - i = -1; - if (readBuffer2[27] == 'A') - i = 0; - else - if (readBuffer2[27] == 'B') - i = 1; - else - if (readBuffer2[27] == 'C') - i = 2; - - /* are we sure that RPT1 is our system? */ - if ((memcmp(readBuffer2 + 20, OWNER, 7) == 0) && (i >= 0)) - { - /* Last Heard */ - if (memcmp(old_sid[i].sid, readBuffer2 + 14, 2) != 0) - { - if (QSO_DETAILS) - traceit("START from remote g2: streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s, source=%.8s\n", - readBuffer2[14],readBuffer2[15], - readBuffer2[17], readBuffer2[18], readBuffer2[19], - &readBuffer2[44], - &readBuffer2[52], &readBuffer2[36], - &readBuffer2[20], &readBuffer2[28], - recvlen2,inet_ntoa(fromDst4.sin_addr), source_stn); - - // put user into tmp1 - memcpy(tmp1, readBuffer2 + 44, 8); tmp1[8] = '\0'; - - // delete the user if exists - for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) - { - if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) - { - dt_lh_list.erase(dt_lh_pos); - break; - } - } - /* Limit?, delete oldest user */ - if (dt_lh_list.size() == LH_MAX_SIZE) - { - dt_lh_pos = dt_lh_list.begin(); - dt_lh_list.erase(dt_lh_pos); - } - // add user - time(&tnow); - sprintf(tmp2, "%ld=r%.6s%c%c", tnow, source_stn, source_stn[7], readBuffer2[27]); - dt_lh_list[tmp2] = tmp1; - - memcpy(old_sid[i].sid, readBuffer2 + 14, 2); - } - - /* send the data to the local gateway/repeater */ - sendto(rptr_sock, (char *)readBuffer2 + 2,56,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - - /* send the data to the donglers */ - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - if (fromDst4.sin_addr.s_addr != inbound_ptr->sin.sin_addr.s_addr) - { - sendto(ref_g2_sock, (char *)readBuffer2, 58, 0, - (struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - } - else - inbound_ptr->mod = readBuffer2[27]; - } - - if ((to_remote_g2[i].toDst4.sin_addr.s_addr != fromDst4.sin_addr.s_addr) && - to_remote_g2[i].is_connected) - { - if ( /*** (memcmp(readBuffer2 + 44, OWNER, 8) != 0) && ***/ /* block repeater announcements */ - (memcmp(readBuffer2 + 36, "CQCQCQ", 6) == 0) && /* CQ calls only */ - ((readBuffer2[17] == 0x00) || /* normal */ - (readBuffer2[17] == 0x08) || /* EMR */ - (readBuffer2[17] == 0x20) || /* BK */ - (readBuffer2[17] == 0x28)) && /* EMR + BK */ - (memcmp(readBuffer2 + 28, OWNER, 7) == 0) && /* rpt2 must be us */ - (readBuffer2[35] == 'G')) - { - to_remote_g2[i].in_streamid[0] = readBuffer2[14]; - to_remote_g2[i].in_streamid[1] = readBuffer2[15]; - - if ((to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) || - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) - { - memcpy((char *)readBuffer2 + 20, to_remote_g2[i].to_call, CALL_SIZE); - readBuffer2[27] = to_remote_g2[i].to_mod; - memcpy((char *)readBuffer2 + 28, to_remote_g2[i].to_call, CALL_SIZE); - readBuffer2[35] = 'G'; - calcPFCS(readBuffer2 + 2, 56); - - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) - { - /* inform XRF about the source */ - readBuffer2[13] = to_remote_g2[i].from_mod; - - sendto(xrf_g2_sock, (char *)readBuffer2 + 2, 56, 0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - else - sendto(ref_g2_sock, (char *)readBuffer2, 58, 0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - memcpy(ref_2_dcs[i].mycall, readBuffer2 + 44, 8); - memcpy(ref_2_dcs[i].sfx, readBuffer2 + 52, 4); - ref_2_dcs[i].dcs_rptr_seq = 0; - } - } - } - } - } - else - if (found) - { - if ((readBuffer2[16] & 0x40) != 0) - { - for (i = 0; i < 3; i++) - { - if (memcmp(old_sid[i].sid, readBuffer2 + 14, 2) == 0) - { - if (QSO_DETAILS) - traceit("END from remote g2: streamID=%d,%d, %d bytes from IP=%s\n", - readBuffer2[14],readBuffer2[15],recvlen2,inet_ntoa(fromDst4.sin_addr)); - - memset(old_sid[i].sid, 0x00, 2); - - break; - } - } - } - - /* send the data to the local gateway/repeater */ - sendto(rptr_sock, (char *)readBuffer2 + 2,27,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - - /* send the data to the donglers */ - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - if (fromDst4.sin_addr.s_addr != inbound_ptr->sin.sin_addr.s_addr) - { - sendto(ref_g2_sock, (char *)readBuffer2, 29, 0, - (struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - } - } - - for (i = 0; i < 3; i++) - { - if ((to_remote_g2[i].is_connected) && - (to_remote_g2[i].toDst4.sin_addr.s_addr != fromDst4.sin_addr.s_addr) && - (memcmp(to_remote_g2[i].in_streamid, readBuffer2 + 14, 2) == 0)) - { - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) - { - /* inform XRF about the source */ - readBuffer2[13] = to_remote_g2[i].from_mod; - - sendto(xrf_g2_sock, (char *)readBuffer2 + 2, 27, 0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) - sendto(ref_g2_sock, (char *)readBuffer2, 29, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - memset(dcs_buf, 0x00, 600); - dcs_buf[0] = dcs_buf[1] = dcs_buf[2] = '0'; - dcs_buf[3] = '1'; - dcs_buf[4] = dcs_buf[5] = dcs_buf[6] = 0x00; - memcpy(dcs_buf + 7, to_remote_g2[i].to_call, 8); - dcs_buf[14] = to_remote_g2[i].to_mod; - memcpy(dcs_buf + 15, OWNER, 8); - dcs_buf[22] = to_remote_g2[i].from_mod; - memcpy(dcs_buf + 23, "CQCQCQ ", 8); - memcpy(dcs_buf + 31, ref_2_dcs[i].mycall, 8); - memcpy(dcs_buf + 39, ref_2_dcs[i].sfx, 4); - dcs_buf[43] = readBuffer2[14]; /* streamid0 */ - dcs_buf[44] = readBuffer2[15]; /* streamid1 */ - dcs_buf[45] = readBuffer2[16]; /* cycle sequence */ - memcpy(dcs_buf + 46, readBuffer2 + 17, 12); - - dcs_buf[58] = (ref_2_dcs[i].dcs_rptr_seq >> 0) & 0xff; - dcs_buf[59] = (ref_2_dcs[i].dcs_rptr_seq >> 8) & 0xff; - dcs_buf[60] = (ref_2_dcs[i].dcs_rptr_seq >> 16) & 0xff; - - ref_2_dcs[i].dcs_rptr_seq ++; - - dcs_buf[61] = 0x01; - dcs_buf[62] = 0x00; - - sendto(dcs_g2_sock, dcs_buf, 100, 0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - - if ((readBuffer2[16] & 0x40) != 0) - { - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - } - break; - } - } - } - } - FD_CLR (ref_g2_sock,&fdset); - } - - if (FD_ISSET(dcs_g2_sock, &fdset)) - { - fromlen = sizeof(struct sockaddr_in); - recvlen2 = recvfrom(dcs_g2_sock,(char *)dcs_buf,1000, - 0,(struct sockaddr *)&fromDst4,&fromlen); - - strncpy(ip, inet_ntoa(fromDst4.sin_addr),IP_SIZE); - ip[IP_SIZE] = '\0'; - - /* header, audio */ - if ((dcs_buf[0] == '0') && (dcs_buf[1] == '0') && - (dcs_buf[2] == '0') && (dcs_buf[3] == '1')) - { - if (recvlen2 == 100) - { - memset(source_stn, ' ', 9); source_stn[8] = '\0'; - - /* find out our local module */ - for (i = 0; i < 3; i++) - { - if ((to_remote_g2[i].is_connected) && - (fromDst4.sin_addr.s_addr = to_remote_g2[i].toDst4.sin_addr.s_addr) && - (memcmp(dcs_buf + 7, to_remote_g2[i].to_call, 7) == 0) && - (to_remote_g2[i].to_mod == dcs_buf[14])) - { - memcpy(source_stn, to_remote_g2[i].to_call, 8); source_stn[7] = to_remote_g2[i].to_mod; - break; - } - } - - /* Is it our local module */ - if (i < 3) - { - /* Last Heard */ - if (memcmp(old_sid[i].sid, dcs_buf + 43, 2) != 0) - { - if (QSO_DETAILS) - traceit("START from dcs: streamID=%d,%d, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s, source=%.8s\n", - dcs_buf[43],dcs_buf[44], - &dcs_buf[31], - &dcs_buf[39], &dcs_buf[23], - &dcs_buf[7], &dcs_buf[15], - recvlen2,inet_ntoa(fromDst4.sin_addr), source_stn); - - // put user into tmp1 - memcpy(tmp1, dcs_buf + 31, 8); tmp1[8] = '\0'; - - // delete the user if exists - for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) - { - if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) - { - dt_lh_list.erase(dt_lh_pos); - break; - } - } - /* Limit?, delete oldest user */ - if (dt_lh_list.size() == LH_MAX_SIZE) - { - dt_lh_pos = dt_lh_list.begin(); - dt_lh_list.erase(dt_lh_pos); - } - // add user - time(&tnow); - sprintf(tmp2, "%ld=r%.6s%c%c", tnow, source_stn, source_stn[7], to_remote_g2[i].from_mod); - dt_lh_list[tmp2] = tmp1; - - memcpy(old_sid[i].sid, dcs_buf + 43, 2); - } - - to_remote_g2[i].countdown = TIMEOUT; - - /* new stream ? */ - if ((to_remote_g2[i].in_streamid[0] != dcs_buf[43]) || - (to_remote_g2[i].in_streamid[1] != dcs_buf[44])) - { - to_remote_g2[i].in_streamid[0] = dcs_buf[43]; - to_remote_g2[i].in_streamid[1] = dcs_buf[44]; - dcs_seq[i] = 0xff; - - /* generate our header */ - - readBuffer2[0] = (unsigned char)(58 & 0xFF); - readBuffer2[1] = (unsigned char)(58 >> 8 & 0x1F); - readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); - memcpy(readBuffer2 + 2, "DSVT", 4); - readBuffer2[6] = 0x10; - readBuffer2[7] = 0x00; - readBuffer2[8] = 0x00; - readBuffer2[9] = 0x00; - readBuffer2[10] = 0x20; - readBuffer2[11] = 0x00; - readBuffer2[12] = 0x01; - if (to_remote_g2[i].from_mod == 'A') - readBuffer2[13] = 0x03; - else - if (to_remote_g2[i].from_mod == 'B') - readBuffer2[13] = 0x01; - else - readBuffer2[13] = 0x02; - readBuffer2[14] = dcs_buf[43]; - readBuffer2[15] = dcs_buf[44]; - readBuffer2[16] = 0x80; - readBuffer2[17] = readBuffer2[18] = readBuffer2[19] = 0x00; - memcpy(readBuffer2 + 20, OWNER, 8); - readBuffer2[27] = to_remote_g2[i].from_mod; - memcpy(readBuffer2 + 28, OWNER, 8); - readBuffer2[35] = 'G'; - memcpy(readBuffer2 + 36, "CQCQCQ ", 8); - memcpy(readBuffer2 + 44, dcs_buf + 31, 8); - memcpy(readBuffer2 + 52, dcs_buf + 39, 4); - calcPFCS(readBuffer2 + 2, 56); - - /* send the header to the local gateway/repeater */ - for (j = 0; j < 5; j++) - sendto(rptr_sock, (char *)readBuffer2 + 2, 56,0, - (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - - /* send the data to the donglers */ - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - for (j = 0; j < 5; j++) - { - sendto(ref_g2_sock, (char *)readBuffer2, 58, 0, - (struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - } - } - } - - if ((to_remote_g2[i].in_streamid[0] == dcs_buf[43]) && - (to_remote_g2[i].in_streamid[1] == dcs_buf[44]) && - (dcs_seq[i] != dcs_buf[45])) - { - dcs_seq[i] = dcs_buf[45]; - - readBuffer2[0] = (unsigned char)(29 & 0xFF); - readBuffer2[1] = (unsigned char)(29 >> 8 & 0x1F); - readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); - memcpy(readBuffer2 + 2, "DSVT", 4); - readBuffer2[6] = 0x20; - readBuffer2[7] = 0x00; - readBuffer2[8] = 0x00; - readBuffer2[9] = 0x00; - readBuffer2[10] = 0x20; - readBuffer2[11] = 0x00; - readBuffer2[12] = 0x01; - if (to_remote_g2[i].from_mod == 'A') - readBuffer2[13] = 0x03; - else - if (to_remote_g2[i].from_mod == 'B') - readBuffer2[13] = 0x01; - else - readBuffer2[13] = 0x02; - readBuffer2[14] = dcs_buf[43]; - readBuffer2[15] = dcs_buf[44]; - readBuffer2[16] = dcs_buf[45]; - memcpy(readBuffer2 + 17, dcs_buf + 46, 12); - - /* send the data to the local gateway/repeater */ - sendto(rptr_sock, (char *)readBuffer2 + 2, 27,0, - (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - - /* send the data to the donglers */ - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - sendto(ref_g2_sock, (char *)readBuffer2, 29, 0, - (struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - } - - if ((dcs_buf[45] & 0x40) != 0) - { - memset(old_sid[i].sid, 0x00, 2); - - if (QSO_DETAILS) - traceit("END from dcs: streamID=%d,%d, %d bytes from IP=%s\n", - dcs_buf[43],dcs_buf[44], recvlen2,inet_ntoa(fromDst4.sin_addr)); - - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - dcs_seq[i] = 0xff; - } - } - } - } - } - else - if ((dcs_buf[0] == 'E') && (dcs_buf[1] == 'E') && - (dcs_buf[2] == 'E') && (dcs_buf[3] == 'E')) - ; - else - if (recvlen2 == 35) - ; - else - /* is this a keepalive 22 bytes */ - if (recvlen2 == 22) - { - i = -1; - if (dcs_buf[17] == 'A') - i = 0; - else - if (dcs_buf[17] == 'B') - i = 1; - else - if (dcs_buf[17] == 'C') - i = 2; - - /* It is one of our valid repeaters */ - // DG1HT from OWNER 8 to 7 - if ((i >= 0) && (memcmp(dcs_buf + 9, OWNER, 7) == 0)) - { - /* is that the remote system that we asked to connect to? */ - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) && - (memcmp(to_remote_g2[i].to_call, dcs_buf, 7) == 0) && - (to_remote_g2[i].to_mod == dcs_buf[7])) - { - if (!to_remote_g2[i].is_connected) - { - tracing[i].last_time = time(NULL); - - to_remote_g2[i].is_connected = true; - traceit("Connected from: %.*s\n", 8, dcs_buf); - print_status_file(); - - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - } - to_remote_g2[i].countdown = TIMEOUT; - } - } - } - /* is this a reply to our link/unlink request: 14 bytes */ - else - if (recvlen2 == 14) - { - i = -1; - if (dcs_buf[8] == 'A') - i = 0; - else - if (dcs_buf[8] == 'B') - i = 1; - else - if (dcs_buf[8] == 'C') - i = 2; - - /* It is one of our valid repeaters */ - if ((i >= 0) && (memcmp(dcs_buf, OWNER, 8) == 0)) - { - /* It is from a remote that we contacted */ - if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) && - (to_remote_g2[i].from_mod == dcs_buf[8])) - { - if ((to_remote_g2[i].to_mod == dcs_buf[9]) && - (memcmp(dcs_buf + 10, "ACK", 3) == 0)) - { - to_remote_g2[i].countdown = TIMEOUT; - if (!to_remote_g2[i].is_connected) - { - tracing[i].last_time = time(NULL); - - to_remote_g2[i].is_connected = true; - traceit("Connected from: %.*s\n", 8, to_remote_g2[i].to_call); - print_status_file(); - - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - } - } - else - if (memcmp(dcs_buf + 10, "NAK", 3) == 0) - { - traceit("Link module %c to [%s] %c is unlinked\n", - to_remote_g2[i].from_mod, to_remote_g2[i].to_call, - to_remote_g2[i].to_mod); - - sprintf(notify_msg, "%c_failed_linked.dat_UNLINKED", - to_remote_g2[i].from_mod); - audio_notify(notify_msg); - - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - - print_status_file(); - } - } - } - } - FD_CLR (dcs_g2_sock,&fdset); - } - - if (FD_ISSET(rptr_sock, &fdset)) - { - fromlen = sizeof(struct sockaddr_in); - recvlen = recvfrom(rptr_sock,(char *)readBuffer,100, - 0,(struct sockaddr *)&fromRptr,&fromlen); - - if ( ((recvlen == 58) || - (recvlen == 29) || - (recvlen == 32)) && - (readBuffer[6] == 0x73) && - (readBuffer[7] == 0x12) && - ((memcmp(readBuffer,"DSTR", 4) == 0) || (memcmp(readBuffer,"CCS_", 4) == 0)) && - (readBuffer[10] == 0x20) && - (readBuffer[8] == 0x00) && - ((readBuffer[9] == 0x30) || - (readBuffer[9] == 0x13) || - (readBuffer[9] == 0x16)) ) - { - - if (recvlen == 58) - { - if (QSO_DETAILS) - traceit("START from local g2: cntr=%02x %02x, streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s\n", - readBuffer[4], readBuffer[5], - readBuffer[14], readBuffer[15], - readBuffer[17], readBuffer[18], readBuffer[19], - readBuffer + 44, readBuffer + 52, readBuffer + 36, - readBuffer + 28, readBuffer + 20, recvlen, inet_ntoa(fromRptr.sin_addr)); - - /* save mycall */ - memcpy(call, readBuffer + 44, 8); - call[8] = '\0'; - - i = -1; - if (readBuffer[35] == 'A') - i = 0; - else - if (readBuffer[35] == 'B') - i = 1; - else - if (readBuffer[35] == 'C') - i = 2; - - if (i >= 0) - { - memcpy(dtmf_mycall[i], readBuffer + 44, 8); - dtmf_mycall[i][8] = '\0'; - - new_group[i] = true; - GPS_seen[i] = false; - - /* Last Heard */ - - //put user into tmp1 - memcpy(tmp1, readBuffer + 44, 8); tmp1[8] = '\0'; - - // delete the user if exists - for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) - { - if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) - { - dt_lh_list.erase(dt_lh_pos); - break; - } - } - /* Limit?, delete oldest user */ - if (dt_lh_list.size() == LH_MAX_SIZE) - { - dt_lh_pos = dt_lh_list.begin(); - dt_lh_list.erase(dt_lh_pos); - } - /* add user */ - time(&tnow); - if (memcmp(readBuffer,"CCS_", 4) == 0) - sprintf(tmp2, "%ld=r%.7s%c", tnow, "-->CCS ", readBuffer[35]); - else - sprintf(tmp2, "%ld=l%.8s", tnow, readBuffer + 28); - dt_lh_list[tmp2] = tmp1; - - memcpy(readBuffer, "DSTR", 4); - - tracing[i].streamid[0] = readBuffer[14]; - tracing[i].streamid[1] = readBuffer[15]; - tracing[i].last_time = time(NULL); - } - - if ((memcmp(readBuffer + 36, "CQCQCQ", 6) != 0) && (i >= 0)) - { - if ((memcmp(readBuffer + 36, OWNER, 7) != 0) && - (readBuffer[43] == LINK_CODE) && - (memcmp(readBuffer + 20, OWNER, 7) == 0) && - (readBuffer[27] == 'G') && - ((readBuffer[17] == 0x00) || - (readBuffer[17] == 0x08) || - (readBuffer[17] == 0x20) || - (readBuffer[17] == 0x28))) - { - if (ONLY_LINK_UNLINK && - (link_unlink_user.find(call) == link_unlink_user.end())) - { - traceit("link request denied, unauthorized rf user [%s]\n", call); - } - else - { - memset(temp_repeater, ' ', CALL_SIZE); - memcpy(temp_repeater, readBuffer + 36, CALL_SIZE - 2); - temp_repeater[CALL_SIZE] = '\0'; - - if ((to_remote_g2[i].to_call[0] == '\0') || /* not linked */ - ((to_remote_g2[i].to_call[0] != '\0') && /* waiting for a link reply that may never arrive */ - !to_remote_g2[i].is_connected)) - - g2link(readBuffer[35], temp_repeater, readBuffer[42]); - else - if (to_remote_g2[i].is_connected) - { - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_already_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - } - } - } - else - if ((readBuffer[43] == UNLINK_CODE) && - (readBuffer[36] == ' ')) - { - if (ONLY_LINK_UNLINK && - (link_unlink_user.find(call) == link_unlink_user.end())) - { - traceit("unlink request denied, unauthorized rf user [%s]\n", call); - } - else - { - if (to_remote_g2[i].to_call[0] != '\0') - { - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) - { - /* Check to see if any other local bands are linked to that same IP */ - for (j = 0; j < 3; j++) - { - if (j != i) - { - if ((to_remote_g2[j].toDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && - (to_remote_g2[j].toDst4.sin_port == htons(RMT_REF_PORT))) - { - traceit("Info: Local %c is also linked to %s (different module) %c\n", - to_remote_g2[j].from_mod, - to_remote_g2[j].to_call, to_remote_g2[j].to_mod); - break; - } - } - } - - if (j == 3) - { - /* nothing else is linked there, send DISCONNECT */ - queryCommand[0] = 5; - queryCommand[1] = 0; - queryCommand[2] = 24; - queryCommand[3] = 0; - queryCommand[4] = 0; - sendto(ref_g2_sock,(char *)queryCommand,5,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) - { - strcpy(unlink_request, OWNER); - unlink_request[8] = to_remote_g2[i].from_mod; - unlink_request[9] = ' '; - unlink_request[10] = '\0'; - - for (j = 0; j < 5; j++) - sendto(xrf_g2_sock,unlink_request, CALL_SIZE + 3,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - else - { - strcpy(cmd_2_dcs, OWNER); - cmd_2_dcs[8] = to_remote_g2[i].from_mod; - cmd_2_dcs[9] = ' '; - cmd_2_dcs[10] = '\0'; - memcpy(cmd_2_dcs + 11, to_remote_g2[i].to_call, 8); - - for (j = 0; j < 5; j++) - sendto(dcs_g2_sock, cmd_2_dcs, 19,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - - traceit("Unlinked from [%s] mod %c\n", - to_remote_g2[i].to_call, to_remote_g2[i].to_mod); - sprintf(notify_msg, "%c_unlinked.dat_UNLINKED", to_remote_g2[i].from_mod); - audio_notify(notify_msg); - - /* now zero out this entry */ - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - - print_status_file(); - } - else - { - sprintf(notify_msg, "%c_already_unlinked.dat_UNLINKED", readBuffer[35]); - audio_notify(notify_msg); - } - } - } - else - if ((readBuffer[43] == INFO_CODE) && - (readBuffer[36] == ' ')) - { - if (to_remote_g2[i].is_connected) - { - strcpy(linked_remote_system, to_remote_g2[i].to_call); - space_p = strchr(linked_remote_system, ' '); - if (space_p) - *space_p = '\0'; - sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", - to_remote_g2[i].from_mod, - linked_remote_system, - to_remote_g2[i].to_mod); - audio_notify(notify_msg); - } - else - { - sprintf(notify_msg, "%c_id.dat_%s_NOT_LINKED", readBuffer[35], OWNER); - audio_notify(notify_msg); - } - } - else - if ((readBuffer[43] == EXEC_CODE) && - (readBuffer[36] == ' ') && - (admin.find(call) != admin.end())) // only ADMIN can execute scripts - { - if (readBuffer[42] != ' ') - { - memset(system_cmd, '\0', sizeof(system_cmd)); - snprintf(system_cmd, FILENAME_MAX, "%s/exec_%c.sh %s %c &", - ANNOUNCE_DIR, - readBuffer[42], call, readBuffer[35]); - traceit("Executing %s\n", system_cmd); - system(system_cmd); - } - } - else - if ((readBuffer[42] == DONGLE_CODE) && - (readBuffer[36] == ' ') && - (admin.find(call) != admin.end())) // only ADMIN can block dongle users - { - if (readBuffer[43] == '1') - { - MAX_DONGLES = SAVED_MAX_DONGLES; - traceit("Dongle connections are now allowed\n"); - } - else - if (readBuffer[43] == '0') - { - inbound_list.clear(); - MAX_DONGLES = 0; - traceit("Dongle connections are now disallowed\n"); - } - } - else - if ((readBuffer[43] == FILE_REFRESH_GWYS_CODE) && - (readBuffer[36] == ' ') && - (admin.find(call) != admin.end())) // only ADMIN can reload gwys.txt - { - gwy_list.clear(); - load_gwys(GWYS); - } - } - - /* send data to the donglers */ - if (inbound_list.size() > 0) - { - readBuffer2[0] = (unsigned char)(58 & 0xFF); - readBuffer2[1] = (unsigned char)(58 >> 8 & 0x1F); - readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); - - memcpy(readBuffer2 + 2, "DSVT", 4); - readBuffer2[6] = 0x10; - readBuffer2[7] = 0x00; - readBuffer2[8] = 0x00; - readBuffer2[9] = 0x00; - readBuffer2[10] = readBuffer[10]; - readBuffer2[11] = readBuffer[11]; - readBuffer2[12] = readBuffer[12]; - readBuffer2[13] = readBuffer[13]; - memcpy(readBuffer2 + 14, readBuffer + 14, 44); - memcpy(readBuffer2 + 20, OWNER, CALL_SIZE); - readBuffer2[27] = readBuffer[35]; - memcpy(readBuffer2 + 28, OWNER, CALL_SIZE); - readBuffer2[35] = 'G'; - memcpy(&readBuffer2[36], "CQCQCQ ", 8); - - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - for (j = 0; j < 5; j++) - sendto(ref_g2_sock, (char *)readBuffer2, 58, - 0,(struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - } - } - - if (i >= 0) - { - /* do we have to broadcast ? */ - /* make sure the source is linked to xrf */ - if ((to_remote_g2[i].is_connected) && - (memcmp(to_remote_g2[i].to_call, "XRF", 3) == 0) && - /* only CQCQCQ */ - (memcmp(readBuffer + 20, OWNER, 7) == 0) && - (memcmp(readBuffer + 36, "CQCQCQ", 6) == 0) && - (readBuffer[27] == 'G')) - { - brd_from_rptr_idx = 0; - streamid_raw = (readBuffer[14] * 256U) + readBuffer[15]; - - for (j = 0; j < 3; j++) - { - if ((j != i) && - (to_remote_g2[j].is_connected) && - (memcmp(to_remote_g2[j].to_call, to_remote_g2[i].to_call, 8) == 0) && - (to_remote_g2[j].to_mod == to_remote_g2[i].to_mod) && - (to_remote_g2[j].to_mod != 'E')) - { - memcpy(fromrptr_torptr_brd, "DSVT", 4); - fromrptr_torptr_brd[4] = 0x10; - fromrptr_torptr_brd[5] = 0x00; - fromrptr_torptr_brd[6] = 0x00; - fromrptr_torptr_brd[7] = 0x00; - fromrptr_torptr_brd[8] = readBuffer[10]; - fromrptr_torptr_brd[9] = readBuffer[11]; - fromrptr_torptr_brd[10] = readBuffer[12]; - fromrptr_torptr_brd[11] = readBuffer[13]; - memcpy(fromrptr_torptr_brd + 12, readBuffer + 14, 44); - - streamid_raw ++; - if (streamid_raw == 0) - streamid_raw ++; - fromrptr_torptr_brd[12] = streamid_raw / 256U; - fromrptr_torptr_brd[13] = streamid_raw % 256U; - - memcpy(fromrptr_torptr_brd + 18, OWNER, 8); - fromrptr_torptr_brd[25] = to_remote_g2[j].from_mod; - memcpy(fromrptr_torptr_brd + 26, OWNER, 8); - fromrptr_torptr_brd[33] = 'G'; - - memcpy(fromrptr_torptr_brd + 34, "CQCQCQ ", 8); - - calcPFCS(fromrptr_torptr_brd, 56); - - sendto(xrf_g2_sock, (char *)fromrptr_torptr_brd,56,0, - (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - - brd_from_rptr.from_rptr_streamid[0] = readBuffer[14]; - brd_from_rptr.from_rptr_streamid[1] = readBuffer[15]; - brd_from_rptr.to_rptr_streamid[brd_from_rptr_idx][0] = fromrptr_torptr_brd[12]; - brd_from_rptr.to_rptr_streamid[brd_from_rptr_idx][1] = fromrptr_torptr_brd[13]; - brd_from_rptr_idx ++; - } - } - } - - if (to_remote_g2[i].is_connected) - { - if ((memcmp(readBuffer + 20, OWNER, 7) == 0) && - (memcmp(readBuffer + 36, "CQCQCQ", 6) == 0) && - (readBuffer[27] == 'G')) - { - to_remote_g2[i].out_streamid[0] = readBuffer[14]; - to_remote_g2[i].out_streamid[1] = readBuffer[15]; - - if ((to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) || - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) - { - readBuffer2[0] = (unsigned char)(58 & 0xFF); - readBuffer2[1] = (unsigned char)(58 >> 8 & 0x1F); - readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); - - memcpy(readBuffer2 + 2, "DSVT", 4); - readBuffer2[6] = 0x10; - readBuffer2[7] = 0x00; - readBuffer2[8] = 0x00; - readBuffer2[9] = 0x00; - readBuffer2[10] = readBuffer[10]; - readBuffer2[11] = readBuffer[11]; - readBuffer2[12] = readBuffer[12]; - readBuffer2[13] = readBuffer[13]; - memcpy(readBuffer2 + 14, readBuffer + 14, 44); - memset(readBuffer2 + 20, ' ', CALL_SIZE); - memcpy(readBuffer2 + 20, to_remote_g2[i].to_call, - strlen(to_remote_g2[i].to_call)); - readBuffer2[27] = to_remote_g2[i].to_mod; - memset(readBuffer2 + 28, ' ', CALL_SIZE); - memcpy(readBuffer2 + 28, to_remote_g2[i].to_call, - strlen(to_remote_g2[i].to_call)); - readBuffer2[35] = 'G'; - memcpy(&readBuffer2[36], "CQCQCQ ", 8); - - calcPFCS(readBuffer2 + 2,56); - - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) - { - /* inform XRF about the source */ - readBuffer2[13] = to_remote_g2[i].from_mod; - - for (j = 0; j < 5; j++) - sendto(xrf_g2_sock, (char *)readBuffer2 + 2, 56, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - else - { - for (j = 0; j < 5; j++) - sendto(ref_g2_sock, (char *)readBuffer2, 58, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - memcpy(rptr_2_dcs[i].mycall, readBuffer + 44, 8); - memcpy(rptr_2_dcs[i].sfx, readBuffer + 52, 4); - rptr_2_dcs[i].dcs_rptr_seq = 0; - } - } - } - } - } - else - { - if (inbound_list.size() > 0) - { - readBuffer2[0] = (unsigned char)(29 & 0xFF); - readBuffer2[1] = (unsigned char)(29 >> 8 & 0x1F); - readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); - - memcpy(readBuffer2 + 2, "DSVT", 4); - readBuffer2[6] = 0x20; - readBuffer2[7] = 0x00; - readBuffer2[8] = 0x00; - readBuffer2[9] = 0x00; - readBuffer2[10] = readBuffer[10]; - readBuffer2[11] = readBuffer[11]; - readBuffer2[12] = readBuffer[12]; - readBuffer2[13] = readBuffer[13]; - memcpy(readBuffer2 + 14, readBuffer + 14, 3); - if (recvlen == 29) - memcpy(readBuffer2 + 17, readBuffer + 17, 12); - else - memcpy(readBuffer2 + 17, readBuffer + 20, 12); - - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - sendto(ref_g2_sock, (char *)readBuffer2, 29, 0, - (struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - } - } - - for (i = 0; i < 3; i++) - { - if ((to_remote_g2[i].is_connected) && - (memcmp(to_remote_g2[i].out_streamid, readBuffer + 14, 2) == 0)) - { - /* check for broadcast */ - if (memcmp(brd_from_rptr.from_rptr_streamid, readBuffer + 14, 2) == 0) - { - memcpy(fromrptr_torptr_brd, "DSVT", 4); - fromrptr_torptr_brd[4] = 0x10; - fromrptr_torptr_brd[5] = 0x00; - fromrptr_torptr_brd[6] = 0x00; - fromrptr_torptr_brd[7] = 0x00; - fromrptr_torptr_brd[8] = readBuffer[10]; - fromrptr_torptr_brd[9] = readBuffer[11]; - fromrptr_torptr_brd[10] = readBuffer[12]; - fromrptr_torptr_brd[11] = readBuffer[13]; - memcpy(fromrptr_torptr_brd + 12, readBuffer + 14, 3); - - if (recvlen == 29) - memcpy(fromrptr_torptr_brd + 15, readBuffer + 17, 12); - else - memcpy(fromrptr_torptr_brd + 15, readBuffer + 20, 12); - - if ((brd_from_rptr.to_rptr_streamid[0][0] != 0x00) || - (brd_from_rptr.to_rptr_streamid[0][1] != 0x00)) - { - fromrptr_torptr_brd[12] = brd_from_rptr.to_rptr_streamid[0][0]; - fromrptr_torptr_brd[13] = brd_from_rptr.to_rptr_streamid[0][1]; - sendto(xrf_g2_sock, (char *)fromrptr_torptr_brd,27,0, - (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - } - - if ((brd_from_rptr.to_rptr_streamid[1][0] != 0x00) || - (brd_from_rptr.to_rptr_streamid[1][1] != 0x00)) - { - fromrptr_torptr_brd[12] = brd_from_rptr.to_rptr_streamid[1][0]; - fromrptr_torptr_brd[13] = brd_from_rptr.to_rptr_streamid[1][1]; - sendto(xrf_g2_sock, (char *)fromrptr_torptr_brd,27,0, - (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - } - - if ((readBuffer[16] & 0x40) != 0) - { - brd_from_rptr.from_rptr_streamid[0] = brd_from_rptr.from_rptr_streamid[1] = 0x00; - brd_from_rptr.to_rptr_streamid[0][0] = brd_from_rptr.to_rptr_streamid[0][1] = 0x00; - brd_from_rptr.to_rptr_streamid[1][0] = brd_from_rptr.to_rptr_streamid[1][1] = 0x00; - brd_from_rptr_idx = 0; - } - } - - if ((to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) || - (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) - { - readBuffer2[0] = (unsigned char)(29 & 0xFF); - readBuffer2[1] = (unsigned char)(29 >> 8 & 0x1F); - readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); - - memcpy(readBuffer2 + 2, "DSVT", 4); - readBuffer2[6] = 0x20; - readBuffer2[7] = 0x00; - readBuffer2[8] = 0x00; - readBuffer2[9] = 0x00; - readBuffer2[10] = readBuffer[10]; - readBuffer2[11] = readBuffer[11]; - readBuffer2[12] = readBuffer[12]; - readBuffer2[13] = readBuffer[13]; - memcpy(readBuffer2 + 14, readBuffer + 14, 3); - if (recvlen == 29) - memcpy(readBuffer2 + 17, readBuffer + 17, 12); - else - memcpy(readBuffer2 + 17, readBuffer + 20, 12); - - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) - { - /* inform XRF about the source */ - readBuffer2[13] = to_remote_g2[i].from_mod; - - sendto(xrf_g2_sock, (char *)readBuffer2 + 2, 27, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) - sendto(ref_g2_sock, (char *)readBuffer2, 29, - 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(struct sockaddr_in)); - } - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) - { - memset(dcs_buf, 0x00, 600); - dcs_buf[0] = dcs_buf[1] = dcs_buf[2] = '0'; - dcs_buf[3] = '1'; - dcs_buf[4] = dcs_buf[5] = dcs_buf[6] = 0x00; - memcpy(dcs_buf + 7, to_remote_g2[i].to_call, 8); - dcs_buf[14] = to_remote_g2[i].to_mod; - memcpy(dcs_buf + 15, OWNER, 8); - dcs_buf[22] = to_remote_g2[i].from_mod; - memcpy(dcs_buf + 23, "CQCQCQ ", 8); - memcpy(dcs_buf + 31, rptr_2_dcs[i].mycall, 8); - memcpy(dcs_buf + 39, rptr_2_dcs[i].sfx, 4); - dcs_buf[43] = readBuffer[14]; /* streamid0 */ - dcs_buf[44] = readBuffer[15]; /* streamid1 */ - dcs_buf[45] = readBuffer[16]; /* cycle sequence */ - memcpy(dcs_buf + 46, readBuffer + 17, 12); - - dcs_buf[58] = (rptr_2_dcs[i].dcs_rptr_seq >> 0) & 0xff; - dcs_buf[59] = (rptr_2_dcs[i].dcs_rptr_seq >> 8) & 0xff; - dcs_buf[60] = (rptr_2_dcs[i].dcs_rptr_seq >> 16) & 0xff; - - rptr_2_dcs[i].dcs_rptr_seq ++; - - dcs_buf[61] = 0x01; - dcs_buf[62] = 0x00; - - sendto(dcs_g2_sock, dcs_buf, 100, 0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - - if ((readBuffer[16] & 0x40) != 0) - { - to_remote_g2[i].out_streamid[0] = 0x00; - to_remote_g2[i].out_streamid[1] = 0x00; - } - break; - } - } - - for (i = 0; i < 3; i++) - { - if (memcmp(tracing[i].streamid, readBuffer + 14, 2) == 0) - { - /* update the last time RF user talked */ - tracing[i].last_time = time(NULL); - - if ((readBuffer[16] & 0x40) != 0) - { - if (QSO_DETAILS) - traceit("END from local g2: cntr=%02x %02x, streamID=%d,%d, %d bytes\n", - readBuffer[4], readBuffer[5], - readBuffer[14],readBuffer[15],recvlen); - - if (RPTR_ACK) - rptr_ack(i); - - memset(dtmf_mycall[i], 0, sizeof(dtmf_mycall[i])); - new_group[i] = true; - GPS_seen[i] = false; - - tracing[i].streamid[0] = 0x00; - tracing[i].streamid[1] = 0x00; - } - else - { - if (!GPS_seen[i]) - { - if (recvlen == 29) - memcpy(tmp_txt, readBuffer + 26, 3); - else - memcpy(tmp_txt, readBuffer + 29, 3); - - if ((tmp_txt[0] != 0x55) || (tmp_txt[1] != 0x2d) || (tmp_txt[2] != 0x16)) - { - if (new_group[i]) - { - tmp_txt[0] = tmp_txt[0] ^ 0x70; - header_type = tmp_txt[0] & 0xf0; - - if ((header_type == 0x50) || /* header */ - (header_type == 0xc0)) /* squelch */ - new_group[i] = false; - else - if (header_type == 0x30) /* GPS or GPS id or APRS */ - { - GPS_seen[i] = true; - new_group[i] = false; - - memcpy(tmp1, dtmf_mycall[i], 8); tmp1[8] = '\0'; - - // delete the user if exists and it is a local RF entry - p_tmp2 = NULL; - for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) - { - if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) - { - strcpy(tmp2, (char *)dt_lh_pos->first.c_str()); - p_tmp2 = strstr(tmp2, "=l"); - if (p_tmp2) - { - dt_lh_list.erase(dt_lh_pos); - break; - } - } - } - /* we have tmp1 and tmp2, we have the user and it is already been removed */ - /* add the user with gps indicator g */ - if (p_tmp2) - { - *(p_tmp2 + 1) = 'g'; - dt_lh_list[tmp2] = tmp1; - } - } - else - if (header_type == 0x40) /* ABC text */ - new_group[i] = false; - else - new_group[i] = false; - } - else - new_group[i] = true; - } - } - } - break; - } - } - } - } - FD_CLR (rptr_sock,&fdset); - } - } + socklen_t fromlen; + int recvlen; + int recvlen2; + short i,j,k; + char temp_repeater[CALL_SIZE + 1]; + time_t tnow = 0, hb = 0; + int rc = 0; + + char *p = NULL; + + char notify_msg[64]; + char *space_p = 0; + char linked_remote_system[CALL_SIZE + 1]; + char unlink_request[CALL_SIZE + 3]; + + char system_cmd[FILENAME_MAX + 1]; + int max_nfds = 0; + + char tmp1[CALL_SIZE + 1]; + char tmp2[36]; // 8 for rpt1 + 24 for time_t in string format + dt_lh_type::iterator dt_lh_pos; + dt_lh_type::reverse_iterator r_dt_lh_pos; + + gwy_list_type::iterator gwy_pos; + + char call[CALL_SIZE + 1]; + char ip[IP_SIZE + 1]; + inbound *inbound_ptr; + inbound_type::iterator pos; + pair insert_pair; + bool found = false; + set::iterator it; + + char cmd_2_dcs[23]; + unsigned char dcs_seq[3] = { 0x00, 0x00, 0x00 }; + struct { + char mycall[9]; + char sfx[5]; + unsigned int dcs_rptr_seq; + } rptr_2_dcs[3] = { {" ", " ", 0}, + {" ", " ", 0}, + {" ", " ", 0} + }; + struct { + char mycall[9]; + char sfx[5]; + unsigned int dcs_rptr_seq; + } ref_2_dcs[3] = { {" ", " ", 0}, + {" ", " ", 0}, + {" ", " ", 0} + }; + struct { + char mycall[9]; + char sfx[5]; + unsigned int dcs_rptr_seq; + } xrf_2_dcs[3] = { {" ", " ", 0}, + {" ", " ", 0}, + {" ", " ", 0} + }; + + u_int16_t streamid_raw; + + char source_stn[9]; + + memset(notify_msg, '\0', sizeof(notify_msg)); + time(&hb); + + if (xrf_g2_sock > max_nfds) + max_nfds = xrf_g2_sock; + if (ref_g2_sock > max_nfds) + max_nfds = ref_g2_sock; + if (rptr_sock > max_nfds) + max_nfds = rptr_sock; + if (dcs_g2_sock > max_nfds) + max_nfds = dcs_g2_sock; + + traceit("xrf=%d, dcs=%d, ref=%d, rptr=%d, MAX+1=%d\n", + xrf_g2_sock, dcs_g2_sock, ref_g2_sock, rptr_sock, max_nfds + 1); + + if (strlen(LINK_AT_STARTUP) >= 8) { + if ((LINK_AT_STARTUP[0] == 'A') || + (LINK_AT_STARTUP[0] == 'B') || + (LINK_AT_STARTUP[0] == 'C')) { + memset(temp_repeater, ' ', CALL_SIZE); + memcpy(temp_repeater, LINK_AT_STARTUP + 1, 6); + temp_repeater[CALL_SIZE] = '\0'; + g2link(LINK_AT_STARTUP[0], temp_repeater, LINK_AT_STARTUP[7]); + } + memset(LINK_AT_STARTUP, '\0', sizeof(LINK_AT_STARTUP)); + } + + while (keep_running) { + time(&tnow); + if ((tnow - hb) > 0) { + /* send heartbeat to connected donglers */ + send_heartbeat(); + + /* send heartbeat to linked XRF repeaters/reflectors */ + if (to_remote_g2[0].toDst4.sin_port == htons(RMT_XRF_PORT)) + sendto(xrf_g2_sock,OWNER, CALL_SIZE + 1, 0, + (struct sockaddr *)&(to_remote_g2[0].toDst4), + sizeof(to_remote_g2[0].toDst4)); + + if ((to_remote_g2[1].toDst4.sin_port == htons(RMT_XRF_PORT)) && + (strcmp(to_remote_g2[1].to_call, to_remote_g2[0].to_call) != 0)) + sendto(xrf_g2_sock,OWNER, CALL_SIZE + 1, 0, + (struct sockaddr *)&(to_remote_g2[1].toDst4), + sizeof(to_remote_g2[1].toDst4)); + + if ((to_remote_g2[2].toDst4.sin_port == htons(RMT_XRF_PORT)) && + (strcmp(to_remote_g2[2].to_call, to_remote_g2[0].to_call) != 0) && + (strcmp(to_remote_g2[2].to_call, to_remote_g2[1].to_call) != 0)) + sendto(xrf_g2_sock,OWNER, CALL_SIZE + 1, 0, + (struct sockaddr *)&(to_remote_g2[2].toDst4), + sizeof(to_remote_g2[2].toDst4)); + + /* send heartbeat to linked DCS reflectors */ + if (to_remote_g2[0].toDst4.sin_port == htons(RMT_DCS_PORT)) { + strcpy(cmd_2_dcs, OWNER); + cmd_2_dcs[7] = to_remote_g2[0].from_mod; + memcpy(cmd_2_dcs + 9, to_remote_g2[0].to_call, 8); + cmd_2_dcs[16] = to_remote_g2[0].to_mod; + sendto(dcs_g2_sock, cmd_2_dcs, 17, 0, + (struct sockaddr *)&(to_remote_g2[0].toDst4), + sizeof(to_remote_g2[0].toDst4)); + } + if (to_remote_g2[1].toDst4.sin_port == htons(RMT_DCS_PORT)) { + strcpy(cmd_2_dcs, OWNER); + cmd_2_dcs[7] = to_remote_g2[1].from_mod; + memcpy(cmd_2_dcs + 9, to_remote_g2[1].to_call, 8); + cmd_2_dcs[16] = to_remote_g2[1].to_mod; + sendto(dcs_g2_sock, cmd_2_dcs, 17, 0, + (struct sockaddr *)&(to_remote_g2[1].toDst4), + sizeof(to_remote_g2[1].toDst4)); + } + if (to_remote_g2[2].toDst4.sin_port == htons(RMT_DCS_PORT)) { + strcpy(cmd_2_dcs, OWNER); + cmd_2_dcs[7] = to_remote_g2[2].from_mod; + memcpy(cmd_2_dcs + 9, to_remote_g2[2].to_call, 8); + cmd_2_dcs[16] = to_remote_g2[2].to_mod; + sendto(dcs_g2_sock, cmd_2_dcs, 17, 0, + (struct sockaddr *)&(to_remote_g2[2].toDst4), + sizeof(to_remote_g2[2].toDst4)); + } + + /* send heartbeat to linked REF reflectors */ + if (to_remote_g2[0].is_connected && + (to_remote_g2[0].toDst4.sin_port == htons(RMT_REF_PORT))) + sendto(ref_g2_sock,(char *)REF_ACK,3,0, + (struct sockaddr *)&(to_remote_g2[0].toDst4), + sizeof(to_remote_g2[0].toDst4)); + + if (to_remote_g2[1].is_connected && + (to_remote_g2[1].toDst4.sin_port == htons(RMT_REF_PORT)) && + (strcmp(to_remote_g2[1].to_call, to_remote_g2[0].to_call) != 0)) + sendto(ref_g2_sock,(char *)REF_ACK,3,0, + (struct sockaddr *)&(to_remote_g2[1].toDst4), + sizeof(to_remote_g2[1].toDst4)); + + if (to_remote_g2[2].is_connected && + (to_remote_g2[2].toDst4.sin_port == htons(RMT_REF_PORT)) && + (strcmp(to_remote_g2[2].to_call, to_remote_g2[0].to_call) != 0) && + (strcmp(to_remote_g2[2].to_call, to_remote_g2[1].to_call) != 0)) + sendto(ref_g2_sock,(char *)REF_ACK,3,0, + (struct sockaddr *)&(to_remote_g2[2].toDst4), + sizeof(to_remote_g2[2].toDst4)); + + for (i = 0; i < 3; i++) { + /* check for timeouts from remote */ + if (to_remote_g2[i].to_call[0] != '\0') { + if (to_remote_g2[i].countdown >= 0) + to_remote_g2[i].countdown--; + + if (to_remote_g2[i].countdown < 0) { + /* maybe remote system has changed IP */ + traceit("Unlinked from [%s] mod %c, TIMEOUT...\n", + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + + sprintf(notify_msg, "%c_unlinked.dat_UNLINKED_TIMEOUT", to_remote_g2[i].from_mod); + audio_notify(notify_msg); + + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + + print_status_file(); + + } + } + + /*** check for RF inactivity ***/ + if (to_remote_g2[i].is_connected) { + if (((tnow - tracing[i].last_time) > RF_INACTIVITY_TIMER[i]) && (RF_INACTIVITY_TIMER[i] > 0)) { + tracing[i].last_time = 0; + + traceit("Unlinked from [%s] mod %c, local RF inactivity...\n", + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + + if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) { + queryCommand[0] = 5; + queryCommand[1] = 0; + queryCommand[2] = 24; + queryCommand[3] = 0; + queryCommand[4] = 0; + sendto(ref_g2_sock,(char *)queryCommand,5,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + + /* zero out any other entries here that match that system */ + for (j = 0; j < 3; j++) { + if (j != i) { + if ((to_remote_g2[j].toDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[j].toDst4.sin_port == htons(RMT_REF_PORT))) { + to_remote_g2[j].to_call[0] = '\0'; + memset(&(to_remote_g2[j].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[j].from_mod = ' '; + to_remote_g2[j].to_mod = ' '; + to_remote_g2[j].countdown = 0; + to_remote_g2[j].is_connected = false; + to_remote_g2[j].in_streamid[0] = 0x00; + to_remote_g2[j].in_streamid[1] = 0x00; + } + } + } + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) { + strcpy(unlink_request, OWNER); + unlink_request[8] = to_remote_g2[i].from_mod; + unlink_request[9] = ' '; + unlink_request[10] = '\0'; + + for (j = 0; j < 5; j++) + sendto(xrf_g2_sock,unlink_request, CALL_SIZE + 3,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) { + strcpy(cmd_2_dcs, OWNER); + cmd_2_dcs[8] = to_remote_g2[i].from_mod; + cmd_2_dcs[9] = ' '; + cmd_2_dcs[10] = '\0'; + memcpy(cmd_2_dcs + 11, to_remote_g2[i].to_call, 8); + + for (j = 0; j < 2; j++) + sendto(dcs_g2_sock, cmd_2_dcs, 19 ,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } + + sprintf(notify_msg, "%c_unlinked.dat_UNLINKED_TIMEOUT", to_remote_g2[i].from_mod); + audio_notify(notify_msg); + + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + + print_status_file(); + } + } + } + time(&hb); + } + + FD_ZERO(&fdset); + FD_SET(xrf_g2_sock,&fdset); + FD_SET(dcs_g2_sock,&fdset); + FD_SET(ref_g2_sock,&fdset); + FD_SET(rptr_sock,&fdset); + tv.tv_sec = 0; + tv.tv_usec = 20000; + (void)select(max_nfds + 1,&fdset,0,0,&tv); + + if (FD_ISSET(xrf_g2_sock, &fdset)) { + fromlen = sizeof(struct sockaddr_in); + recvlen2 = recvfrom(xrf_g2_sock,(char *)readBuffer2,100, + 0,(struct sockaddr *)&fromDst4,&fromlen); + + strncpy(ip, inet_ntoa(fromDst4.sin_addr),IP_SIZE); + ip[IP_SIZE] = '\0'; + strncpy(call, (char *)readBuffer2,CALL_SIZE); + call[CALL_SIZE] = '\0'; + + /* a packet of length (CALL_SIZE + 1) is a keepalive from a repeater/reflector */ + /* If it is from a dongle, it is either a keepalive or a request to connect */ + + if (recvlen2 == (CALL_SIZE + 1)) { + found = false; + /* Find out if it is a keepalive from a repeater */ + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) { + found = true; + if (!to_remote_g2[i].is_connected) { + tracing[i].last_time = time(NULL); + + to_remote_g2[i].is_connected = true; + traceit("Connected from: %.*s\n", recvlen2 - 1, readBuffer2); + print_status_file(); + + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + + } + to_remote_g2[i].countdown = TIMEOUT; + } + } + } else + /* A packet of length (CALL_SIZE + 6) is either an ACK or a NAK from repeater-reflector */ + /* Because we sent a request before asking to link */ + if (recvlen2 == (CALL_SIZE + 6)) { + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) { + if ((memcmp((char *)readBuffer2 + 10, "ACK", 3) == 0) && + (to_remote_g2[i].from_mod == readBuffer2[8])) { + if (!to_remote_g2[i].is_connected) { + tracing[i].last_time = time(NULL); + + to_remote_g2[i].is_connected = true; + traceit("Connected from: [%s] %c\n", + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + print_status_file(); + + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + } + } else if ((memcmp((char *)readBuffer2 + 10, "NAK", 3) == 0) && + (to_remote_g2[i].from_mod == readBuffer2[8])) { + traceit("Link module %c to [%s] %c is rejected\n", + to_remote_g2[i].from_mod, to_remote_g2[i].to_call, + to_remote_g2[i].to_mod); + + sprintf(notify_msg, "%c_failed_linked.dat_FAILED_TO_LINK", + to_remote_g2[i].from_mod); + audio_notify(notify_msg); + + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + + print_status_file(); + } + } + } + } else + /* + A packet of length (CALL_SIZE + 3) is a request + from a remote repeater to link-unlink with our repeater + */ + if (recvlen2 == CALL_SIZE + 3) { + /* Check our linked repeaters/reflectors */ + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) { + if (to_remote_g2[i].to_mod == readBuffer2[8]) { + /* unlink request from remote repeater that we know */ + if (readBuffer2[9] == ' ') { + traceit("Received: %.*s\n", recvlen2 - 1, readBuffer2); + traceit("Module %c to [%s] %c is unlinked\n", + to_remote_g2[i].from_mod, + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + + sprintf(notify_msg, "%c_unlinked.dat_UNLINKED", to_remote_g2[i].from_mod); + audio_notify(notify_msg); + + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + + print_status_file(); + } else + /* link request from a remote repeater that we know */ + if ( + ((i == 0) && (readBuffer2[9] == 'A')) || + ((i == 1) && (readBuffer2[9] == 'B')) || + ((i == 2) && (readBuffer2[9] == 'C')) + ) { + + /* + I HAVE TO ADD CODE here to PREVENT the REMOTE NODE + from LINKING one of their remote modules to + more than one of our local modules + */ + + traceit("Received: %.*s\n", recvlen2 - 1, readBuffer2); + + strncpy(to_remote_g2[i].to_call, (char *)readBuffer2,CALL_SIZE); + to_remote_g2[i].to_call[CALL_SIZE] = '\0'; + memcpy(&(to_remote_g2[i].toDst4), &fromDst4, sizeof(struct sockaddr_in)); + to_remote_g2[i].toDst4.sin_port = htons(RMT_XRF_PORT); + to_remote_g2[i].to_mod = readBuffer2[8]; + to_remote_g2[i].countdown = TIMEOUT; + to_remote_g2[i].is_connected = true; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + + traceit("Module %c to [%s] %c linked\n", + readBuffer2[9], + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + + tracing[i].last_time = time(NULL); + + print_status_file(); + + /* send back an ACK */ + memcpy(readBuffer2 + 10, "ACK", 4); + sendto(xrf_g2_sock, (char *)readBuffer2, CALL_SIZE + 6, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + + if (to_remote_g2[i].from_mod != readBuffer2[9]) { + to_remote_g2[i].from_mod = readBuffer2[9]; + + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + } + } + } + } + } + + /* link request from remote repeater that is not yet linked to our system */ + /* find out which of our local modules the remote repeater is interested in */ + i = -1; + if (readBuffer2[9] == 'A') + i = 0; + else if (readBuffer2[9] == 'B') + i = 1; + else if (readBuffer2[9] == 'C') + i = 2; + + /* Is this repeater listed in gwys.txt? */ + gwy_pos = gwy_list.find(call); + if (gwy_pos == gwy_list.end()) { + /* We did NOT find this repeater in gwys.txt, reject the incoming link request */ + traceit("Incoming link from %s,%s but not found in gwys.txt\n",call,ip); + i = -1; + } else { + rc = regexec(&preg, call, 0, NULL, 0); + if (rc != 0) { + traceit("Invalid repeater %s,%s requesting to link\n", call, ip); + i = -1; + } + } + + if (i >= 0) { + /* Is the local repeater module linked to anything ? */ + if (to_remote_g2[i].to_mod == ' ') { + if ((readBuffer2[8] == 'A') || (readBuffer2[8] == 'B') || (readBuffer2[8] == 'C') || + (readBuffer2[8] == 'D') || (readBuffer2[8] == 'E')) { + /* + I HAVE TO ADD CODE here to PREVENT the REMOTE NODE + from LINKING one of their remote modules to + more than one of our local modules + */ + + /* now it can be added as a repeater */ + strcpy(to_remote_g2[i].to_call, call); + to_remote_g2[i].to_call[CALL_SIZE] = '\0'; + memcpy(&(to_remote_g2[i].toDst4), &fromDst4, sizeof(struct sockaddr_in)); + to_remote_g2[i].toDst4.sin_port = htons(RMT_XRF_PORT); + to_remote_g2[i].from_mod = readBuffer2[9]; + to_remote_g2[i].to_mod = readBuffer2[8]; + to_remote_g2[i].countdown = TIMEOUT; + to_remote_g2[i].is_connected = true; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + + print_status_file(); + + tracing[i].last_time = time(NULL); + + traceit("Received: %.*s\n", recvlen2 - 1, readBuffer2); + traceit("Module %c to [%s] %c linked\n", + to_remote_g2[i].from_mod, + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + + /* send back an ACK */ + memcpy(readBuffer2 + 10, "ACK", 4); + sendto(xrf_g2_sock, (char *)readBuffer2, CALL_SIZE + 6, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } + } else { + if (fromDst4.sin_addr.s_addr != to_remote_g2[i].toDst4.sin_addr.s_addr) { + /* Our repeater module is linked to another repeater-reflector */ + memcpy(readBuffer2 + 10, "NAK", 4); + fromDst4.sin_port = htons(RMT_XRF_PORT); + sendto(xrf_g2_sock, (char *)readBuffer2, CALL_SIZE + 6, + 0,(struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + } + } + } + } else if ( ((recvlen2 == 56) || + (recvlen2 == 27)) && + (memcmp(readBuffer2, "DSVT", 4) == 0) && + ((readBuffer2[4] == 0x10) || + (readBuffer2[4] == 0x20)) && + (readBuffer2[8] == 0x20)) { + /* reset countdown and protect against hackers */ + + found = false; + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) { + to_remote_g2[i].countdown = TIMEOUT; + found = true; + } + } + + /* process header */ + + if ((recvlen2 == 56) && found) { + memset(source_stn, ' ', 9); + source_stn[8] = '\0'; + + /* some bad hotspot programs out there using INCORRECT flag */ + if (readBuffer2[15] == 0x40) + readBuffer2[15] = 0x00; + else if (readBuffer2[15] == 0x48) + readBuffer2[15] = 0x08; + else if (readBuffer2[15] == 0x60) + readBuffer2[15] = 0x20; + else if (readBuffer2[15] == 0x68) + readBuffer2[15] = 0x28; + + /* A reflector will send to us its own RPT1 */ + /* A repeater will send to us our RPT1 */ + + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT))) { + /* it is a reflector, reflector's rpt1 */ + if ((memcmp(readBuffer2 + 18, to_remote_g2[i].to_call, 7) == 0) && + (readBuffer2[25] == to_remote_g2[i].to_mod)) { + memcpy(&readBuffer2[18], OWNER, CALL_SIZE); + readBuffer2[25] = to_remote_g2[i].from_mod; + memcpy(&readBuffer2[34], "CQCQCQ ", 8); + + memcpy(source_stn, to_remote_g2[i].to_call, 8); + source_stn[7] = to_remote_g2[i].to_mod; + break; + } else + /* it is a repeater, our rpt1 */ + if ((memcmp(readBuffer2 + 18, OWNER, 7)) && + (readBuffer2[25] == to_remote_g2[i].from_mod)) { + memcpy(source_stn, to_remote_g2[i].to_call, 8); + source_stn[7] = to_remote_g2[i].to_mod; + break; + } + } + } + + /* somebody's crazy idea of having a personal callsign in RPT2 */ + /* we must set it to our gateway callsign */ + memcpy(&readBuffer2[26], OWNER, CALL_SIZE); + readBuffer2[33] = 'G'; + calcPFCS(readBuffer2,56); + + /* At this point, all data have our RPT1 and RPT2 */ + + /* send the data to the repeater/reflector that is linked to our RPT1 */ + i = -1; + if (readBuffer2[25] == 'A') + i = 0; + else if (readBuffer2[25] == 'B') + i = 1; + else if (readBuffer2[25] == 'C') + i = 2; + + /* are we sure that RPT1 is our system? */ + if ((memcmp(readBuffer2 + 18, OWNER, 7) == 0) && (i >= 0)) { + /* Last Heard */ + if (memcmp(old_sid[i].sid, readBuffer2 + 12, 2) != 0) { + if (QSO_DETAILS) + traceit("START from remote g2: streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s, source=%.8s\n", + readBuffer2[12],readBuffer2[13], + readBuffer2[15], readBuffer2[16], readBuffer2[17], + &readBuffer2[42], + &readBuffer2[50], &readBuffer2[34], + &readBuffer2[18], &readBuffer2[26], + recvlen2,inet_ntoa(fromDst4.sin_addr), source_stn); + + // put user into tmp1 + memcpy(tmp1, readBuffer2 + 42, 8); + tmp1[8] = '\0'; + + // delete the user if exists + for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) { + if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) { + dt_lh_list.erase(dt_lh_pos); + break; + } + } + /* Limit?, delete oldest user */ + if (dt_lh_list.size() == LH_MAX_SIZE) { + dt_lh_pos = dt_lh_list.begin(); + dt_lh_list.erase(dt_lh_pos); + } + // add user + time(&tnow); + sprintf(tmp2, "%ld=r%.6s%c%c", tnow, source_stn, source_stn[7], readBuffer2[25]); + dt_lh_list[tmp2] = tmp1; + + memcpy(old_sid[i].sid, readBuffer2 + 12, 2); + } + + /* relay data to our local G2 */ + sendto(rptr_sock, (char *)readBuffer2,56,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + + /* send data to donglers */ + /* no changes here */ + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + if (fromDst4.sin_addr.s_addr != inbound_ptr->sin.sin_addr.s_addr) { + readBuffer[0] = (unsigned char)(58 & 0xFF); + readBuffer[1] = (unsigned char)(58 >> 8 & 0x1F); + readBuffer[1] = (unsigned char)(readBuffer[1] | 0xFFFFFF80); + memcpy(readBuffer + 2, readBuffer2, 56); + + sendto(ref_g2_sock, (char *)readBuffer, 58, 0, + (struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + } else + inbound_ptr->mod = readBuffer2[25]; + } + + /* send the data to the repeater/reflector that is linked to our RPT1 */ + + /* Is there another local module linked to the remote same xrf mod ? */ + /* If Yes, then broadcast */ + k = i + 1; + + if (k < 3) { + brd_from_xrf_idx = 0; + streamid_raw = (readBuffer2[12] * 256U) + readBuffer2[13]; + + /* We can only enter this loop up to 2 times max */ + for (j = k; j < 3; j++) { + /* it is a remote gateway, not a dongle user */ + if ((fromDst4.sin_addr.s_addr == to_remote_g2[j].toDst4.sin_addr.s_addr) && + /* it is xrf */ + (to_remote_g2[j].toDst4.sin_port == htons(RMT_XRF_PORT)) && + (memcmp(to_remote_g2[j].to_call, "XRF", 3) == 0) && + /* it is the same xrf and xrf module */ + (memcmp(to_remote_g2[j].to_call, to_remote_g2[i].to_call, 8) == 0) && + (to_remote_g2[j].to_mod == to_remote_g2[i].to_mod)) { + /* send the packet to another module of our local repeater: this is multi-link */ + + /* generate new packet */ + memcpy(from_xrf_torptr_brd, readBuffer2, 56); + + /* different repeater module */ + from_xrf_torptr_brd[25] = to_remote_g2[j].from_mod; + + /* assign new streamid */ + streamid_raw ++; + if (streamid_raw == 0) + streamid_raw ++; + from_xrf_torptr_brd[12] = streamid_raw / 256U; + from_xrf_torptr_brd[13] = streamid_raw % 256U; + + calcPFCS(from_xrf_torptr_brd, 56); + + /* send the data to the local gateway/repeater */ + sendto(rptr_sock, (char *)from_xrf_torptr_brd,56,0, + (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + + /* save streamid for use with the audio packets that will arrive after this header */ + + brd_from_xrf.xrf_streamid[0] = readBuffer2[12]; + brd_from_xrf.xrf_streamid[1] = readBuffer2[13]; + brd_from_xrf.rptr_streamid[brd_from_xrf_idx][0] = from_xrf_torptr_brd[12]; + brd_from_xrf.rptr_streamid[brd_from_xrf_idx][1] = from_xrf_torptr_brd[13]; + brd_from_xrf_idx ++; + } + } + } + + if ((to_remote_g2[i].toDst4.sin_addr.s_addr != fromDst4.sin_addr.s_addr) && + to_remote_g2[i].is_connected) { + if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) { + if ( /*** (memcmp(readBuffer2 + 42, OWNER, 8) != 0) && ***/ /* block repeater announcements */ + (memcmp(readBuffer2 + 34, "CQCQCQ", 6) == 0) && /* CQ calls only */ + ((readBuffer2[15] == 0x00) || /* normal */ + (readBuffer2[15] == 0x08) || /* EMR */ + (readBuffer2[15] == 0x20) || /* BK */ + (readBuffer2[15] == 0x28)) && /* EMR + BK */ + (memcmp(readBuffer2 + 26, OWNER, 7) == 0) && /* rpt2 must be us */ + (readBuffer2[33] == 'G')) { + to_remote_g2[i].in_streamid[0] = readBuffer2[12]; + to_remote_g2[i].in_streamid[1] = readBuffer2[13]; + + /* inform XRF about the source */ + readBuffer2[11] = to_remote_g2[i].from_mod; + + memcpy((char *)readBuffer2 + 18, to_remote_g2[i].to_call, CALL_SIZE); + readBuffer2[25] = to_remote_g2[i].to_mod; + memcpy((char *)readBuffer2 + 26, to_remote_g2[i].to_call, CALL_SIZE); + readBuffer2[33] = 'G'; + calcPFCS(readBuffer2, 56); + + sendto(xrf_g2_sock, (char *)readBuffer2, 56, 0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) { + if ( /*** (memcmp(readBuffer2 + 42, OWNER, 8) != 0) && ***/ /* block repeater announcements */ + (memcmp(readBuffer2 + 34, "CQCQCQ", 6) == 0) && /* CQ calls only */ + ((readBuffer2[15] == 0x00) || /* normal */ + (readBuffer2[15] == 0x08) || /* EMR */ + (readBuffer2[15] == 0x20) || /* BK */ + (readBuffer2[15] == 0x28)) && /* EMR + BK */ + (memcmp(readBuffer2 + 26, OWNER, 7) == 0) && /* rpt2 must be us */ + (readBuffer2[33] == 'G')) { + to_remote_g2[i].in_streamid[0] = readBuffer2[12]; + to_remote_g2[i].in_streamid[1] = readBuffer2[13]; + + readBuffer[0] = (unsigned char)(58 & 0xFF); + readBuffer[1] = (unsigned char)(58 >> 8 & 0x1F); + readBuffer[1] = (unsigned char)(readBuffer[1] | 0xFFFFFF80); + + memcpy(readBuffer + 2, readBuffer2, 56); + + memset(readBuffer + 20, ' ', CALL_SIZE); + memcpy(readBuffer + 20, to_remote_g2[i].to_call, + strlen(to_remote_g2[i].to_call)); + readBuffer[27] = to_remote_g2[i].to_mod; + memset(readBuffer + 28, ' ', CALL_SIZE); + memcpy(readBuffer + 28, to_remote_g2[i].to_call, + strlen(to_remote_g2[i].to_call)); + readBuffer[35] = 'G'; + memcpy(&readBuffer[36], "CQCQCQ ", 8); + + calcPFCS(readBuffer + 2, 56); + + sendto(ref_g2_sock, (char *)readBuffer, 58, 0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) { + if ( /*** (memcmp(readBuffer2 + 42, OWNER, 8) != 0) && ***/ /* block repeater announcements */ + (memcmp(readBuffer2 + 34, "CQCQCQ", 6) == 0) && /* CQ calls only */ + ((readBuffer2[15] == 0x00) || /* normal */ + (readBuffer2[15] == 0x08) || /* EMR */ + (readBuffer2[15] == 0x20) || /* BK */ + (readBuffer2[15] == 0x28)) && /* EMR + BK */ + (memcmp(readBuffer2 + 26, OWNER, 7) == 0) && /* rpt2 must be us */ + (readBuffer2[33] == 'G')) { + to_remote_g2[i].in_streamid[0] = readBuffer2[12]; + to_remote_g2[i].in_streamid[1] = readBuffer2[13]; + + memcpy(xrf_2_dcs[i].mycall, readBuffer2 + 42, 8); + memcpy(xrf_2_dcs[i].sfx, readBuffer2 + 50, 4); + xrf_2_dcs[i].dcs_rptr_seq = 0; + } + } + } + } + } else if (found) { + if ((readBuffer2[14] & 0x40) != 0) { + for (i = 0; i < 3; i++) { + if (memcmp(old_sid[i].sid, readBuffer2 + 12, 2) == 0) { + if (QSO_DETAILS) + traceit("END from remote g2: streamID=%d,%d, %d bytes from IP=%s\n", + readBuffer2[12],readBuffer2[13],recvlen2,inet_ntoa(fromDst4.sin_addr)); + + memset(old_sid[i].sid, 0x00, 2); + + break; + } + } + } + + /* relay data to our local G2 */ + sendto(rptr_sock, (char *)readBuffer2,27,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + + /* send data to donglers */ + /* no changes here */ + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + if (fromDst4.sin_addr.s_addr != inbound_ptr->sin.sin_addr.s_addr) { + readBuffer[0] = (unsigned char)(29 & 0xFF); + readBuffer[1] = (unsigned char)(29 >> 8 & 0x1F); + readBuffer[1] = (unsigned char)(readBuffer[1] | 0xFFFFFF80); + + memcpy(readBuffer + 2, readBuffer2, 27); + + sendto(ref_g2_sock, (char *)readBuffer, 29, + 0,(struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + } + } + + /* do we have to broadcast ? */ + if (memcmp(brd_from_xrf.xrf_streamid, readBuffer2 + 12, 2) == 0) { + memcpy(from_xrf_torptr_brd, readBuffer2, 27); + + if ((brd_from_xrf.rptr_streamid[0][0] != 0x00) || + (brd_from_xrf.rptr_streamid[0][1] != 0x00)) { + from_xrf_torptr_brd[12] = brd_from_xrf.rptr_streamid[0][0]; + from_xrf_torptr_brd[13] = brd_from_xrf.rptr_streamid[0][1]; + sendto(rptr_sock, (char *)from_xrf_torptr_brd,27,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + } + + if ((brd_from_xrf.rptr_streamid[1][0] != 0x00) || + (brd_from_xrf.rptr_streamid[1][1] != 0x00)) { + from_xrf_torptr_brd[12] = brd_from_xrf.rptr_streamid[1][0]; + from_xrf_torptr_brd[13] = brd_from_xrf.rptr_streamid[1][1]; + sendto(rptr_sock, (char *)from_xrf_torptr_brd,27,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + } + + if ((readBuffer2[14] & 0x40) != 0) { + brd_from_xrf.xrf_streamid[0] = brd_from_xrf.xrf_streamid[1] = 0x00; + brd_from_xrf.rptr_streamid[0][0] = brd_from_xrf.rptr_streamid[0][1] = 0x00; + brd_from_xrf.rptr_streamid[1][0] = brd_from_xrf.rptr_streamid[1][1] = 0x00; + brd_from_xrf_idx = 0; + } + } + + for (i = 0; i < 3; i++) { + if ((to_remote_g2[i].is_connected) && + (to_remote_g2[i].toDst4.sin_addr.s_addr != fromDst4.sin_addr.s_addr) && + (memcmp(to_remote_g2[i].in_streamid, readBuffer2 + 12, 2) == 0)) { + if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) { + /* inform XRF about the source */ + readBuffer2[11] = to_remote_g2[i].from_mod; + + sendto(xrf_g2_sock, (char *)readBuffer2, 27, 0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) { + readBuffer[0] = (unsigned char)(29 & 0xFF); + readBuffer[1] = (unsigned char)(29 >> 8 & 0x1F); + readBuffer[1] = (unsigned char)(readBuffer[1] | 0xFFFFFF80); + + memcpy(readBuffer + 2, readBuffer2, 27); + + sendto(ref_g2_sock, (char *)readBuffer, 29, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) { + memset(dcs_buf, 0x00, 600); + dcs_buf[0] = dcs_buf[1] = dcs_buf[2] = '0'; + dcs_buf[3] = '1'; + dcs_buf[4] = dcs_buf[5] = dcs_buf[6] = 0x00; + memcpy(dcs_buf + 7, to_remote_g2[i].to_call, 8); + dcs_buf[14] = to_remote_g2[i].to_mod; + memcpy(dcs_buf + 15, OWNER, 8); + dcs_buf[22] = to_remote_g2[i].from_mod; + memcpy(dcs_buf + 23, "CQCQCQ ", 8); + memcpy(dcs_buf + 31, xrf_2_dcs[i].mycall, 8); + memcpy(dcs_buf + 39, xrf_2_dcs[i].sfx, 4); + dcs_buf[43] = readBuffer2[12]; /* streamid0 */ + dcs_buf[44] = readBuffer2[13]; /* streamid1 */ + dcs_buf[45] = readBuffer2[14]; /* cycle sequence */ + memcpy(dcs_buf + 46, readBuffer2 + 15, 12); + + dcs_buf[58] = (xrf_2_dcs[i].dcs_rptr_seq >> 0) & 0xff; + dcs_buf[59] = (xrf_2_dcs[i].dcs_rptr_seq >> 8) & 0xff; + dcs_buf[60] = (xrf_2_dcs[i].dcs_rptr_seq >> 16) & 0xff; + + xrf_2_dcs[i].dcs_rptr_seq ++; + + dcs_buf[61] = 0x01; + dcs_buf[62] = 0x00; + + sendto(dcs_g2_sock, dcs_buf, 100, 0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } + + if ((readBuffer2[14] & 0x40) != 0) { + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + } + break; + } + } + } + } + FD_CLR (xrf_g2_sock,&fdset); + } + + if (FD_ISSET(ref_g2_sock, &fdset)) { + fromlen = sizeof(struct sockaddr_in); + recvlen2 = recvfrom(ref_g2_sock,(char *)readBuffer2,100, + 0,(struct sockaddr *)&fromDst4,&fromlen); + + strncpy(ip, inet_ntoa(fromDst4.sin_addr),IP_SIZE); + ip[IP_SIZE] = '\0'; + + found = false; + + /* LH */ + if ((recvlen2 == 4) && + (readBuffer2[0] == 4) && + (readBuffer2[1] == 192) && + (readBuffer2[2] == 7) && + (readBuffer2[3] == 0)) { + unsigned short j_idx = 0; + unsigned short k_idx = 0; + unsigned char tmp[2]; + + pos = inbound_list.find(ip); + if (pos != inbound_list.end()) { + inbound_ptr = (inbound *)pos->second; + // traceit("Remote station %s %s requested LH list\n", inbound_ptr->call, ip); + + /* header is 10 bytes */ + + /* reply type */ + readBuffer2[2] = 7; + readBuffer2[3] = 0; + + /* it looks like time_t here */ + time(&tnow); + memcpy((char *)readBuffer2 + 6, (char *)&tnow, sizeof(time_t)); + + for (r_dt_lh_pos = dt_lh_list.rbegin(); r_dt_lh_pos != dt_lh_list.rend(); r_dt_lh_pos++) { + /* each entry has 24 bytes */ + + /* start at position 10 to bypass the header */ + strcpy((char *)readBuffer2 + 10 + (24 * j_idx), r_dt_lh_pos->second.c_str()); + p = strchr((char *)r_dt_lh_pos->first.c_str(), '='); + if (p) { + memcpy((char *)readBuffer2 + 18 + (24 * j_idx), p + 2, 8); + + /* if local or local w/gps */ + if ((p[1] == 'l') || (p[1] == 'g')) + readBuffer2[18 + (24 * j_idx) + 6] = *(p + 1); + + *p = '\0'; + tnow = atol(r_dt_lh_pos->first.c_str()); + *p = '='; + memcpy((char *)readBuffer2 + 26 + (24 * j_idx), &tnow, sizeof(time_t)); + } else { + memcpy((char *)readBuffer2 + 18 + (24 * j_idx), "ERROR ", 8); + time(&tnow); + memcpy((char *)readBuffer2 + 26 + (24 * j_idx), &tnow, sizeof(time_t)); + } + + readBuffer2[30 + (24 * j_idx)] = 0; + readBuffer2[31 + (24 * j_idx)] = 0; + readBuffer2[32 + (24 * j_idx)] = 0; + readBuffer2[33 + (24 * j_idx)] = 0; + + j_idx++; + + /* process 39 entries at a time */ + if (j_idx == 39) { + /* 39 * 24 = 936 + 10 header = 946 */ + readBuffer2[0] = 0xb2; + readBuffer2[1] = 0xc3; + + /* 39 entries */ + readBuffer2[4] = 0x27; + readBuffer2[5] = 0x00; + + sendto(ref_g2_sock,(char *)readBuffer2,946,0, + (struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + + j_idx = 0; + } + } + + if (j_idx != 0) { + k_idx = 10 + (j_idx * 24); + memcpy(tmp, (char *)&k_idx, 2); + readBuffer2[0] = tmp[0]; + readBuffer2[1] = tmp[1] | 0xc0; + + memcpy(tmp, (char *)&j_idx, 2); + readBuffer2[4] = tmp[0]; + readBuffer2[5] = tmp[1]; + + sendto(ref_g2_sock,(char *)readBuffer2, k_idx, 0, + (struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + } + } + } else + /* linked repeaters request */ + if ((recvlen2 == 4) && + (readBuffer2[0] == 4) && + (readBuffer2[1] == 192) && + (readBuffer2[2] == 5) && + (readBuffer2[3] == 0)) { + unsigned short i_idx = 0; + unsigned short j_idx = 0; + unsigned short k_idx = 0; + unsigned char tmp[2]; + unsigned short total = 0; + + pos = inbound_list.find(ip); + if (pos != inbound_list.end()) { + inbound_ptr = (inbound *)pos->second; + // traceit("Remote station %s %s requested linked repeaters list\n", inbound_ptr->call, ip); + + /* header is 8 bytes */ + + /* reply type */ + readBuffer2[2] = 5; + readBuffer2[3] = 1; + + /* we can have up to 3 linked systems */ + total = 3; + memcpy(tmp, (char *)&total, 2); + readBuffer2[6] = tmp[0]; + readBuffer2[7] = tmp[1]; + + for (i = 0, i_idx = 0; i < 3; i++, i_idx++) { + /* each entry has 20 bytes */ + if (to_remote_g2[i].to_mod != ' ') { + if (i == 0) + readBuffer2[8 + (20 * j_idx)] = 'A'; + else if (i == 1) + readBuffer2[8 + (20 * j_idx)] = 'B'; + else if (i == 2) + readBuffer2[8 + (20 * j_idx)] = 'C'; + + strcpy((char *)readBuffer2 + 9 + (20 * j_idx), to_remote_g2[i].to_call); + readBuffer2[16 + (20 * j_idx)] = to_remote_g2[i].to_mod; + + readBuffer2[17 + (20 * j_idx)] = 0; + readBuffer2[18 + (20 * j_idx)] = 0; + readBuffer2[19 + (20 * j_idx)] = 0; + readBuffer2[20 + (20 * j_idx)] = 0x50; + readBuffer2[21 + (20 * j_idx)] = 0x04; + readBuffer2[22 + (20 * j_idx)] = 0x32; + readBuffer2[23 + (20 * j_idx)] = 0x4d; + readBuffer2[24 + (20 * j_idx)] = 0x9f; + readBuffer2[25 + (20 * j_idx)] = 0xdb; + readBuffer2[26 + (20 * j_idx)] = 0x0e; + readBuffer2[27 + (20 * j_idx)] = 0; + + j_idx++; + + if (j_idx == 39) { + /* 20 bytes for each user, so 39 * 20 = 780 bytes + 8 bytes header = 788 */ + readBuffer2[0] = 0x14; + readBuffer2[1] = 0xc3; + + k_idx = i_idx - 38; + memcpy(tmp, (char *)&k_idx, 2); + readBuffer2[4] = tmp[0]; + readBuffer2[5] = tmp[1]; + + sendto(ref_g2_sock,(char *)readBuffer2,788,0, + (struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + + j_idx = 0; + } + } + } + + if (j_idx != 0) { + k_idx = 8 + (j_idx * 20); + memcpy(tmp, (char *)&k_idx, 2); + readBuffer2[0] = tmp[0]; + readBuffer2[1] = tmp[1] | 0xc0; + + if (i_idx > j_idx) + k_idx = i_idx - j_idx; + else + k_idx = 0; + + memcpy(tmp, (char *)&k_idx, 2); + readBuffer2[4] = tmp[0]; + readBuffer2[5] = tmp[1]; + + sendto(ref_g2_sock,(char *)readBuffer2, 8 + (j_idx * 20), 0, + (struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + } + } + } else + /* connected user list request */ + if ((recvlen2 == 4) && + (readBuffer2[0] == 4) && + (readBuffer2[1] == 192) && + (readBuffer2[2] == 6) && + (readBuffer2[3] == 0)) { + unsigned short i_idx = 0; + unsigned short j_idx = 0; + unsigned short k_idx = 0; + unsigned char tmp[2]; + unsigned short total = 0; + + pos = inbound_list.find(ip); + if (pos != inbound_list.end()) { + inbound_ptr = (inbound *)pos->second; + // traceit("Remote station %s %s requested connected user list\n", inbound_ptr->call, ip); + + /* header is 8 bytes */ + + /* reply type */ + readBuffer2[2] = 6; + readBuffer2[3] = 0; + + /* total connected users */ + total = inbound_list.size(); + memcpy(tmp, (char *)&total, 2); + readBuffer2[6] = tmp[0]; + readBuffer2[7] = tmp[1]; + + for (pos = inbound_list.begin(), i_idx = 0; pos != inbound_list.end(); pos++, i_idx++) { + /* each entry has 20 bytes */ + readBuffer2[8 + (20 * j_idx)] = ' '; + inbound_ptr = (inbound *)pos->second; + + readBuffer2[8 + (20 * j_idx)] = inbound_ptr->mod; + strcpy((char *)readBuffer2 + 9 + (20 * j_idx), inbound_ptr->call); + + readBuffer2[17 + (20 * j_idx)] = 0; + /* readBuffer2[18 + (20 * j_idx)] = 0; */ + readBuffer2[18 + (20 * j_idx)] = inbound_ptr->client; + readBuffer2[19 + (20 * j_idx)] = 0; + readBuffer2[20 + (20 * j_idx)] = 0x0d; + readBuffer2[21 + (20 * j_idx)] = 0x4d; + readBuffer2[22 + (20 * j_idx)] = 0x37; + readBuffer2[23 + (20 * j_idx)] = 0x4d; + readBuffer2[24 + (20 * j_idx)] = 0x6f; + readBuffer2[25 + (20 * j_idx)] = 0x98; + readBuffer2[26 + (20 * j_idx)] = 0x04; + readBuffer2[27 + (20 * j_idx)] = 0; + + j_idx++; + + if (j_idx == 39) { + /* 20 bytes for each user, so 39 * 20 = 788 bytes + 8 bytes header = 788 */ + readBuffer2[0] = 0x14; + readBuffer2[1] = 0xc3; + + k_idx = i_idx - 38; + memcpy(tmp, (char *)&k_idx, 2); + readBuffer2[4] = tmp[0]; + readBuffer2[5] = tmp[1]; + + sendto(ref_g2_sock,(char *)readBuffer2,788,0, + (struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + + j_idx = 0; + } + } + + if (j_idx != 0) { + k_idx = 8 + (j_idx * 20); + memcpy(tmp, (char *)&k_idx, 2); + readBuffer2[0] = tmp[0]; + readBuffer2[1] = tmp[1] | 0xc0; + + if (i_idx > j_idx) + k_idx = i_idx - j_idx; + else + k_idx = 0; + + memcpy(tmp, (char *)&k_idx, 2); + readBuffer2[4] = tmp[0]; + readBuffer2[5] = tmp[1]; + + sendto(ref_g2_sock,(char *)readBuffer2, 8 + (j_idx * 20), 0, + (struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + } + } + } else + /* date request */ + if ((recvlen2 == 4) && + (readBuffer2[0] == 4) && + (readBuffer2[1] == 192) && + (readBuffer2[2] == 8) && + (readBuffer2[3] == 0)) { + time_t ltime; + struct tm tm; + + pos = inbound_list.find(ip); + if (pos != inbound_list.end()) { + inbound_ptr = (inbound *)pos->second; + // traceit("Remote station %s %s requested date\n", inbound_ptr->call, ip); + + time(<ime); + localtime_r(<ime,&tm); + + readBuffer2[0] = 34; + readBuffer2[1] = 192; + readBuffer2[2] = 8; + readBuffer2[3] = 0; + readBuffer2[4] = 0xb5; + readBuffer2[5] = 0xae; + readBuffer2[6] = 0x37; + readBuffer2[7] = 0x4d; + snprintf((char *)readBuffer2 + 8, 1024 - 1, + "20%02d/%02d/%02d %02d:%02d:%02d %5.5s", + tm.tm_year % 100, tm.tm_mon+1,tm.tm_mday, + tm.tm_hour,tm.tm_min,tm.tm_sec, + (tzname[0] == NULL)?" ":tzname[0]); + + sendto(ref_g2_sock,(char *)readBuffer2,34,0, + (struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + } + } else + /* version request */ + if ((recvlen2 == 4) && + (readBuffer2[0] == 4) && + (readBuffer2[1] == 192) && + (readBuffer2[2] == 3) && + (readBuffer2[3] == 0)) { + pos = inbound_list.find(ip); + if (pos != inbound_list.end()) { + inbound_ptr = (inbound *)pos->second; + // traceit("Remote station %s %s requested version\n", inbound_ptr->call, ip); + + readBuffer2[0] = 9; + readBuffer2[1] = 192; + readBuffer2[2] = 3; + readBuffer2[3] = 0; + strncpy((char *)readBuffer2 + 4, VERSION, 4); + readBuffer2[8] = 0; + + sendto(ref_g2_sock,(char *)readBuffer2,9,0, + (struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + } + } else if ((recvlen2 == 5) && + (readBuffer2[0] == 5) && + (readBuffer2[1] == 0) && + (readBuffer2[2] == 24) && + (readBuffer2[3] == 0) && + (readBuffer2[4] == 0)) { + /* reply with the same DISCONNECT */ + sendto(ref_g2_sock,(char *)readBuffer2,5,0, + (struct sockaddr *)&fromDst4, + sizeof(struct sockaddr_in)); + + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) { + traceit("Call %s disconnected\n", to_remote_g2[i].to_call); + + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + } + } + + pos = inbound_list.find(ip); + if (pos != inbound_list.end()) { + inbound_ptr = (inbound *)pos->second; + if (memcmp(inbound_ptr->call, "1NFO", 4) != 0) + traceit("Call %s disconnected\n", inbound_ptr->call); + free(pos->second); + pos->second = NULL; + inbound_list.erase(pos); + } + print_status_file(); + } + + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) { + found = true; + if ((recvlen2 == 5) && + (readBuffer2[0] == 5) && + (readBuffer2[1] == 0) && + (readBuffer2[2] == 24) && + (readBuffer2[3] == 0) && + (readBuffer2[4] == 1)) { + traceit("Connected to call %s\n", to_remote_g2[i].to_call); + queryCommand[0] = 28; + queryCommand[1] = 192; + queryCommand[2] = 4; + queryCommand[3] = 0; + + memcpy(queryCommand + 4, LOGIN_CALL, CALL_SIZE); + for (j = 11; j > 3; j--) { + if (queryCommand[j] == ' ') + queryCommand[j] = '\0'; + else + break; + } + memset(queryCommand + 12, '\0', 8); + memcpy(queryCommand + 20, "DV019999", 8); + + /*** ATTENTION: I should ONLY send once for each distinct + remote IP, so get out of the loop immediately + ***/ + sendto(ref_g2_sock,(char *)queryCommand,28,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + + break; + } + } + } + + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) { + found = true; + if ((recvlen2 == 8) && + (readBuffer2[0] == 8) && + (readBuffer2[1] == 192) && + (readBuffer2[2] == 4) && + (readBuffer2[3] == 0)) { + if ((readBuffer2[4] == 79) && + (readBuffer2[5] == 75) && + (readBuffer2[6] == 82)) { + if (!to_remote_g2[i].is_connected) { + to_remote_g2[i].is_connected = true; + to_remote_g2[i].countdown = TIMEOUT; + traceit("Login OK to call %s mod %c\n", + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + print_status_file(); + + tracing[i].last_time = time(NULL); + + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + } + } else if ((readBuffer2[4] == 70) && + (readBuffer2[5] == 65) && + (readBuffer2[6] == 73) && + (readBuffer2[7] == 76)) { + traceit("Login failed to call %s mod %c\n", + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + + sprintf(notify_msg, "%c_failed_linked.dat_FAILED_TO_LINK", + to_remote_g2[i].from_mod); + audio_notify(notify_msg); + + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + } else if ((readBuffer2[4] == 66) && + (readBuffer2[5] == 85) && + (readBuffer2[6] == 83) && + (readBuffer2[7] == 89)) { + traceit("Busy or unknown status from call %s mod %c\n", + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + + sprintf(notify_msg, "%c_failed_linked.dat_FAILED_TO_LINK", + to_remote_g2[i].from_mod); + audio_notify(notify_msg); + + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + } + } + } + } + + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) { + found = true; + if ((recvlen2 == 24) && + (readBuffer2[0] == 24) && + (readBuffer2[1] == 192) && + (readBuffer2[2] == 3) && + (readBuffer2[3] == 0)) { + j = i; + to_remote_g2[i].countdown = TIMEOUT; + } + } + } + + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) { + found = true; + if (recvlen2 == 3) + to_remote_g2[i].countdown = TIMEOUT; + } + } + + /* find out if it is a connected dongle */ + pos = inbound_list.find(ip); + if (pos != inbound_list.end()) { + inbound_ptr = (inbound *)pos->second; + found = true; + inbound_ptr->countdown = TIMEOUT; + /*** ip is same, do not update port + memcpy((char *)&(inbound_ptr->sin),(char *)&fromDst4, sizeof(struct sockaddr_in)); + ***/ + } + + if (!found) { + /* + The incoming packet is not in the list of outbound repeater connections. + and it is not a connected dongle. + In this case, this must be an INCOMING dongle request + */ + if ((recvlen2 == 5) && + (readBuffer2[0] == 5) && + (readBuffer2[1] == 0) && + (readBuffer2[2] == 24) && + (readBuffer2[3] == 0) && + (readBuffer2[4] == 1)) { + if ((inbound_list.size() + 1) > MAX_DONGLES) + traceit("Inbound DONGLE-p connection from %s but over the MAX_DONGLES limit of %d\n", + ip, inbound_list.size()); + else + sendto(ref_g2_sock,(char *)readBuffer2,5,0, + (struct sockaddr *)&fromDst4, + sizeof(fromDst4)); + } else if ((recvlen2 == 28) && + (readBuffer2[0] == 28) && + (readBuffer2[1] == 192) && + (readBuffer2[2] == 4) && + (readBuffer2[3] == 0)) { + /* verify callsign */ + memcpy(call, readBuffer2 + 4, CALL_SIZE); + call[CALL_SIZE] = '\0'; + for (i = 7; i > 0; i--) { + if (call[i] == '\0') + call[i] = ' '; + else + break; + } + + if (memcmp(call, "1NFO", 4) != 0) + traceit("Inbound DONGLE-p CALL=%s, ip=%s, DV=%.8s\n", + call, ip, readBuffer2 + 20); + + if ((inbound_list.size() + 1) > MAX_DONGLES) + traceit("Inbound DONGLE-p connection from %s but over the MAX_DONGLES limit of %d\n", + ip, inbound_list.size()); + else if (ONLY_ADMIN_LOGIN && (admin.find(call) == admin.end())) + traceit("Incoming call [%s] from %s not an ADMIN\n", call, ip); + else if (regexec(&preg, call, 0, NULL, 0) != 0) { + traceit("Invalid dongle callsign: CALL=%s,ip=%s\n", call, ip); + + readBuffer2[0] = 8; + readBuffer2[4] = 70; + readBuffer2[5] = 65; + readBuffer2[6] = 73; + readBuffer2[7] = 76; + + sendto(ref_g2_sock,(char *)readBuffer2,8,0, + (struct sockaddr *)&fromDst4, + sizeof(fromDst4)); + } else { + /* add the dongle to the inbound list */ + inbound_ptr = (inbound *)malloc(sizeof(inbound)); + if (inbound_ptr) { + inbound_ptr->countdown = TIMEOUT; + memcpy((char *)&(inbound_ptr->sin),(char *)&fromDst4, sizeof(struct sockaddr_in)); + strcpy(inbound_ptr->call, call); + + inbound_ptr->mod = ' '; + + if (memcmp(readBuffer2 + 20, "AP", 2) == 0) + inbound_ptr->client = 'A'; /* dvap */ + else if (memcmp(readBuffer2 + 20, "DV019999", 8) == 0) + inbound_ptr->client = 'H'; /* spot */ + else + inbound_ptr->client = 'D'; /* dongle */ + + insert_pair = inbound_list.insert(pair(ip, inbound_ptr)); + if (insert_pair.second) { + if (memcmp(inbound_ptr->call, "1NFO", 4) != 0) + traceit("new CALL=%s, DONGLE-p, ip=%s, users=%d\n", + inbound_ptr->call,ip,inbound_list.size()); + + readBuffer2[0] = 8; + readBuffer2[4] = 79; + readBuffer2[5] = 75; + readBuffer2[6] = 82; + readBuffer2[7] = 87; + + sendto(ref_g2_sock,(char *)readBuffer2,8,0, + (struct sockaddr *)&fromDst4, + sizeof(fromDst4)); + + print_status_file(); + + } else { + traceit("failed to add CALL=%s,ip=%s\n",inbound_ptr->call,ip); + free(inbound_ptr); + inbound_ptr = NULL; + + readBuffer2[0] = 8; + readBuffer2[4] = 70; + readBuffer2[5] = 65; + readBuffer2[6] = 73; + readBuffer2[7] = 76; + + sendto(ref_g2_sock,(char *)readBuffer2,8,0, + (struct sockaddr *)&fromDst4, + sizeof(fromDst4)); + } + } else { + traceit("malloc() failed for call=%s,ip=%s\n",call,ip); + + readBuffer2[0] = 8; + readBuffer2[4] = 70; + readBuffer2[5] = 65; + readBuffer2[6] = 73; + readBuffer2[7] = 76; + + sendto(ref_g2_sock,(char *)readBuffer2,8,0, + (struct sockaddr *)&fromDst4, + sizeof(fromDst4)); + } + } + } + } + + if ( ((recvlen2 == 58) || + (recvlen2 == 29) || + (recvlen2 == 32)) && + (memcmp(readBuffer2 + 2, "DSVT", 4) == 0) && + ((readBuffer2[6] == 0x10) || + (readBuffer2[6] == 0x20)) && + (readBuffer2[10] == 0x20)) { + /* Is it one of the donglers or repeaters-reflectors */ + found = false; + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) { + to_remote_g2[i].countdown = TIMEOUT; + found = true; + } + } + if (!found) { + pos = inbound_list.find(ip); + if (pos != inbound_list.end()) { + inbound_ptr = (inbound *)pos->second; + inbound_ptr->countdown = TIMEOUT; + found = true; + } + } + + if ((recvlen2 == 58) && found) { + memset(source_stn, ' ', 9); + source_stn[8] = '\0'; + + /* some bad hotspot programs out there using INCORRECT flag */ + if (readBuffer2[17] == 0x40) + readBuffer2[17] = 0x00; + else if (readBuffer2[17] == 0x48) + readBuffer2[17] = 0x08; + else if (readBuffer2[17] == 0x60) + readBuffer2[17] = 0x20; + else if (readBuffer2[17] == 0x68) + readBuffer2[17] = 0x28; + + /* A reflector will send to us its own RPT1 */ + /* A repeater will send to us its own RPT1 */ + /* A dongleR will send to us our RPT1 */ + + /* It is from a repeater-reflector, correct rpt1, rpt2 and re-compute pfcs */ + for (i = 0; i < 3; i++) { + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) && + ( + ((memcmp(readBuffer2 + 20, to_remote_g2[i].to_call, 7) == 0) && + (readBuffer2[27] == to_remote_g2[i].to_mod)) || + ((memcmp(readBuffer2 + 28, to_remote_g2[i].to_call, 7) == 0) && + (readBuffer2[35] == to_remote_g2[i].to_mod)) + )) { + memcpy(&readBuffer2[20], OWNER, CALL_SIZE); + readBuffer2[27] = to_remote_g2[i].from_mod; + memcpy(&readBuffer2[36], "CQCQCQ ", 8); + + memcpy(source_stn, to_remote_g2[i].to_call, 8); + source_stn[7] = to_remote_g2[i].to_mod; + + break; + } + } + + if (i == 3) { + pos = inbound_list.find(ip); + if (pos != inbound_list.end()) { + inbound_ptr = (inbound *)pos->second; + memcpy(source_stn, inbound_ptr->call, 8); + } + } + + /* somebody's crazy idea of having a personal callsign in RPT2 */ + /* we must set it to our gateway callsign */ + memcpy(&readBuffer2[28], OWNER, CALL_SIZE); + readBuffer2[35] = 'G'; + calcPFCS(readBuffer2 + 2,56); + + /* At this point, all data have our RPT1 and RPT2 */ + + i = -1; + if (readBuffer2[27] == 'A') + i = 0; + else if (readBuffer2[27] == 'B') + i = 1; + else if (readBuffer2[27] == 'C') + i = 2; + + /* are we sure that RPT1 is our system? */ + if ((memcmp(readBuffer2 + 20, OWNER, 7) == 0) && (i >= 0)) { + /* Last Heard */ + if (memcmp(old_sid[i].sid, readBuffer2 + 14, 2) != 0) { + if (QSO_DETAILS) + traceit("START from remote g2: streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s, source=%.8s\n", + readBuffer2[14],readBuffer2[15], + readBuffer2[17], readBuffer2[18], readBuffer2[19], + &readBuffer2[44], + &readBuffer2[52], &readBuffer2[36], + &readBuffer2[20], &readBuffer2[28], + recvlen2,inet_ntoa(fromDst4.sin_addr), source_stn); + + // put user into tmp1 + memcpy(tmp1, readBuffer2 + 44, 8); + tmp1[8] = '\0'; + + // delete the user if exists + for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) { + if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) { + dt_lh_list.erase(dt_lh_pos); + break; + } + } + /* Limit?, delete oldest user */ + if (dt_lh_list.size() == LH_MAX_SIZE) { + dt_lh_pos = dt_lh_list.begin(); + dt_lh_list.erase(dt_lh_pos); + } + // add user + time(&tnow); + sprintf(tmp2, "%ld=r%.6s%c%c", tnow, source_stn, source_stn[7], readBuffer2[27]); + dt_lh_list[tmp2] = tmp1; + + memcpy(old_sid[i].sid, readBuffer2 + 14, 2); + } + + /* send the data to the local gateway/repeater */ + sendto(rptr_sock, (char *)readBuffer2 + 2,56,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + + /* send the data to the donglers */ + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + if (fromDst4.sin_addr.s_addr != inbound_ptr->sin.sin_addr.s_addr) { + sendto(ref_g2_sock, (char *)readBuffer2, 58, 0, + (struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + } else + inbound_ptr->mod = readBuffer2[27]; + } + + if ((to_remote_g2[i].toDst4.sin_addr.s_addr != fromDst4.sin_addr.s_addr) && + to_remote_g2[i].is_connected) { + if ( /*** (memcmp(readBuffer2 + 44, OWNER, 8) != 0) && ***/ /* block repeater announcements */ + (memcmp(readBuffer2 + 36, "CQCQCQ", 6) == 0) && /* CQ calls only */ + ((readBuffer2[17] == 0x00) || /* normal */ + (readBuffer2[17] == 0x08) || /* EMR */ + (readBuffer2[17] == 0x20) || /* BK */ + (readBuffer2[17] == 0x28)) && /* EMR + BK */ + (memcmp(readBuffer2 + 28, OWNER, 7) == 0) && /* rpt2 must be us */ + (readBuffer2[35] == 'G')) { + to_remote_g2[i].in_streamid[0] = readBuffer2[14]; + to_remote_g2[i].in_streamid[1] = readBuffer2[15]; + + if ((to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) || + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) { + memcpy((char *)readBuffer2 + 20, to_remote_g2[i].to_call, CALL_SIZE); + readBuffer2[27] = to_remote_g2[i].to_mod; + memcpy((char *)readBuffer2 + 28, to_remote_g2[i].to_call, CALL_SIZE); + readBuffer2[35] = 'G'; + calcPFCS(readBuffer2 + 2, 56); + + if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) { + /* inform XRF about the source */ + readBuffer2[13] = to_remote_g2[i].from_mod; + + sendto(xrf_g2_sock, (char *)readBuffer2 + 2, 56, 0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } else + sendto(ref_g2_sock, (char *)readBuffer2, 58, 0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) { + memcpy(ref_2_dcs[i].mycall, readBuffer2 + 44, 8); + memcpy(ref_2_dcs[i].sfx, readBuffer2 + 52, 4); + ref_2_dcs[i].dcs_rptr_seq = 0; + } + } + } + } + } else if (found) { + if ((readBuffer2[16] & 0x40) != 0) { + for (i = 0; i < 3; i++) { + if (memcmp(old_sid[i].sid, readBuffer2 + 14, 2) == 0) { + if (QSO_DETAILS) + traceit("END from remote g2: streamID=%d,%d, %d bytes from IP=%s\n", + readBuffer2[14],readBuffer2[15],recvlen2,inet_ntoa(fromDst4.sin_addr)); + + memset(old_sid[i].sid, 0x00, 2); + + break; + } + } + } + + /* send the data to the local gateway/repeater */ + sendto(rptr_sock, (char *)readBuffer2 + 2,27,0,(struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + + /* send the data to the donglers */ + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + if (fromDst4.sin_addr.s_addr != inbound_ptr->sin.sin_addr.s_addr) { + sendto(ref_g2_sock, (char *)readBuffer2, 29, 0, + (struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + } + } + + for (i = 0; i < 3; i++) { + if ((to_remote_g2[i].is_connected) && + (to_remote_g2[i].toDst4.sin_addr.s_addr != fromDst4.sin_addr.s_addr) && + (memcmp(to_remote_g2[i].in_streamid, readBuffer2 + 14, 2) == 0)) { + if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) { + /* inform XRF about the source */ + readBuffer2[13] = to_remote_g2[i].from_mod; + + sendto(xrf_g2_sock, (char *)readBuffer2 + 2, 27, 0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) + sendto(ref_g2_sock, (char *)readBuffer2, 29, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) { + memset(dcs_buf, 0x00, 600); + dcs_buf[0] = dcs_buf[1] = dcs_buf[2] = '0'; + dcs_buf[3] = '1'; + dcs_buf[4] = dcs_buf[5] = dcs_buf[6] = 0x00; + memcpy(dcs_buf + 7, to_remote_g2[i].to_call, 8); + dcs_buf[14] = to_remote_g2[i].to_mod; + memcpy(dcs_buf + 15, OWNER, 8); + dcs_buf[22] = to_remote_g2[i].from_mod; + memcpy(dcs_buf + 23, "CQCQCQ ", 8); + memcpy(dcs_buf + 31, ref_2_dcs[i].mycall, 8); + memcpy(dcs_buf + 39, ref_2_dcs[i].sfx, 4); + dcs_buf[43] = readBuffer2[14]; /* streamid0 */ + dcs_buf[44] = readBuffer2[15]; /* streamid1 */ + dcs_buf[45] = readBuffer2[16]; /* cycle sequence */ + memcpy(dcs_buf + 46, readBuffer2 + 17, 12); + + dcs_buf[58] = (ref_2_dcs[i].dcs_rptr_seq >> 0) & 0xff; + dcs_buf[59] = (ref_2_dcs[i].dcs_rptr_seq >> 8) & 0xff; + dcs_buf[60] = (ref_2_dcs[i].dcs_rptr_seq >> 16) & 0xff; + + ref_2_dcs[i].dcs_rptr_seq ++; + + dcs_buf[61] = 0x01; + dcs_buf[62] = 0x00; + + sendto(dcs_g2_sock, dcs_buf, 100, 0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } + + if ((readBuffer2[16] & 0x40) != 0) { + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + } + break; + } + } + } + } + FD_CLR (ref_g2_sock,&fdset); + } + + if (FD_ISSET(dcs_g2_sock, &fdset)) { + fromlen = sizeof(struct sockaddr_in); + recvlen2 = recvfrom(dcs_g2_sock,(char *)dcs_buf,1000, + 0,(struct sockaddr *)&fromDst4,&fromlen); + + strncpy(ip, inet_ntoa(fromDst4.sin_addr),IP_SIZE); + ip[IP_SIZE] = '\0'; + + /* header, audio */ + if ((dcs_buf[0] == '0') && (dcs_buf[1] == '0') && + (dcs_buf[2] == '0') && (dcs_buf[3] == '1')) { + if (recvlen2 == 100) { + memset(source_stn, ' ', 9); + source_stn[8] = '\0'; + + /* find out our local module */ + for (i = 0; i < 3; i++) { + if ((to_remote_g2[i].is_connected) && + (fromDst4.sin_addr.s_addr = to_remote_g2[i].toDst4.sin_addr.s_addr) && + (memcmp(dcs_buf + 7, to_remote_g2[i].to_call, 7) == 0) && + (to_remote_g2[i].to_mod == dcs_buf[14])) { + memcpy(source_stn, to_remote_g2[i].to_call, 8); + source_stn[7] = to_remote_g2[i].to_mod; + break; + } + } + + /* Is it our local module */ + if (i < 3) { + /* Last Heard */ + if (memcmp(old_sid[i].sid, dcs_buf + 43, 2) != 0) { + if (QSO_DETAILS) + traceit("START from dcs: streamID=%d,%d, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s, source=%.8s\n", + dcs_buf[43],dcs_buf[44], + &dcs_buf[31], + &dcs_buf[39], &dcs_buf[23], + &dcs_buf[7], &dcs_buf[15], + recvlen2,inet_ntoa(fromDst4.sin_addr), source_stn); + + // put user into tmp1 + memcpy(tmp1, dcs_buf + 31, 8); + tmp1[8] = '\0'; + + // delete the user if exists + for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) { + if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) { + dt_lh_list.erase(dt_lh_pos); + break; + } + } + /* Limit?, delete oldest user */ + if (dt_lh_list.size() == LH_MAX_SIZE) { + dt_lh_pos = dt_lh_list.begin(); + dt_lh_list.erase(dt_lh_pos); + } + // add user + time(&tnow); + sprintf(tmp2, "%ld=r%.6s%c%c", tnow, source_stn, source_stn[7], to_remote_g2[i].from_mod); + dt_lh_list[tmp2] = tmp1; + + memcpy(old_sid[i].sid, dcs_buf + 43, 2); + } + + to_remote_g2[i].countdown = TIMEOUT; + + /* new stream ? */ + if ((to_remote_g2[i].in_streamid[0] != dcs_buf[43]) || + (to_remote_g2[i].in_streamid[1] != dcs_buf[44])) { + to_remote_g2[i].in_streamid[0] = dcs_buf[43]; + to_remote_g2[i].in_streamid[1] = dcs_buf[44]; + dcs_seq[i] = 0xff; + + /* generate our header */ + + readBuffer2[0] = (unsigned char)(58 & 0xFF); + readBuffer2[1] = (unsigned char)(58 >> 8 & 0x1F); + readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); + memcpy(readBuffer2 + 2, "DSVT", 4); + readBuffer2[6] = 0x10; + readBuffer2[7] = 0x00; + readBuffer2[8] = 0x00; + readBuffer2[9] = 0x00; + readBuffer2[10] = 0x20; + readBuffer2[11] = 0x00; + readBuffer2[12] = 0x01; + if (to_remote_g2[i].from_mod == 'A') + readBuffer2[13] = 0x03; + else if (to_remote_g2[i].from_mod == 'B') + readBuffer2[13] = 0x01; + else + readBuffer2[13] = 0x02; + readBuffer2[14] = dcs_buf[43]; + readBuffer2[15] = dcs_buf[44]; + readBuffer2[16] = 0x80; + readBuffer2[17] = readBuffer2[18] = readBuffer2[19] = 0x00; + memcpy(readBuffer2 + 20, OWNER, 8); + readBuffer2[27] = to_remote_g2[i].from_mod; + memcpy(readBuffer2 + 28, OWNER, 8); + readBuffer2[35] = 'G'; + memcpy(readBuffer2 + 36, "CQCQCQ ", 8); + memcpy(readBuffer2 + 44, dcs_buf + 31, 8); + memcpy(readBuffer2 + 52, dcs_buf + 39, 4); + calcPFCS(readBuffer2 + 2, 56); + + /* send the header to the local gateway/repeater */ + for (j = 0; j < 5; j++) + sendto(rptr_sock, (char *)readBuffer2 + 2, 56,0, + (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + + /* send the data to the donglers */ + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + for (j = 0; j < 5; j++) { + sendto(ref_g2_sock, (char *)readBuffer2, 58, 0, + (struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + } + } + } + + if ((to_remote_g2[i].in_streamid[0] == dcs_buf[43]) && + (to_remote_g2[i].in_streamid[1] == dcs_buf[44]) && + (dcs_seq[i] != dcs_buf[45])) { + dcs_seq[i] = dcs_buf[45]; + + readBuffer2[0] = (unsigned char)(29 & 0xFF); + readBuffer2[1] = (unsigned char)(29 >> 8 & 0x1F); + readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); + memcpy(readBuffer2 + 2, "DSVT", 4); + readBuffer2[6] = 0x20; + readBuffer2[7] = 0x00; + readBuffer2[8] = 0x00; + readBuffer2[9] = 0x00; + readBuffer2[10] = 0x20; + readBuffer2[11] = 0x00; + readBuffer2[12] = 0x01; + if (to_remote_g2[i].from_mod == 'A') + readBuffer2[13] = 0x03; + else if (to_remote_g2[i].from_mod == 'B') + readBuffer2[13] = 0x01; + else + readBuffer2[13] = 0x02; + readBuffer2[14] = dcs_buf[43]; + readBuffer2[15] = dcs_buf[44]; + readBuffer2[16] = dcs_buf[45]; + memcpy(readBuffer2 + 17, dcs_buf + 46, 12); + + /* send the data to the local gateway/repeater */ + sendto(rptr_sock, (char *)readBuffer2 + 2, 27,0, + (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + + /* send the data to the donglers */ + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + sendto(ref_g2_sock, (char *)readBuffer2, 29, 0, + (struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + } + + if ((dcs_buf[45] & 0x40) != 0) { + memset(old_sid[i].sid, 0x00, 2); + + if (QSO_DETAILS) + traceit("END from dcs: streamID=%d,%d, %d bytes from IP=%s\n", + dcs_buf[43],dcs_buf[44], recvlen2,inet_ntoa(fromDst4.sin_addr)); + + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + dcs_seq[i] = 0xff; + } + } + } + } + } else if ((dcs_buf[0] == 'E') && (dcs_buf[1] == 'E') && + (dcs_buf[2] == 'E') && (dcs_buf[3] == 'E')) + ; + else if (recvlen2 == 35) + ; + else + /* is this a keepalive 22 bytes */ + if (recvlen2 == 22) { + i = -1; + if (dcs_buf[17] == 'A') + i = 0; + else if (dcs_buf[17] == 'B') + i = 1; + else if (dcs_buf[17] == 'C') + i = 2; + + /* It is one of our valid repeaters */ + // DG1HT from OWNER 8 to 7 + if ((i >= 0) && (memcmp(dcs_buf + 9, OWNER, 7) == 0)) { + /* is that the remote system that we asked to connect to? */ + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) && + (memcmp(to_remote_g2[i].to_call, dcs_buf, 7) == 0) && + (to_remote_g2[i].to_mod == dcs_buf[7])) { + if (!to_remote_g2[i].is_connected) { + tracing[i].last_time = time(NULL); + + to_remote_g2[i].is_connected = true; + traceit("Connected from: %.*s\n", 8, dcs_buf); + print_status_file(); + + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + } + to_remote_g2[i].countdown = TIMEOUT; + } + } + } + /* is this a reply to our link/unlink request: 14 bytes */ + else if (recvlen2 == 14) { + i = -1; + if (dcs_buf[8] == 'A') + i = 0; + else if (dcs_buf[8] == 'B') + i = 1; + else if (dcs_buf[8] == 'C') + i = 2; + + /* It is one of our valid repeaters */ + if ((i >= 0) && (memcmp(dcs_buf, OWNER, 8) == 0)) { + /* It is from a remote that we contacted */ + if ((fromDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) && + (to_remote_g2[i].from_mod == dcs_buf[8])) { + if ((to_remote_g2[i].to_mod == dcs_buf[9]) && + (memcmp(dcs_buf + 10, "ACK", 3) == 0)) { + to_remote_g2[i].countdown = TIMEOUT; + if (!to_remote_g2[i].is_connected) { + tracing[i].last_time = time(NULL); + + to_remote_g2[i].is_connected = true; + traceit("Connected from: %.*s\n", 8, to_remote_g2[i].to_call); + print_status_file(); + + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + } + } else if (memcmp(dcs_buf + 10, "NAK", 3) == 0) { + traceit("Link module %c to [%s] %c is unlinked\n", + to_remote_g2[i].from_mod, to_remote_g2[i].to_call, + to_remote_g2[i].to_mod); + + sprintf(notify_msg, "%c_failed_linked.dat_UNLINKED", + to_remote_g2[i].from_mod); + audio_notify(notify_msg); + + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + + print_status_file(); + } + } + } + } + FD_CLR (dcs_g2_sock,&fdset); + } + + if (FD_ISSET(rptr_sock, &fdset)) { + fromlen = sizeof(struct sockaddr_in); + recvlen = recvfrom(rptr_sock,(char *)readBuffer,100, + 0,(struct sockaddr *)&fromRptr,&fromlen); + + if ( ((recvlen == 58) || + (recvlen == 29) || + (recvlen == 32)) && + (readBuffer[6] == 0x73) && + (readBuffer[7] == 0x12) && + ((memcmp(readBuffer,"DSTR", 4) == 0) || (memcmp(readBuffer,"CCS_", 4) == 0)) && + (readBuffer[10] == 0x20) && + (readBuffer[8] == 0x00) && + ((readBuffer[9] == 0x30) || + (readBuffer[9] == 0x13) || + (readBuffer[9] == 0x16)) ) { + + if (recvlen == 58) { + if (QSO_DETAILS) + traceit("START from local g2: cntr=%02x %02x, streamID=%d,%d, flags=%02x:%02x:%02x, my=%.8s, sfx=%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes fromIP=%s\n", + readBuffer[4], readBuffer[5], + readBuffer[14], readBuffer[15], + readBuffer[17], readBuffer[18], readBuffer[19], + readBuffer + 44, readBuffer + 52, readBuffer + 36, + readBuffer + 28, readBuffer + 20, recvlen, inet_ntoa(fromRptr.sin_addr)); + + /* save mycall */ + memcpy(call, readBuffer + 44, 8); + call[8] = '\0'; + + i = -1; + if (readBuffer[35] == 'A') + i = 0; + else if (readBuffer[35] == 'B') + i = 1; + else if (readBuffer[35] == 'C') + i = 2; + + if (i >= 0) { + memcpy(dtmf_mycall[i], readBuffer + 44, 8); + dtmf_mycall[i][8] = '\0'; + + new_group[i] = true; + GPS_seen[i] = false; + + /* Last Heard */ + + //put user into tmp1 + memcpy(tmp1, readBuffer + 44, 8); + tmp1[8] = '\0'; + + // delete the user if exists + for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) { + if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) { + dt_lh_list.erase(dt_lh_pos); + break; + } + } + /* Limit?, delete oldest user */ + if (dt_lh_list.size() == LH_MAX_SIZE) { + dt_lh_pos = dt_lh_list.begin(); + dt_lh_list.erase(dt_lh_pos); + } + /* add user */ + time(&tnow); + if (memcmp(readBuffer,"CCS_", 4) == 0) + sprintf(tmp2, "%ld=r%.7s%c", tnow, "-->CCS ", readBuffer[35]); + else + sprintf(tmp2, "%ld=l%.8s", tnow, readBuffer + 28); + dt_lh_list[tmp2] = tmp1; + + memcpy(readBuffer, "DSTR", 4); + + tracing[i].streamid[0] = readBuffer[14]; + tracing[i].streamid[1] = readBuffer[15]; + tracing[i].last_time = time(NULL); + } + + if ((memcmp(readBuffer + 36, "CQCQCQ", 6) != 0) && (i >= 0)) { + if ((memcmp(readBuffer + 36, OWNER, 7) != 0) && + (readBuffer[43] == LINK_CODE) && + (memcmp(readBuffer + 20, OWNER, 7) == 0) && + (readBuffer[27] == 'G') && + ((readBuffer[17] == 0x00) || + (readBuffer[17] == 0x08) || + (readBuffer[17] == 0x20) || + (readBuffer[17] == 0x28))) { + if (ONLY_LINK_UNLINK && + (link_unlink_user.find(call) == link_unlink_user.end())) { + traceit("link request denied, unauthorized rf user [%s]\n", call); + } else { + memset(temp_repeater, ' ', CALL_SIZE); + memcpy(temp_repeater, readBuffer + 36, CALL_SIZE - 2); + temp_repeater[CALL_SIZE] = '\0'; + + if ((to_remote_g2[i].to_call[0] == '\0') || /* not linked */ + ((to_remote_g2[i].to_call[0] != '\0') && /* waiting for a link reply that may never arrive */ + !to_remote_g2[i].is_connected)) + + g2link(readBuffer[35], temp_repeater, readBuffer[42]); + else if (to_remote_g2[i].is_connected) { + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_already_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + } + } + } else if ((readBuffer[43] == UNLINK_CODE) && + (readBuffer[36] == ' ')) { + if (ONLY_LINK_UNLINK && + (link_unlink_user.find(call) == link_unlink_user.end())) { + traceit("unlink request denied, unauthorized rf user [%s]\n", call); + } else { + if (to_remote_g2[i].to_call[0] != '\0') { + if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) { + /* Check to see if any other local bands are linked to that same IP */ + for (j = 0; j < 3; j++) { + if (j != i) { + if ((to_remote_g2[j].toDst4.sin_addr.s_addr == to_remote_g2[i].toDst4.sin_addr.s_addr) && + (to_remote_g2[j].toDst4.sin_port == htons(RMT_REF_PORT))) { + traceit("Info: Local %c is also linked to %s (different module) %c\n", + to_remote_g2[j].from_mod, + to_remote_g2[j].to_call, to_remote_g2[j].to_mod); + break; + } + } + } + + if (j == 3) { + /* nothing else is linked there, send DISCONNECT */ + queryCommand[0] = 5; + queryCommand[1] = 0; + queryCommand[2] = 24; + queryCommand[3] = 0; + queryCommand[4] = 0; + sendto(ref_g2_sock,(char *)queryCommand,5,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) { + strcpy(unlink_request, OWNER); + unlink_request[8] = to_remote_g2[i].from_mod; + unlink_request[9] = ' '; + unlink_request[10] = '\0'; + + for (j = 0; j < 5; j++) + sendto(xrf_g2_sock,unlink_request, CALL_SIZE + 3,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } else { + strcpy(cmd_2_dcs, OWNER); + cmd_2_dcs[8] = to_remote_g2[i].from_mod; + cmd_2_dcs[9] = ' '; + cmd_2_dcs[10] = '\0'; + memcpy(cmd_2_dcs + 11, to_remote_g2[i].to_call, 8); + + for (j = 0; j < 5; j++) + sendto(dcs_g2_sock, cmd_2_dcs, 19,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } + + traceit("Unlinked from [%s] mod %c\n", + to_remote_g2[i].to_call, to_remote_g2[i].to_mod); + sprintf(notify_msg, "%c_unlinked.dat_UNLINKED", to_remote_g2[i].from_mod); + audio_notify(notify_msg); + + /* now zero out this entry */ + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + + print_status_file(); + } else { + sprintf(notify_msg, "%c_already_unlinked.dat_UNLINKED", readBuffer[35]); + audio_notify(notify_msg); + } + } + } else if ((readBuffer[43] == INFO_CODE) && + (readBuffer[36] == ' ')) { + if (to_remote_g2[i].is_connected) { + strcpy(linked_remote_system, to_remote_g2[i].to_call); + space_p = strchr(linked_remote_system, ' '); + if (space_p) + *space_p = '\0'; + sprintf(notify_msg, "%c_linked.dat_LINKED_%s_%c", + to_remote_g2[i].from_mod, + linked_remote_system, + to_remote_g2[i].to_mod); + audio_notify(notify_msg); + } else { + sprintf(notify_msg, "%c_id.dat_%s_NOT_LINKED", readBuffer[35], OWNER); + audio_notify(notify_msg); + } + } else if ((readBuffer[43] == EXEC_CODE) && + (readBuffer[36] == ' ') && + (admin.find(call) != admin.end())) { // only ADMIN can execute scripts + if (readBuffer[42] != ' ') { + memset(system_cmd, '\0', sizeof(system_cmd)); + snprintf(system_cmd, FILENAME_MAX, "%s/exec_%c.sh %s %c &", + ANNOUNCE_DIR, + readBuffer[42], call, readBuffer[35]); + traceit("Executing %s\n", system_cmd); + system(system_cmd); + } + } else if ((readBuffer[42] == DONGLE_CODE) && + (readBuffer[36] == ' ') && + (admin.find(call) != admin.end())) { // only ADMIN can block dongle users + if (readBuffer[43] == '1') { + MAX_DONGLES = SAVED_MAX_DONGLES; + traceit("Dongle connections are now allowed\n"); + } else if (readBuffer[43] == '0') { + inbound_list.clear(); + MAX_DONGLES = 0; + traceit("Dongle connections are now disallowed\n"); + } + } else if ((readBuffer[43] == FILE_REFRESH_GWYS_CODE) && + (readBuffer[36] == ' ') && + (admin.find(call) != admin.end())) { // only ADMIN can reload gwys.txt + gwy_list.clear(); + load_gwys(GWYS); + } + } + + /* send data to the donglers */ + if (inbound_list.size() > 0) { + readBuffer2[0] = (unsigned char)(58 & 0xFF); + readBuffer2[1] = (unsigned char)(58 >> 8 & 0x1F); + readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); + + memcpy(readBuffer2 + 2, "DSVT", 4); + readBuffer2[6] = 0x10; + readBuffer2[7] = 0x00; + readBuffer2[8] = 0x00; + readBuffer2[9] = 0x00; + readBuffer2[10] = readBuffer[10]; + readBuffer2[11] = readBuffer[11]; + readBuffer2[12] = readBuffer[12]; + readBuffer2[13] = readBuffer[13]; + memcpy(readBuffer2 + 14, readBuffer + 14, 44); + memcpy(readBuffer2 + 20, OWNER, CALL_SIZE); + readBuffer2[27] = readBuffer[35]; + memcpy(readBuffer2 + 28, OWNER, CALL_SIZE); + readBuffer2[35] = 'G'; + memcpy(&readBuffer2[36], "CQCQCQ ", 8); + + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + for (j = 0; j < 5; j++) + sendto(ref_g2_sock, (char *)readBuffer2, 58, + 0,(struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + } + } + + if (i >= 0) { + /* do we have to broadcast ? */ + /* make sure the source is linked to xrf */ + if ((to_remote_g2[i].is_connected) && + (memcmp(to_remote_g2[i].to_call, "XRF", 3) == 0) && + /* only CQCQCQ */ + (memcmp(readBuffer + 20, OWNER, 7) == 0) && + (memcmp(readBuffer + 36, "CQCQCQ", 6) == 0) && + (readBuffer[27] == 'G')) { + brd_from_rptr_idx = 0; + streamid_raw = (readBuffer[14] * 256U) + readBuffer[15]; + + for (j = 0; j < 3; j++) { + if ((j != i) && + (to_remote_g2[j].is_connected) && + (memcmp(to_remote_g2[j].to_call, to_remote_g2[i].to_call, 8) == 0) && + (to_remote_g2[j].to_mod == to_remote_g2[i].to_mod) && + (to_remote_g2[j].to_mod != 'E')) { + memcpy(fromrptr_torptr_brd, "DSVT", 4); + fromrptr_torptr_brd[4] = 0x10; + fromrptr_torptr_brd[5] = 0x00; + fromrptr_torptr_brd[6] = 0x00; + fromrptr_torptr_brd[7] = 0x00; + fromrptr_torptr_brd[8] = readBuffer[10]; + fromrptr_torptr_brd[9] = readBuffer[11]; + fromrptr_torptr_brd[10] = readBuffer[12]; + fromrptr_torptr_brd[11] = readBuffer[13]; + memcpy(fromrptr_torptr_brd + 12, readBuffer + 14, 44); + + streamid_raw ++; + if (streamid_raw == 0) + streamid_raw ++; + fromrptr_torptr_brd[12] = streamid_raw / 256U; + fromrptr_torptr_brd[13] = streamid_raw % 256U; + + memcpy(fromrptr_torptr_brd + 18, OWNER, 8); + fromrptr_torptr_brd[25] = to_remote_g2[j].from_mod; + memcpy(fromrptr_torptr_brd + 26, OWNER, 8); + fromrptr_torptr_brd[33] = 'G'; + + memcpy(fromrptr_torptr_brd + 34, "CQCQCQ ", 8); + + calcPFCS(fromrptr_torptr_brd, 56); + + sendto(xrf_g2_sock, (char *)fromrptr_torptr_brd,56,0, + (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + + brd_from_rptr.from_rptr_streamid[0] = readBuffer[14]; + brd_from_rptr.from_rptr_streamid[1] = readBuffer[15]; + brd_from_rptr.to_rptr_streamid[brd_from_rptr_idx][0] = fromrptr_torptr_brd[12]; + brd_from_rptr.to_rptr_streamid[brd_from_rptr_idx][1] = fromrptr_torptr_brd[13]; + brd_from_rptr_idx ++; + } + } + } + + if (to_remote_g2[i].is_connected) { + if ((memcmp(readBuffer + 20, OWNER, 7) == 0) && + (memcmp(readBuffer + 36, "CQCQCQ", 6) == 0) && + (readBuffer[27] == 'G')) { + to_remote_g2[i].out_streamid[0] = readBuffer[14]; + to_remote_g2[i].out_streamid[1] = readBuffer[15]; + + if ((to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) || + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) { + readBuffer2[0] = (unsigned char)(58 & 0xFF); + readBuffer2[1] = (unsigned char)(58 >> 8 & 0x1F); + readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); + + memcpy(readBuffer2 + 2, "DSVT", 4); + readBuffer2[6] = 0x10; + readBuffer2[7] = 0x00; + readBuffer2[8] = 0x00; + readBuffer2[9] = 0x00; + readBuffer2[10] = readBuffer[10]; + readBuffer2[11] = readBuffer[11]; + readBuffer2[12] = readBuffer[12]; + readBuffer2[13] = readBuffer[13]; + memcpy(readBuffer2 + 14, readBuffer + 14, 44); + memset(readBuffer2 + 20, ' ', CALL_SIZE); + memcpy(readBuffer2 + 20, to_remote_g2[i].to_call, + strlen(to_remote_g2[i].to_call)); + readBuffer2[27] = to_remote_g2[i].to_mod; + memset(readBuffer2 + 28, ' ', CALL_SIZE); + memcpy(readBuffer2 + 28, to_remote_g2[i].to_call, + strlen(to_remote_g2[i].to_call)); + readBuffer2[35] = 'G'; + memcpy(&readBuffer2[36], "CQCQCQ ", 8); + + calcPFCS(readBuffer2 + 2,56); + + if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) { + /* inform XRF about the source */ + readBuffer2[13] = to_remote_g2[i].from_mod; + + for (j = 0; j < 5; j++) + sendto(xrf_g2_sock, (char *)readBuffer2 + 2, 56, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } else { + for (j = 0; j < 5; j++) + sendto(ref_g2_sock, (char *)readBuffer2, 58, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) { + memcpy(rptr_2_dcs[i].mycall, readBuffer + 44, 8); + memcpy(rptr_2_dcs[i].sfx, readBuffer + 52, 4); + rptr_2_dcs[i].dcs_rptr_seq = 0; + } + } + } + } + } else { + if (inbound_list.size() > 0) { + readBuffer2[0] = (unsigned char)(29 & 0xFF); + readBuffer2[1] = (unsigned char)(29 >> 8 & 0x1F); + readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); + + memcpy(readBuffer2 + 2, "DSVT", 4); + readBuffer2[6] = 0x20; + readBuffer2[7] = 0x00; + readBuffer2[8] = 0x00; + readBuffer2[9] = 0x00; + readBuffer2[10] = readBuffer[10]; + readBuffer2[11] = readBuffer[11]; + readBuffer2[12] = readBuffer[12]; + readBuffer2[13] = readBuffer[13]; + memcpy(readBuffer2 + 14, readBuffer + 14, 3); + if (recvlen == 29) + memcpy(readBuffer2 + 17, readBuffer + 17, 12); + else + memcpy(readBuffer2 + 17, readBuffer + 20, 12); + + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + sendto(ref_g2_sock, (char *)readBuffer2, 29, 0, + (struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + } + } + + for (i = 0; i < 3; i++) { + if ((to_remote_g2[i].is_connected) && + (memcmp(to_remote_g2[i].out_streamid, readBuffer + 14, 2) == 0)) { + /* check for broadcast */ + if (memcmp(brd_from_rptr.from_rptr_streamid, readBuffer + 14, 2) == 0) { + memcpy(fromrptr_torptr_brd, "DSVT", 4); + fromrptr_torptr_brd[4] = 0x10; + fromrptr_torptr_brd[5] = 0x00; + fromrptr_torptr_brd[6] = 0x00; + fromrptr_torptr_brd[7] = 0x00; + fromrptr_torptr_brd[8] = readBuffer[10]; + fromrptr_torptr_brd[9] = readBuffer[11]; + fromrptr_torptr_brd[10] = readBuffer[12]; + fromrptr_torptr_brd[11] = readBuffer[13]; + memcpy(fromrptr_torptr_brd + 12, readBuffer + 14, 3); + + if (recvlen == 29) + memcpy(fromrptr_torptr_brd + 15, readBuffer + 17, 12); + else + memcpy(fromrptr_torptr_brd + 15, readBuffer + 20, 12); + + if ((brd_from_rptr.to_rptr_streamid[0][0] != 0x00) || + (brd_from_rptr.to_rptr_streamid[0][1] != 0x00)) { + fromrptr_torptr_brd[12] = brd_from_rptr.to_rptr_streamid[0][0]; + fromrptr_torptr_brd[13] = brd_from_rptr.to_rptr_streamid[0][1]; + sendto(xrf_g2_sock, (char *)fromrptr_torptr_brd,27,0, + (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + } + + if ((brd_from_rptr.to_rptr_streamid[1][0] != 0x00) || + (brd_from_rptr.to_rptr_streamid[1][1] != 0x00)) { + fromrptr_torptr_brd[12] = brd_from_rptr.to_rptr_streamid[1][0]; + fromrptr_torptr_brd[13] = brd_from_rptr.to_rptr_streamid[1][1]; + sendto(xrf_g2_sock, (char *)fromrptr_torptr_brd,27,0, + (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + } + + if ((readBuffer[16] & 0x40) != 0) { + brd_from_rptr.from_rptr_streamid[0] = brd_from_rptr.from_rptr_streamid[1] = 0x00; + brd_from_rptr.to_rptr_streamid[0][0] = brd_from_rptr.to_rptr_streamid[0][1] = 0x00; + brd_from_rptr.to_rptr_streamid[1][0] = brd_from_rptr.to_rptr_streamid[1][1] = 0x00; + brd_from_rptr_idx = 0; + } + } + + if ((to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) || + (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT))) { + readBuffer2[0] = (unsigned char)(29 & 0xFF); + readBuffer2[1] = (unsigned char)(29 >> 8 & 0x1F); + readBuffer2[1] = (unsigned char)(readBuffer2[1] | 0xFFFFFF80); + + memcpy(readBuffer2 + 2, "DSVT", 4); + readBuffer2[6] = 0x20; + readBuffer2[7] = 0x00; + readBuffer2[8] = 0x00; + readBuffer2[9] = 0x00; + readBuffer2[10] = readBuffer[10]; + readBuffer2[11] = readBuffer[11]; + readBuffer2[12] = readBuffer[12]; + readBuffer2[13] = readBuffer[13]; + memcpy(readBuffer2 + 14, readBuffer + 14, 3); + if (recvlen == 29) + memcpy(readBuffer2 + 17, readBuffer + 17, 12); + else + memcpy(readBuffer2 + 17, readBuffer + 20, 12); + + if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) { + /* inform XRF about the source */ + readBuffer2[13] = to_remote_g2[i].from_mod; + + sendto(xrf_g2_sock, (char *)readBuffer2 + 2, 27, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) + sendto(ref_g2_sock, (char *)readBuffer2, 29, + 0,(struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(struct sockaddr_in)); + } else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_DCS_PORT)) { + memset(dcs_buf, 0x00, 600); + dcs_buf[0] = dcs_buf[1] = dcs_buf[2] = '0'; + dcs_buf[3] = '1'; + dcs_buf[4] = dcs_buf[5] = dcs_buf[6] = 0x00; + memcpy(dcs_buf + 7, to_remote_g2[i].to_call, 8); + dcs_buf[14] = to_remote_g2[i].to_mod; + memcpy(dcs_buf + 15, OWNER, 8); + dcs_buf[22] = to_remote_g2[i].from_mod; + memcpy(dcs_buf + 23, "CQCQCQ ", 8); + memcpy(dcs_buf + 31, rptr_2_dcs[i].mycall, 8); + memcpy(dcs_buf + 39, rptr_2_dcs[i].sfx, 4); + dcs_buf[43] = readBuffer[14]; /* streamid0 */ + dcs_buf[44] = readBuffer[15]; /* streamid1 */ + dcs_buf[45] = readBuffer[16]; /* cycle sequence */ + memcpy(dcs_buf + 46, readBuffer + 17, 12); + + dcs_buf[58] = (rptr_2_dcs[i].dcs_rptr_seq >> 0) & 0xff; + dcs_buf[59] = (rptr_2_dcs[i].dcs_rptr_seq >> 8) & 0xff; + dcs_buf[60] = (rptr_2_dcs[i].dcs_rptr_seq >> 16) & 0xff; + + rptr_2_dcs[i].dcs_rptr_seq ++; + + dcs_buf[61] = 0x01; + dcs_buf[62] = 0x00; + + sendto(dcs_g2_sock, dcs_buf, 100, 0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } + + if ((readBuffer[16] & 0x40) != 0) { + to_remote_g2[i].out_streamid[0] = 0x00; + to_remote_g2[i].out_streamid[1] = 0x00; + } + break; + } + } + + for (i = 0; i < 3; i++) { + if (memcmp(tracing[i].streamid, readBuffer + 14, 2) == 0) { + /* update the last time RF user talked */ + tracing[i].last_time = time(NULL); + + if ((readBuffer[16] & 0x40) != 0) { + if (QSO_DETAILS) + traceit("END from local g2: cntr=%02x %02x, streamID=%d,%d, %d bytes\n", + readBuffer[4], readBuffer[5], + readBuffer[14],readBuffer[15],recvlen); + + if (RPTR_ACK) + rptr_ack(i); + + memset(dtmf_mycall[i], 0, sizeof(dtmf_mycall[i])); + new_group[i] = true; + GPS_seen[i] = false; + + tracing[i].streamid[0] = 0x00; + tracing[i].streamid[1] = 0x00; + } else { + if (!GPS_seen[i]) { + if (recvlen == 29) + memcpy(tmp_txt, readBuffer + 26, 3); + else + memcpy(tmp_txt, readBuffer + 29, 3); + + if ((tmp_txt[0] != 0x55) || (tmp_txt[1] != 0x2d) || (tmp_txt[2] != 0x16)) { + if (new_group[i]) { + tmp_txt[0] = tmp_txt[0] ^ 0x70; + header_type = tmp_txt[0] & 0xf0; + + if ((header_type == 0x50) || /* header */ + (header_type == 0xc0)) /* squelch */ + new_group[i] = false; + else if (header_type == 0x30) { /* GPS or GPS id or APRS */ + GPS_seen[i] = true; + new_group[i] = false; + + memcpy(tmp1, dtmf_mycall[i], 8); + tmp1[8] = '\0'; + + // delete the user if exists and it is a local RF entry + p_tmp2 = NULL; + for (dt_lh_pos = dt_lh_list.begin(); dt_lh_pos != dt_lh_list.end(); dt_lh_pos++) { + if (strcmp((char *)dt_lh_pos->second.c_str(), tmp1) == 0) { + strcpy(tmp2, (char *)dt_lh_pos->first.c_str()); + p_tmp2 = strstr(tmp2, "=l"); + if (p_tmp2) { + dt_lh_list.erase(dt_lh_pos); + break; + } + } + } + /* we have tmp1 and tmp2, we have the user and it is already been removed */ + /* add the user with gps indicator g */ + if (p_tmp2) { + *(p_tmp2 + 1) = 'g'; + dt_lh_list[tmp2] = tmp1; + } + } else if (header_type == 0x40) /* ABC text */ + new_group[i] = false; + else + new_group[i] = false; + } else + new_group[i] = true; + } + } + } + break; + } + } + } + } + FD_CLR (rptr_sock,&fdset); + } + } } void audio_notify(char *msg) { - if (!ANNOUNCE) - return; - - short int i = 0; - static char notify_msg[3][64]; - - if (*msg == 'A') - i = 0; - else - if (*msg == 'B') - i = 1; - else - if (*msg == 'C') - i = 2; - - strcpy(notify_msg[i], msg); - - int rc = 0; - pthread_t audio_notify_thread; - pthread_attr_t attr; - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&audio_notify_thread, &attr, audio_notify_run, (void *)(notify_msg[i])); - if (rc != 0) - traceit("failed to start audio_notify thread for mod %c\n", *msg); - pthread_attr_destroy(&attr); - return; + if (!ANNOUNCE) + return; + + short int i = 0; + static char notify_msg[3][64]; + + if (*msg == 'A') + i = 0; + else if (*msg == 'B') + i = 1; + else if (*msg == 'C') + i = 2; + + strcpy(notify_msg[i], msg); + + int rc = 0; + pthread_t audio_notify_thread; + pthread_attr_t attr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&audio_notify_thread, &attr, audio_notify_run, (void *)(notify_msg[i])); + if (rc != 0) + traceit("failed to start audio_notify thread for mod %c\n", *msg); + pthread_attr_destroy(&attr); + return; } static void *audio_notify_run(void *arg) { - char notify_msg[64]; - - strcpy(notify_msg, (char *)arg); - - unsigned short rlen = 0; - size_t nread = 0; - unsigned char dstar_buf[56]; - bool useTEXT = false; - short int TEXT_idx = 0; - char RADIO_ID[21]; - char temp_file[FILENAME_MAX + 1]; - FILE *fp = NULL; - char mod; - char *p = NULL; - u_int16_t streamid_raw = 0; - struct timespec nanos; - unsigned int aseed; - time_t tnow = 0; - struct sigaction act; - - /* example: A_linked.dat_LINKED_TO_XRF005_A */ - /* example: A_unlinked.dat */ - /* example: A_failed_linked.dat */ - - act.sa_handler = sigCatch; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - traceit("audio_notify thread exiting...\n"); - pthread_exit(NULL); - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - traceit("audio_notify thread exiting...\n"); - pthread_exit(NULL); - } - - memset(RADIO_ID, ' ', 20); - RADIO_ID[20] = '\0'; - - mod = notify_msg[0]; - - if ((mod != 'A') && (mod != 'B') && (mod != 'C')) - { - traceit("Invalid module %c in %s\n", mod, notify_msg); - pthread_exit(NULL); - } - - p = strstr(notify_msg, ".dat"); - if (!p) - { - traceit("Incorrect filename in %s\n", notify_msg); - pthread_exit(NULL); - } - - if (p[4] == '_') - { - useTEXT = true; - memcpy(RADIO_ID, p + 5, (strlen(p + 5) > 20)?20:strlen(p + 5)); - for (TEXT_idx = 0; TEXT_idx < 20; TEXT_idx++) - { - RADIO_ID[TEXT_idx] = toupper(RADIO_ID[TEXT_idx]); - if (RADIO_ID[TEXT_idx] == '_') - RADIO_ID[TEXT_idx] = ' '; - } - TEXT_idx = 0; - p[4] = '\0'; - } - else - useTEXT = false; - - sleep(DELAY_BEFORE); - - memset(temp_file, '\0', sizeof(temp_file)); - snprintf(temp_file, FILENAME_MAX, "%s/%s", ANNOUNCE_DIR, notify_msg + 2); - traceit("sending File:[%s], mod:[%c], RADIO_ID=[%s]\n", temp_file, mod, RADIO_ID); - - fp = fopen(temp_file, "rb"); - if (!fp) - { - traceit("Failed to open file %s for reading\n", temp_file); - pthread_exit(NULL); - } - - /* stupid DVTOOL + 4 byte num_of_records */ - nread = fread(dstar_buf, 10, 1, fp); - if (nread != 1) - { - traceit("Cant read first 10 bytes from %s\n", temp_file); - fclose(fp); - pthread_exit(NULL); - } - if (memcmp(dstar_buf, "DVTOOL", 6) != 0) - { - traceit("DVTOOL keyword not found in %s\n", temp_file); - fclose(fp); - pthread_exit(NULL); - } - - time(&tnow); - aseed = tnow + pthread_self(); - - while (keep_running) - { - /* 2 byte length */ - nread = fread(&rlen, 2, 1, fp); - if (nread != 1) - break; - - if (rlen == 56) - streamid_raw = (::rand_r(&aseed) % 65535U) + 1U; - else - if (rlen == 27) - ; - else - { - traceit("Not 56-byte and not 27-byte in %s\n", temp_file); - break; - } - - nread = fread(dstar_buf, rlen, 1, fp); - if (nread == 1) - { - if (memcmp(dstar_buf, "DSVT", 4) != 0) - { - traceit("DVST not found in %s\n", temp_file); - break; - } - - if (dstar_buf[8] != 0x20) - { - traceit("Not Voice type in %s\n", temp_file); - break; - } - - if (dstar_buf[4] == 0x10) - ; - else - if (dstar_buf[4] == 0x20) - ; - else - { - traceit("Not a valid record type in %s\n", temp_file); - break; - } - - dstar_buf[12] = streamid_raw / 256U; - dstar_buf[13] = streamid_raw % 256U; - - if (rlen == 56) - { - dstar_buf[15] = 0x01; - - memcpy(dstar_buf + 18, OWNER, CALL_SIZE); - dstar_buf[25] = mod; - - memcpy(dstar_buf + 26, OWNER, CALL_SIZE); - dstar_buf[33] = 'G'; - - memcpy(dstar_buf + 34, "CQCQCQ ", 8); - - memcpy(dstar_buf + 42, OWNER, CALL_SIZE); - dstar_buf[48] = ' '; - dstar_buf[49] = ' '; - - memcpy(dstar_buf + 50, "RPTR", 4); - calcPFCS(dstar_buf, 56); - } - else - { - if (useTEXT) - { - if ((dstar_buf[24] != 0x55) || - (dstar_buf[25] != 0x2d) || - (dstar_buf[26] != 0x16)) - { - if (TEXT_idx == 0) - { - dstar_buf[24] = '@' ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 2) - { - dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 5) - { - dstar_buf[24] = 'A' ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 7) - { - dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 10) - { - dstar_buf[24] = 'B' ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 12) - { - dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 15) - { - dstar_buf[24] = 'C' ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 17) - { - dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - { - dstar_buf[24] = 0x70; - dstar_buf[25] = 0x4f; - dstar_buf[26] = 0x93; - } - } - } - } - (void)sendto(rptr_sock, (char *)dstar_buf,rlen,0, - (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); - } - nanos.tv_sec = 0; - nanos.tv_nsec = DELAY_BETWEEN * 1000000; - nanosleep(&nanos,0); - } - fclose(fp); - traceit("finished sending File to mod:[%c]\n", mod); - pthread_exit(NULL); + char notify_msg[64]; + + strcpy(notify_msg, (char *)arg); + + unsigned short rlen = 0; + size_t nread = 0; + unsigned char dstar_buf[56]; + bool useTEXT = false; + short int TEXT_idx = 0; + char RADIO_ID[21]; + char temp_file[FILENAME_MAX + 1]; + FILE *fp = NULL; + char mod; + char *p = NULL; + u_int16_t streamid_raw = 0; + struct timespec nanos; + unsigned int aseed; + time_t tnow = 0; + struct sigaction act; + + /* example: A_linked.dat_LINKED_TO_XRF005_A */ + /* example: A_unlinked.dat */ + /* example: A_failed_linked.dat */ + + act.sa_handler = sigCatch; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + traceit("audio_notify thread exiting...\n"); + pthread_exit(NULL); + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + traceit("audio_notify thread exiting...\n"); + pthread_exit(NULL); + } + + memset(RADIO_ID, ' ', 20); + RADIO_ID[20] = '\0'; + + mod = notify_msg[0]; + + if ((mod != 'A') && (mod != 'B') && (mod != 'C')) { + traceit("Invalid module %c in %s\n", mod, notify_msg); + pthread_exit(NULL); + } + + p = strstr(notify_msg, ".dat"); + if (!p) { + traceit("Incorrect filename in %s\n", notify_msg); + pthread_exit(NULL); + } + + if (p[4] == '_') { + useTEXT = true; + memcpy(RADIO_ID, p + 5, (strlen(p + 5) > 20)?20:strlen(p + 5)); + for (TEXT_idx = 0; TEXT_idx < 20; TEXT_idx++) { + RADIO_ID[TEXT_idx] = toupper(RADIO_ID[TEXT_idx]); + if (RADIO_ID[TEXT_idx] == '_') + RADIO_ID[TEXT_idx] = ' '; + } + TEXT_idx = 0; + p[4] = '\0'; + } else + useTEXT = false; + + sleep(DELAY_BEFORE); + + memset(temp_file, '\0', sizeof(temp_file)); + snprintf(temp_file, FILENAME_MAX, "%s/%s", ANNOUNCE_DIR, notify_msg + 2); + traceit("sending File:[%s], mod:[%c], RADIO_ID=[%s]\n", temp_file, mod, RADIO_ID); + + fp = fopen(temp_file, "rb"); + if (!fp) { + traceit("Failed to open file %s for reading\n", temp_file); + pthread_exit(NULL); + } + + /* stupid DVTOOL + 4 byte num_of_records */ + nread = fread(dstar_buf, 10, 1, fp); + if (nread != 1) { + traceit("Cant read first 10 bytes from %s\n", temp_file); + fclose(fp); + pthread_exit(NULL); + } + if (memcmp(dstar_buf, "DVTOOL", 6) != 0) { + traceit("DVTOOL keyword not found in %s\n", temp_file); + fclose(fp); + pthread_exit(NULL); + } + + time(&tnow); + aseed = tnow + pthread_self(); + + while (keep_running) { + /* 2 byte length */ + nread = fread(&rlen, 2, 1, fp); + if (nread != 1) + break; + + if (rlen == 56) + streamid_raw = (::rand_r(&aseed) % 65535U) + 1U; + else if (rlen == 27) + ; + else { + traceit("Not 56-byte and not 27-byte in %s\n", temp_file); + break; + } + + nread = fread(dstar_buf, rlen, 1, fp); + if (nread == 1) { + if (memcmp(dstar_buf, "DSVT", 4) != 0) { + traceit("DVST not found in %s\n", temp_file); + break; + } + + if (dstar_buf[8] != 0x20) { + traceit("Not Voice type in %s\n", temp_file); + break; + } + + if (dstar_buf[4] == 0x10) + ; + else if (dstar_buf[4] == 0x20) + ; + else { + traceit("Not a valid record type in %s\n", temp_file); + break; + } + + dstar_buf[12] = streamid_raw / 256U; + dstar_buf[13] = streamid_raw % 256U; + + if (rlen == 56) { + dstar_buf[15] = 0x01; + + memcpy(dstar_buf + 18, OWNER, CALL_SIZE); + dstar_buf[25] = mod; + + memcpy(dstar_buf + 26, OWNER, CALL_SIZE); + dstar_buf[33] = 'G'; + + memcpy(dstar_buf + 34, "CQCQCQ ", 8); + + memcpy(dstar_buf + 42, OWNER, CALL_SIZE); + dstar_buf[48] = ' '; + dstar_buf[49] = ' '; + + memcpy(dstar_buf + 50, "RPTR", 4); + calcPFCS(dstar_buf, 56); + } else { + if (useTEXT) { + if ((dstar_buf[24] != 0x55) || + (dstar_buf[25] != 0x2d) || + (dstar_buf[26] != 0x16)) { + if (TEXT_idx == 0) { + dstar_buf[24] = '@' ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 2) { + dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 5) { + dstar_buf[24] = 'A' ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 7) { + dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 10) { + dstar_buf[24] = 'B' ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 12) { + dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 15) { + dstar_buf[24] = 'C' ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 17) { + dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else { + dstar_buf[24] = 0x70; + dstar_buf[25] = 0x4f; + dstar_buf[26] = 0x93; + } + } + } + } + (void)sendto(rptr_sock, (char *)dstar_buf,rlen,0, + (struct sockaddr *)&toLocalg2,sizeof(struct sockaddr_in)); + } + nanos.tv_sec = 0; + nanos.tv_nsec = DELAY_BETWEEN * 1000000; + nanosleep(&nanos,0); + } + fclose(fp); + traceit("finished sending File to mod:[%c]\n", mod); + pthread_exit(NULL); } int main(int argc, char **argv) { - short i, j; - struct sigaction act; - int rc = 0; - char unlink_request[CALL_SIZE + 3]; - inbound_type::iterator pos; - inbound *inbound_ptr; - - char cmd_2_dcs[19]; - - tzset(); - setvbuf(stdout, (char *)NULL, _IOLBF, 0); - - if (argc != 2) - { - traceit("Usage: ./g2_link g2_link.cfg\n"); - return 1; - } - - rc = regcomp(&preg, - "^(([1-9][A-Z])|([A-Z][0-9])|([A-Z][A-Z][0-9]))[0-9A-Z]*[A-Z][ ]*[ A-RT-Z]$", - REG_EXTENDED | REG_NOSUB); - if (rc != 0) - { - traceit("The IRC regular expression is NOT valid\n"); - return 1; - } - - act.sa_handler = sigCatch; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; - if (sigaction(SIGTERM, &act, 0) != 0) - { - traceit("sigaction-TERM failed, error=%d\n", errno); - return 1; - } - if (sigaction(SIGINT, &act, 0) != 0) - { - traceit("sigaction-INT failed, error=%d\n", errno); - return 1; - } - - for (i = 0; i < 3; i++) - { - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - to_remote_g2[i].out_streamid[0] = 0x00; - to_remote_g2[i].out_streamid[1] = 0x00; - } - - brd_from_xrf.xrf_streamid[0] = brd_from_xrf.xrf_streamid[1] = 0x00; - brd_from_xrf.rptr_streamid[0][0] = brd_from_xrf.rptr_streamid[0][1] = 0x00; - brd_from_xrf.rptr_streamid[1][0] = brd_from_xrf.rptr_streamid[1][1] = 0x00; - brd_from_xrf_idx = 0; - - brd_from_rptr.from_rptr_streamid[0] = brd_from_rptr.from_rptr_streamid[1] = 0x00; - brd_from_rptr.to_rptr_streamid[0][0] = brd_from_rptr.to_rptr_streamid[0][1] = 0x00; - brd_from_rptr.to_rptr_streamid[1][0] = brd_from_rptr.to_rptr_streamid[1][1] = 0x00; - brd_from_rptr_idx = 0; - - do - { - /* process configuration file */ - if (!read_config(argv[1])) - { - traceit("Failed to process config file %s\n", argv[1]); - break; - } - print_status_file(); - - /* Open DB */ - if (!load_gwys(GWYS)) - break; - - /* create our server */ - if (!srv_open()) - { - traceit("srv_open() failed\n"); - break; - } - - traceit("g2_link %s initialized...entering processing loop\n", VERSION); - runit(); - traceit("Leaving processing loop...\n"); - - } while (false); - - - /* Clear connections */ - queryCommand[0] = 5; - queryCommand[1] = 0; - queryCommand[2] = 24; - queryCommand[3] = 0; - queryCommand[4] = 0; - for (i = 0; i < 3; i++) - { - if (to_remote_g2[i].to_call[0] != '\0') - { - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) - sendto(ref_g2_sock,(char *)queryCommand,5,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - else - if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) - { - strcpy(unlink_request, OWNER); - unlink_request[8] = to_remote_g2[i].from_mod; - unlink_request[9] = ' '; - unlink_request[10] = '\0'; - for (j = 0; j < 5; j++) - sendto(xrf_g2_sock,unlink_request, CALL_SIZE + 3,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - else - { - strcpy(cmd_2_dcs, OWNER); - cmd_2_dcs[8] = to_remote_g2[i].from_mod; - cmd_2_dcs[9] = ' '; - cmd_2_dcs[10] = '\0'; - memcpy(cmd_2_dcs + 11, to_remote_g2[i].to_call, 8); - - for (j = 0; j < 5; j++) - sendto(dcs_g2_sock, cmd_2_dcs, 19,0, - (struct sockaddr *)&(to_remote_g2[i].toDst4), - sizeof(to_remote_g2[i].toDst4)); - } - } - to_remote_g2[i].to_call[0] = '\0'; - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].from_mod = ' '; - to_remote_g2[i].to_mod = ' '; - to_remote_g2[i].countdown = 0; - to_remote_g2[i].is_connected = false; - to_remote_g2[i].in_streamid[0] = 0x00; - to_remote_g2[i].in_streamid[1] = 0x00; - to_remote_g2[i].out_streamid[0] = 0x00; - to_remote_g2[i].out_streamid[1] = 0x00; - } - - /* tell inbound dongles we are down */ - for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) - { - inbound_ptr = (inbound *)pos->second; - sendto(ref_g2_sock,(char *)queryCommand,5,0, - (struct sockaddr *)&(inbound_ptr->sin), - sizeof(struct sockaddr_in)); - } - inbound_list.clear(); - - print_status_file(); - srv_close(); - traceit("g2_link exiting\n"); - - return 0; + short i, j; + struct sigaction act; + int rc = 0; + char unlink_request[CALL_SIZE + 3]; + inbound_type::iterator pos; + inbound *inbound_ptr; + + char cmd_2_dcs[19]; + + tzset(); + setvbuf(stdout, (char *)NULL, _IOLBF, 0); + + if (argc != 2) { + traceit("Usage: ./g2_link g2_link.cfg\n"); + return 1; + } + + rc = regcomp(&preg, + "^(([1-9][A-Z])|([A-Z][0-9])|([A-Z][A-Z][0-9]))[0-9A-Z]*[A-Z][ ]*[ A-RT-Z]$", + REG_EXTENDED | REG_NOSUB); + if (rc != 0) { + traceit("The IRC regular expression is NOT valid\n"); + return 1; + } + + act.sa_handler = sigCatch; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + if (sigaction(SIGTERM, &act, 0) != 0) { + traceit("sigaction-TERM failed, error=%d\n", errno); + return 1; + } + if (sigaction(SIGINT, &act, 0) != 0) { + traceit("sigaction-INT failed, error=%d\n", errno); + return 1; + } + + for (i = 0; i < 3; i++) { + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + to_remote_g2[i].out_streamid[0] = 0x00; + to_remote_g2[i].out_streamid[1] = 0x00; + } + + brd_from_xrf.xrf_streamid[0] = brd_from_xrf.xrf_streamid[1] = 0x00; + brd_from_xrf.rptr_streamid[0][0] = brd_from_xrf.rptr_streamid[0][1] = 0x00; + brd_from_xrf.rptr_streamid[1][0] = brd_from_xrf.rptr_streamid[1][1] = 0x00; + brd_from_xrf_idx = 0; + + brd_from_rptr.from_rptr_streamid[0] = brd_from_rptr.from_rptr_streamid[1] = 0x00; + brd_from_rptr.to_rptr_streamid[0][0] = brd_from_rptr.to_rptr_streamid[0][1] = 0x00; + brd_from_rptr.to_rptr_streamid[1][0] = brd_from_rptr.to_rptr_streamid[1][1] = 0x00; + brd_from_rptr_idx = 0; + + do { + /* process configuration file */ + if (!read_config(argv[1])) { + traceit("Failed to process config file %s\n", argv[1]); + break; + } + print_status_file(); + + /* Open DB */ + if (!load_gwys(GWYS)) + break; + + /* create our server */ + if (!srv_open()) { + traceit("srv_open() failed\n"); + break; + } + + traceit("g2_link %s initialized...entering processing loop\n", VERSION); + runit(); + traceit("Leaving processing loop...\n"); + + } while (false); + + + /* Clear connections */ + queryCommand[0] = 5; + queryCommand[1] = 0; + queryCommand[2] = 24; + queryCommand[3] = 0; + queryCommand[4] = 0; + for (i = 0; i < 3; i++) { + if (to_remote_g2[i].to_call[0] != '\0') { + if (to_remote_g2[i].toDst4.sin_port == htons(RMT_REF_PORT)) + sendto(ref_g2_sock,(char *)queryCommand,5,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + else if (to_remote_g2[i].toDst4.sin_port == htons(RMT_XRF_PORT)) { + strcpy(unlink_request, OWNER); + unlink_request[8] = to_remote_g2[i].from_mod; + unlink_request[9] = ' '; + unlink_request[10] = '\0'; + for (j = 0; j < 5; j++) + sendto(xrf_g2_sock,unlink_request, CALL_SIZE + 3,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } else { + strcpy(cmd_2_dcs, OWNER); + cmd_2_dcs[8] = to_remote_g2[i].from_mod; + cmd_2_dcs[9] = ' '; + cmd_2_dcs[10] = '\0'; + memcpy(cmd_2_dcs + 11, to_remote_g2[i].to_call, 8); + + for (j = 0; j < 5; j++) + sendto(dcs_g2_sock, cmd_2_dcs, 19,0, + (struct sockaddr *)&(to_remote_g2[i].toDst4), + sizeof(to_remote_g2[i].toDst4)); + } + } + to_remote_g2[i].to_call[0] = '\0'; + memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + to_remote_g2[i].from_mod = ' '; + to_remote_g2[i].to_mod = ' '; + to_remote_g2[i].countdown = 0; + to_remote_g2[i].is_connected = false; + to_remote_g2[i].in_streamid[0] = 0x00; + to_remote_g2[i].in_streamid[1] = 0x00; + to_remote_g2[i].out_streamid[0] = 0x00; + to_remote_g2[i].out_streamid[1] = 0x00; + } + + /* tell inbound dongles we are down */ + for (pos = inbound_list.begin(); pos != inbound_list.end(); pos++) { + inbound_ptr = (inbound *)pos->second; + sendto(ref_g2_sock,(char *)queryCommand,5,0, + (struct sockaddr *)&(inbound_ptr->sin), + sizeof(struct sockaddr_in)); + } + inbound_list.clear(); + + print_status_file(); + srv_close(); + traceit("g2_link exiting\n"); + + return 0; } diff --git a/g2link_test.cpp b/g2link_test.cpp index c51d2d2..6f33088 100644 --- a/g2link_test.cpp +++ b/g2link_test.cpp @@ -1,406 +1,383 @@ - -/* - * Copyright (C) 2010 by Scott Lawson KI4LKF - * - * 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. - */ - -/* by KI4LKF */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define VERSION "v3.2" - -static int sockDst = -1; -static struct sockaddr_in toDst; -static void dst_close(); -static bool dst_open(char *ip, int port); -static void calcPFCS(unsigned char rawbytes[58]); - -static time_t tNow = 0; -static short streamid_raw = 0; - -/*** -static char silence[12] = -{ - 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8, - 0x70,0x4f,0x93 -}; -***/ - -static char silence[12] = -{ - 0xfa,0x87,0x1e,0x32,0x30,0x2f,0xea,0x45,0x66, - 0x70,0x4f,0x93 -}; - - -static unsigned short crc_tabccitt[256] = -{ - 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, - 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, - 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, - 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, - 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, - 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, - 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, - 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, - 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, - 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, - 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, - 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, - 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, - 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, - 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, - 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, - 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, - 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, - 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, - 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, - 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, - 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, - 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, - 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, - 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, - 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, - 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, - 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, - 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, - 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, - 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, - 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 -}; - -static void calcPFCS(unsigned char rawbytes[58]) -{ - - unsigned short crc_dstar_ffff = 0xffff; - unsigned short tmp, short_c; - short int i; - - for (i = 17; i < 56 ; i++) - { - short_c = 0x00ff & (unsigned short)rawbytes[i]; - tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; - crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; - } - crc_dstar_ffff = ~crc_dstar_ffff; - tmp = crc_dstar_ffff; - - rawbytes[56] = (unsigned char)(crc_dstar_ffff & 0xff); - rawbytes[57] = (unsigned char)((tmp >> 8) & 0xff); - return; -} - -static bool dst_open(char *ip, int port) -{ - int reuse = 1; - - sockDst = socket(PF_INET,SOCK_DGRAM,0); - if (sockDst == -1) - { - printf("Failed to create DSTAR socket\n"); - return false; - } - if (setsockopt(sockDst,SOL_SOCKET,SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) - { - close(sockDst); sockDst = -1; - printf("setsockopt DSTAR REUSE failed\n"); - return false; - } - memset(&toDst,0,sizeof(struct sockaddr_in)); - toDst.sin_family = AF_INET; - toDst.sin_port = htons(port); - toDst.sin_addr.s_addr = inet_addr(ip); - - fcntl(sockDst,F_SETFL,O_NONBLOCK); - return true; -} - -static void dst_close() -{ - if (sockDst != -1) - { - close(sockDst); - sockDst = -1; - } - return; -} - -int main(int argc, char **argv) -{ - unsigned char dstar_buf[58]; - static unsigned short G2_COUNTER = 0; - unsigned long delay; - char RADIO_ID[21]; - short int i; - - if (argc != 10) - { - printf("Usage: g2link_test \n"); - printf("Example: g2link_test 127.0.0.1 19000 \"HELLO\" KJ4NHF B 20 2 KI4LKF XRF005AL\n"); - printf("Where...\n\n"); - printf(" 127.0.0.1 is the G2 INTERNAL IP of the G2 gateway\n"); - printf(" 19000 is the the G2 INTERNAL port of the G2 gateway\n"); - printf(" HELLO is the text message that we will send, no more than 20 characters\n"); - printf(" Note: the text message will be converted to UPPERCASE\n"); - printf(" KJ4NHF is your dstar repeater callsign\n"); - printf(" B is the local repeater module\n"); - printf(" 20 millisecond delay before each packet is sent\n"); - printf(" 2 second delay before the program starts processing your input \n"); - printf(" KI4LKF is the value of mycall\n"); - printf(" XRF005AL is the value of yrcall, in this case this is a Link command\n\n"); - return 0; - } - - if (strlen(argv[4]) > 6) - { - printf("repeaterCallsign can not be more than 6 characters, %s is invalid\n", argv[4]); - return 0; - } - for (i = 0; i < 6; i++) - argv[4][i] = toupper(argv[4][i]); - - - if (strlen(argv[8]) > 8) - { - printf("MYCALL can not be nore than 8 characters, %s is invalid\n", argv[8]); - return 0; - } - for (i = 0; i < 8; i++) - argv[8][i] = toupper(argv[8][i]); - - - if (strlen(argv[9]) > 8) - { - printf("YRCALL can not be nore than 8 characters, %s is invalid\n", argv[9]); - return 0; - } - for (i = 0; i < 8; i++) - argv[9][i] = toupper(argv[9][i]); - - if ((argv[5][0] != 'A') && (argv[5][0] != 'B') && (argv[5][0] != 'C')) - { - printf("module must be one of A B C\n"); - return 0; - } - - delay = atol(argv[6]) * 1000L; - sleep(atoi(argv[7])); - - memset(RADIO_ID, ' ', 20); - RADIO_ID[20] = '\0'; - memcpy(RADIO_ID, argv[3], (strlen(argv[3]) > 20)?20:strlen(argv[3])); - - /*** - for (i = 0; i < 20; i++) - RADIO_ID[i] = toupper(RADIO_ID[i]); - ***/ - - time(&tNow); - srand(tNow + getpid()); - - if (dst_open(argv[1], atoi(argv[2]))) - { - streamid_raw = (short)(::rand() & 0xFFFF); - memcpy(dstar_buf,"DSTR", 4); - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[6] = 0x73; - dstar_buf[7] = 0x12; - dstar_buf[8] = 0x00; - dstar_buf[9] = 0x30; - dstar_buf[10] = 0x20; - - dstar_buf[11] = 0x00; - dstar_buf[12] = 0x01; - if (argv[5][0] == 'A') - dstar_buf[13] = 0x03; - else - if (argv[5][0] == 'B') - dstar_buf[13] = 0x01; - else - if (argv[5][0] == 'C') - dstar_buf[13] = 0x02; - else - dstar_buf[13] = 0x00; - - dstar_buf[14] = (unsigned char)(streamid_raw & 0xFF); - dstar_buf[15] = (unsigned char)((streamid_raw >> 8) & 0xFF); - dstar_buf[16] = 0x80; - dstar_buf[17] = 0x00; - dstar_buf[18] = 0x00; - dstar_buf[19] = 0x00; - - /* RPT2 */ - memcpy(dstar_buf + 20, argv[4], strlen(argv[4])); - if (strlen(argv[4]) < 6) - memset(dstar_buf + 20 + strlen(argv[4]), ' ', 6 - strlen(argv[4])); - dstar_buf[26] = ' '; - dstar_buf[27] = 'G'; - - /* RPT1 */ - memcpy(dstar_buf + 28, argv[4], strlen(argv[4])); - if (strlen(argv[4]) < 6) - memset(dstar_buf + 28 + strlen(argv[4]), ' ', 6 - strlen(argv[4])); - dstar_buf[34] = ' '; - dstar_buf[35] = argv[5][0]; - - /* YRCALL */ - memcpy(dstar_buf + 36, argv[9], strlen(argv[9])); - if (strlen(argv[9]) < 8) - memset(dstar_buf + 36 + strlen(argv[9]), ' ', 8 - strlen(argv[9])); - - /* MYCALL */ - memcpy(dstar_buf + 44, argv[8], strlen(argv[8])); - if (strlen(argv[8]) < 8) - memset(dstar_buf + 44 + strlen(argv[8]), ' ', 8 - strlen(argv[8])); - - /* suffix */ - memcpy(dstar_buf + 52, " ", 4); - calcPFCS(dstar_buf); - (void)sendto(sockDst,(char *)dstar_buf,58,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[9] = 0x13; - memcpy((char *)dstar_buf + 17, silence, 9); - - /* start sending silence + text */ - - /* SYNC */ - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x00; - dstar_buf[26] = 0x55; - dstar_buf[27] = 0x2d; - dstar_buf[28] = 0x16; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x01; - dstar_buf[26] = '@' ^ 0x70; - dstar_buf[27] = RADIO_ID[0] ^ 0x4f; - dstar_buf[28] = RADIO_ID[1] ^ 0x93; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x02; - dstar_buf[26] = RADIO_ID[2] ^ 0x70; - dstar_buf[27] = RADIO_ID[3] ^ 0x4f; - dstar_buf[28] = RADIO_ID[4] ^ 0x93; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x03; - dstar_buf[26] = 'A' ^ 0x70; - dstar_buf[27] = RADIO_ID[5] ^ 0x4f; - dstar_buf[28] = RADIO_ID[6] ^ 0x93; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x04; - dstar_buf[26] = RADIO_ID[7] ^ 0x70; - dstar_buf[27] = RADIO_ID[8] ^ 0x4f; - dstar_buf[28] = RADIO_ID[9] ^ 0x93; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x05; - dstar_buf[26] = 'B' ^ 0x70; - dstar_buf[27] = RADIO_ID[10] ^ 0x4f; - dstar_buf[28] = RADIO_ID[11] ^ 0x93; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x06; - dstar_buf[26] = RADIO_ID[12] ^ 0x70; - dstar_buf[27] = RADIO_ID[13] ^ 0x4f; - dstar_buf[28] = RADIO_ID[14] ^ 0x93; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x07; - dstar_buf[26] = 'C' ^ 0x70; - dstar_buf[27] = RADIO_ID[15] ^ 0x4f; - dstar_buf[28] = RADIO_ID[16] ^ 0x93; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x08; - dstar_buf[26] = RADIO_ID[17] ^ 0x70; - dstar_buf[27] = RADIO_ID[18] ^ 0x4f; - dstar_buf[28] = RADIO_ID[19] ^ 0x93; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - dstar_buf[16] = 0x09 | 0x40; - - memset((char *)dstar_buf + 17, '\0', 9); - - dstar_buf[26] = 0x70; - dstar_buf[27] = 0x4f; - dstar_buf[28] = 0x93; - (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - usleep(delay); - - dst_close(); - } - - printf("g2link_test exiting...\n"); - return 0; -} + +/* + * Copyright (C) 2010 by Scott Lawson KI4LKF + * + * 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. + */ + +/* by KI4LKF */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define VERSION "v3.2" + +static int sockDst = -1; +static struct sockaddr_in toDst; +static void dst_close(); +static bool dst_open(char *ip, int port); +static void calcPFCS(unsigned char rawbytes[58]); + +static time_t tNow = 0; +static short streamid_raw = 0; + +//static unsigned char silence[12] = { 0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8,0x70,0x4f,0x93 }; +static unsigned char silence[12] = { 0xfa,0x87,0x1e,0x32,0x30,0x2f,0xea,0x45,0x66,0x70,0x4f,0x93 }; + + +static unsigned short crc_tabccitt[256] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 +}; + +static void calcPFCS(unsigned char rawbytes[58]) +{ + + unsigned short crc_dstar_ffff = 0xffff; + unsigned short tmp, short_c; + short int i; + + for (i = 17; i < 56 ; i++) { + short_c = 0x00ff & (unsigned short)rawbytes[i]; + tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; + crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; + } + crc_dstar_ffff = ~crc_dstar_ffff; + tmp = crc_dstar_ffff; + + rawbytes[56] = (unsigned char)(crc_dstar_ffff & 0xff); + rawbytes[57] = (unsigned char)((tmp >> 8) & 0xff); + return; +} + +static bool dst_open(char *ip, int port) +{ + int reuse = 1; + + sockDst = socket(PF_INET,SOCK_DGRAM,0); + if (sockDst == -1) { + printf("Failed to create DSTAR socket\n"); + return false; + } + if (setsockopt(sockDst,SOL_SOCKET,SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) { + close(sockDst); + sockDst = -1; + printf("setsockopt DSTAR REUSE failed\n"); + return false; + } + memset(&toDst,0,sizeof(struct sockaddr_in)); + toDst.sin_family = AF_INET; + toDst.sin_port = htons(port); + toDst.sin_addr.s_addr = inet_addr(ip); + + fcntl(sockDst,F_SETFL,O_NONBLOCK); + return true; +} + +static void dst_close() +{ + if (sockDst != -1) { + close(sockDst); + sockDst = -1; + } + return; +} + +int main(int argc, char **argv) +{ + unsigned char dstar_buf[58]; + static unsigned short G2_COUNTER = 0; + unsigned long delay; + char RADIO_ID[21]; + short int i; + + if (argc != 10) { + printf("Usage: g2link_test \n"); + printf("Example: g2link_test 127.0.0.1 19000 \"HELLO\" KJ4NHF B 20 2 KI4LKF XRF005AL\n"); + printf("Where...\n\n"); + printf(" 127.0.0.1 is the G2 INTERNAL IP of the G2 gateway\n"); + printf(" 19000 is the the G2 INTERNAL port of the G2 gateway\n"); + printf(" HELLO is the text message that we will send, no more than 20 characters\n"); + printf(" Note: the text message will be converted to UPPERCASE\n"); + printf(" KJ4NHF is your dstar repeater callsign\n"); + printf(" B is the local repeater module\n"); + printf(" 20 millisecond delay before each packet is sent\n"); + printf(" 2 second delay before the program starts processing your input \n"); + printf(" KI4LKF is the value of mycall\n"); + printf(" XRF005AL is the value of yrcall, in this case this is a Link command\n\n"); + return 0; + } + + if (strlen(argv[4]) > 6) { + printf("repeaterCallsign can not be more than 6 characters, %s is invalid\n", argv[4]); + return 0; + } + for (i = 0; i < 6; i++) + argv[4][i] = toupper(argv[4][i]); + + + if (strlen(argv[8]) > 8) { + printf("MYCALL can not be nore than 8 characters, %s is invalid\n", argv[8]); + return 0; + } + for (i = 0; i < 8; i++) + argv[8][i] = toupper(argv[8][i]); + + + if (strlen(argv[9]) > 8) { + printf("YRCALL can not be nore than 8 characters, %s is invalid\n", argv[9]); + return 0; + } + for (i = 0; i < 8; i++) + argv[9][i] = toupper(argv[9][i]); + + if ((argv[5][0] != 'A') && (argv[5][0] != 'B') && (argv[5][0] != 'C')) { + printf("module must be one of A B C\n"); + return 0; + } + + delay = atol(argv[6]) * 1000L; + sleep(atoi(argv[7])); + + memset(RADIO_ID, ' ', 20); + RADIO_ID[20] = '\0'; + memcpy(RADIO_ID, argv[3], (strlen(argv[3]) > 20)?20:strlen(argv[3])); + + /*** + for (i = 0; i < 20; i++) + RADIO_ID[i] = toupper(RADIO_ID[i]); + ***/ + + time(&tNow); + srand(tNow + getpid()); + + if (dst_open(argv[1], atoi(argv[2]))) { + streamid_raw = (short)(::rand() & 0xFFFF); + memcpy(dstar_buf,"DSTR", 4); + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[6] = 0x73; + dstar_buf[7] = 0x12; + dstar_buf[8] = 0x00; + dstar_buf[9] = 0x30; + dstar_buf[10] = 0x20; + + dstar_buf[11] = 0x00; + dstar_buf[12] = 0x01; + if (argv[5][0] == 'A') + dstar_buf[13] = 0x03; + else if (argv[5][0] == 'B') + dstar_buf[13] = 0x01; + else if (argv[5][0] == 'C') + dstar_buf[13] = 0x02; + else + dstar_buf[13] = 0x00; + + dstar_buf[14] = (unsigned char)(streamid_raw & 0xFF); + dstar_buf[15] = (unsigned char)((streamid_raw >> 8) & 0xFF); + dstar_buf[16] = 0x80; + dstar_buf[17] = 0x00; + dstar_buf[18] = 0x00; + dstar_buf[19] = 0x00; + + /* RPT2 */ + memcpy(dstar_buf + 20, argv[4], strlen(argv[4])); + if (strlen(argv[4]) < 6) + memset(dstar_buf + 20 + strlen(argv[4]), ' ', 6 - strlen(argv[4])); + dstar_buf[26] = ' '; + dstar_buf[27] = 'G'; + + /* RPT1 */ + memcpy(dstar_buf + 28, argv[4], strlen(argv[4])); + if (strlen(argv[4]) < 6) + memset(dstar_buf + 28 + strlen(argv[4]), ' ', 6 - strlen(argv[4])); + dstar_buf[34] = ' '; + dstar_buf[35] = argv[5][0]; + + /* YRCALL */ + memcpy(dstar_buf + 36, argv[9], strlen(argv[9])); + if (strlen(argv[9]) < 8) + memset(dstar_buf + 36 + strlen(argv[9]), ' ', 8 - strlen(argv[9])); + + /* MYCALL */ + memcpy(dstar_buf + 44, argv[8], strlen(argv[8])); + if (strlen(argv[8]) < 8) + memset(dstar_buf + 44 + strlen(argv[8]), ' ', 8 - strlen(argv[8])); + + /* suffix */ + memcpy(dstar_buf + 52, " ", 4); + calcPFCS(dstar_buf); + (void)sendto(sockDst,(char *)dstar_buf,58,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[9] = 0x13; + memcpy((char *)dstar_buf + 17, silence, 9); + + /* start sending silence + text */ + + /* SYNC */ + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x00; + dstar_buf[26] = 0x55; + dstar_buf[27] = 0x2d; + dstar_buf[28] = 0x16; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x01; + dstar_buf[26] = '@' ^ 0x70; + dstar_buf[27] = RADIO_ID[0] ^ 0x4f; + dstar_buf[28] = RADIO_ID[1] ^ 0x93; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x02; + dstar_buf[26] = RADIO_ID[2] ^ 0x70; + dstar_buf[27] = RADIO_ID[3] ^ 0x4f; + dstar_buf[28] = RADIO_ID[4] ^ 0x93; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x03; + dstar_buf[26] = 'A' ^ 0x70; + dstar_buf[27] = RADIO_ID[5] ^ 0x4f; + dstar_buf[28] = RADIO_ID[6] ^ 0x93; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x04; + dstar_buf[26] = RADIO_ID[7] ^ 0x70; + dstar_buf[27] = RADIO_ID[8] ^ 0x4f; + dstar_buf[28] = RADIO_ID[9] ^ 0x93; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x05; + dstar_buf[26] = 'B' ^ 0x70; + dstar_buf[27] = RADIO_ID[10] ^ 0x4f; + dstar_buf[28] = RADIO_ID[11] ^ 0x93; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x06; + dstar_buf[26] = RADIO_ID[12] ^ 0x70; + dstar_buf[27] = RADIO_ID[13] ^ 0x4f; + dstar_buf[28] = RADIO_ID[14] ^ 0x93; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x07; + dstar_buf[26] = 'C' ^ 0x70; + dstar_buf[27] = RADIO_ID[15] ^ 0x4f; + dstar_buf[28] = RADIO_ID[16] ^ 0x93; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x08; + dstar_buf[26] = RADIO_ID[17] ^ 0x70; + dstar_buf[27] = RADIO_ID[18] ^ 0x4f; + dstar_buf[28] = RADIO_ID[19] ^ 0x93; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + dstar_buf[16] = 0x09 | 0x40; + + memset((char *)dstar_buf + 17, '\0', 9); + + dstar_buf[26] = 0x70; + dstar_buf[27] = 0x4f; + dstar_buf[28] = 0x93; + (void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + usleep(delay); + + dst_close(); + } + + printf("g2link_test exiting...\n"); + return 0; +} diff --git a/g2link_test_audio.cpp b/g2link_test_audio.cpp index f1875b4..7f5d7c6 100644 --- a/g2link_test_audio.cpp +++ b/g2link_test_audio.cpp @@ -29,371 +29,321 @@ static FILE *fp = NULL; static time_t tNow = 0; static short streamid_raw = 0; -static unsigned short crc_tabccitt[256] = -{ - 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, - 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, - 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, - 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, - 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, - 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, - 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, - 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, - 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, - 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, - 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, - 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, - 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, - 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, - 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, - 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, - 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, - 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, - 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, - 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, - 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, - 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, - 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, - 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, - 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, - 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, - 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, - 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, - 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, - 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, - 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, - 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 +static unsigned short crc_tabccitt[256] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 }; static void calcPFCS(unsigned char rawbytes[58]) { - unsigned short crc_dstar_ffff = 0xffff; - unsigned short tmp, short_c; - short int i; - - for (i = 17; i < 56 ; i++) - { - short_c = 0x00ff & (unsigned short)rawbytes[i]; - tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; - crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; - } - crc_dstar_ffff = ~crc_dstar_ffff; - tmp = crc_dstar_ffff; - - rawbytes[56] = (unsigned char)(crc_dstar_ffff & 0xff); - rawbytes[57] = (unsigned char)((tmp >> 8) & 0xff); - return; + unsigned short crc_dstar_ffff = 0xffff; + unsigned short tmp, short_c; + short int i; + + for (i = 17; i < 56 ; i++) { + short_c = 0x00ff & (unsigned short)rawbytes[i]; + tmp = (crc_dstar_ffff & 0x00ff) ^ short_c; + crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp]; + } + crc_dstar_ffff = ~crc_dstar_ffff; + tmp = crc_dstar_ffff; + + rawbytes[56] = (unsigned char)(crc_dstar_ffff & 0xff); + rawbytes[57] = (unsigned char)((tmp >> 8) & 0xff); + return; } static bool dst_open(char *ip, int port) { - int reuse = 1; - - sockDst = socket(PF_INET,SOCK_DGRAM,0); - if (sockDst == -1) - { - printf("Failed to create DSTAR socket\n"); - return false; - } - if (setsockopt(sockDst,SOL_SOCKET,SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) - { - close(sockDst); sockDst = -1; - printf("setsockopt DSTAR REUSE failed\n"); - return false; - } - memset(&toDst,0,sizeof(struct sockaddr_in)); - toDst.sin_family = AF_INET; - toDst.sin_port = htons(port); - toDst.sin_addr.s_addr = inet_addr(ip); - - fcntl(sockDst,F_SETFL,O_NONBLOCK); - return true; + int reuse = 1; + + sockDst = socket(PF_INET,SOCK_DGRAM,0); + if (sockDst == -1) { + printf("Failed to create DSTAR socket\n"); + return false; + } + if (setsockopt(sockDst,SOL_SOCKET,SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) { + close(sockDst); + sockDst = -1; + printf("setsockopt DSTAR REUSE failed\n"); + return false; + } + memset(&toDst,0,sizeof(struct sockaddr_in)); + toDst.sin_family = AF_INET; + toDst.sin_port = htons(port); + toDst.sin_addr.s_addr = inet_addr(ip); + + fcntl(sockDst,F_SETFL,O_NONBLOCK); + return true; } static void dst_close() { - if (sockDst != -1) - { - close(sockDst); - sockDst = -1; - } - return; + if (sockDst != -1) { + close(sockDst); + sockDst = -1; + } + return; } int main(int argc, char **argv) { - unsigned short rlen = 0; - static unsigned short G2_COUNTER = 0; - size_t nread = 0; - unsigned char dstar_buf[56]; - unsigned char rptr_buf[58]; - unsigned long delay; - unsigned short i; - char RADIO_ID[21]; - short int TEXT_idx = 0; - - if (argc != 10) - { - printf("Usage: g2link_test_audio \n"); - printf("Example: g2link_test_audio 127.0.0.1 19000 somefile.dvtool KJ4NHF B 19 2 KI4LKF CQCQCQ\n"); - printf("Where...\n"); - printf(" 127.0.0.1 is the IP address of the local G2\n"); - printf(" 19000 is the port of the INTERNAL G2\n"); - printf(" somefile.dvtool is a dvtool file\n"); - printf(" KJ4NHF is your G2 callsign, dont use KJ4NHF\n"); - printf(" B is one of your modules\n"); - printf(" 19 millisecond delay between each packet\n"); - printf(" 2 second delay before we begin this test\n"); - printf(" mycall is KI4LKF, your personal callsign, do not use KI4LKF\n"); - printf(" yrcall is CQCQCQ\n"); - return 0; - } - - if (strlen(argv[4]) > 6) - { - printf("repeaterCallsign can not be more than 6 characters, %s is invalid\n", argv[4]); - return 0; - } - for (i = 0; i < strlen(argv[4]); i++) - argv[4][i] = toupper(argv[4][i]); - - if ((argv[5][0] != 'A') && (argv[5][0] != 'B') && (argv[5][0] != 'C')) - { - printf("module must be one of A B C\n"); - return 0; - } - - if (strlen(argv[8]) > 8) - { - printf("No more than 8 characters in MYCALL\n"); - return 0; - } - for (i = 0; i < strlen(argv[8]); i++) - argv[8][i] = toupper(argv[8][i]); - - if (strlen(argv[9]) > 8) - { - printf("No more than 8 characters in YRCALL\n"); - return 0; - } - for (i = 0; i < strlen(argv[9]); i++) - argv[9][i] = toupper(argv[9][i]); - - - fp = fopen(argv[3], "rb"); - if (!fp) - { - printf("Failed to open file %s for reading\n", argv[3]); - return 0; - } - - /* stupid DVTOOL + 4 byte num_of_records */ - nread = fread(dstar_buf, 10, 1, fp); - if (nread != 1) - { - printf("Cant read first 10 bytes\n"); - fclose(fp); - return 0; - } - if (memcmp(dstar_buf, "DVTOOL", 6) != 0) - { - printf("DVTOOL not found\n"); - fclose(fp); - return 0; - } - - memset(RADIO_ID, ' ', 20); - RADIO_ID[20] = '\0'; - - memcpy(RADIO_ID, "TEST", 4); - - delay = atol(argv[6]) * 1000L; - sleep(atoi(argv[7])); - - time(&tNow); - srand(tNow + getpid()); - - if (dst_open(argv[1], atoi(argv[2]))) - { - while (true) - { - /* 2 byte length */ - nread = fread(&rlen, 2, 1, fp); - if (nread != 1) - { - printf("End-Of-File\n"); - break; - } - if (rlen == 56) - streamid_raw = (short)(::rand() & 0xFFFF); - else - if (rlen == 27) - ; - else - { - printf("Not 56-byte and not 27-byte\n"); - break; - } - - /* read the packet */ - nread = fread(dstar_buf, rlen, 1, fp); - if (nread == 1) - { - if (memcmp(dstar_buf, "DSVT", 4) != 0) - { - printf("DVST not found\n"); - break; - } - - if (dstar_buf[8] != 0x20) - { - printf("Not Voice type\n"); - break; - } - - if (dstar_buf[4] == 0x10) - ; - else - if (dstar_buf[4] == 0x20) - ; - else - { - printf("Not a valid record type\n"); - break; - } - - if (rlen == 56) - { - memcpy(rptr_buf, "DSTR", 4); - rptr_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - rptr_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - rptr_buf[6] = 0x73; - rptr_buf[7] = 0x12; - rptr_buf[8] = 0x00; - rptr_buf[9] = 0x30; - rptr_buf[10] = 0x20; - memcpy(rptr_buf + 11, dstar_buf + 9, 47); - - rptr_buf[14] = (unsigned char)(streamid_raw & 0xFF); - rptr_buf[15] = (unsigned char)((streamid_raw >> 8) & 0xFF); - - memcpy(rptr_buf + 20, argv[4], strlen(argv[4])); - if (strlen(argv[4]) < 6) - memset(rptr_buf + 20 + strlen(argv[4]), ' ', 6 - strlen(argv[4])); - rptr_buf[26] = ' '; - rptr_buf[27] = 'G'; - - memcpy(rptr_buf + 28, argv[4], strlen(argv[4])); - if (strlen(argv[4]) < 6) - memset(rptr_buf + 28 + strlen(argv[4]), ' ', 6 - strlen(argv[4])); - rptr_buf[34] = ' '; - rptr_buf[35] = argv[5][0]; - - /* yrcall */ - memcpy(rptr_buf + 36, argv[9], strlen(argv[9])); - if (strlen(argv[9]) < 8) - memset(rptr_buf + 36 + strlen(argv[9]), ' ', 8 - strlen(argv[9])); - - /* mycall */ - memcpy(rptr_buf + 44, argv[8], strlen(argv[8])); - if (strlen(argv[8]) < 8) - memset(rptr_buf + 44 + strlen(argv[8]), ' ', 8 - strlen(argv[8])); - - memcpy(rptr_buf + 52, "TEST", 4); - - calcPFCS(rptr_buf); - } - else - { - rptr_buf[5] = (unsigned char)(G2_COUNTER & 0xff); - rptr_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); - rptr_buf[9] = 0x13; - - if ((dstar_buf[24] != 0x55) || - (dstar_buf[25] != 0x2d) || - (dstar_buf[26] != 0x16)) - { - if (TEXT_idx == 0) - { - dstar_buf[24] = '@' ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 2) - { - dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 5) - { - dstar_buf[24] = 'A' ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 7) - { - dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 10) - { - dstar_buf[24] = 'B' ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 12) - { - dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 15) - { - dstar_buf[24] = 'C' ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - if (TEXT_idx == 17) - { - dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; - dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; - dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; - } - else - { - dstar_buf[24] = 0x70; - dstar_buf[25] = 0x4f; - dstar_buf[26] = 0x93; - } - } - memcpy(rptr_buf + 11, dstar_buf + 9, 18); - rptr_buf[14] = (unsigned char)(streamid_raw & 0xFF); - rptr_buf[15] = (unsigned char)((streamid_raw >> 8) & 0xFF); - } - - sendto(sockDst,(char *)rptr_buf,rlen + 2,0, - (struct sockaddr *)&toDst,sizeof(toDst)); - G2_COUNTER ++; - - } - usleep(delay); - } - dst_close(); - } - fclose(fp); - - printf("g2link_test_audio exiting...\n"); - return 0; + unsigned short rlen = 0; + static unsigned short G2_COUNTER = 0; + size_t nread = 0; + unsigned char dstar_buf[56]; + unsigned char rptr_buf[58]; + unsigned long delay; + unsigned short i; + char RADIO_ID[21]; + short int TEXT_idx = 0; + + if (argc != 10) { + printf("Usage: g2link_test_audio \n"); + printf("Example: g2link_test_audio 127.0.0.1 19000 somefile.dvtool KJ4NHF B 19 2 KI4LKF CQCQCQ\n"); + printf("Where...\n"); + printf(" 127.0.0.1 is the IP address of the local G2\n"); + printf(" 19000 is the port of the INTERNAL G2\n"); + printf(" somefile.dvtool is a dvtool file\n"); + printf(" KJ4NHF is your G2 callsign, dont use KJ4NHF\n"); + printf(" B is one of your modules\n"); + printf(" 19 millisecond delay between each packet\n"); + printf(" 2 second delay before we begin this test\n"); + printf(" mycall is KI4LKF, your personal callsign, do not use KI4LKF\n"); + printf(" yrcall is CQCQCQ\n"); + return 0; + } + + if (strlen(argv[4]) > 6) { + printf("repeaterCallsign can not be more than 6 characters, %s is invalid\n", argv[4]); + return 0; + } + for (i = 0; i < strlen(argv[4]); i++) + argv[4][i] = toupper(argv[4][i]); + + if ((argv[5][0] != 'A') && (argv[5][0] != 'B') && (argv[5][0] != 'C')) { + printf("module must be one of A B C\n"); + return 0; + } + + if (strlen(argv[8]) > 8) { + printf("No more than 8 characters in MYCALL\n"); + return 0; + } + for (i = 0; i < strlen(argv[8]); i++) + argv[8][i] = toupper(argv[8][i]); + + if (strlen(argv[9]) > 8) { + printf("No more than 8 characters in YRCALL\n"); + return 0; + } + for (i = 0; i < strlen(argv[9]); i++) + argv[9][i] = toupper(argv[9][i]); + + + fp = fopen(argv[3], "rb"); + if (!fp) { + printf("Failed to open file %s for reading\n", argv[3]); + return 0; + } + + /* stupid DVTOOL + 4 byte num_of_records */ + nread = fread(dstar_buf, 10, 1, fp); + if (nread != 1) { + printf("Cant read first 10 bytes\n"); + fclose(fp); + return 0; + } + if (memcmp(dstar_buf, "DVTOOL", 6) != 0) { + printf("DVTOOL not found\n"); + fclose(fp); + return 0; + } + + memset(RADIO_ID, ' ', 20); + RADIO_ID[20] = '\0'; + + memcpy(RADIO_ID, "TEST", 4); + + delay = atol(argv[6]) * 1000L; + sleep(atoi(argv[7])); + + time(&tNow); + srand(tNow + getpid()); + + if (dst_open(argv[1], atoi(argv[2]))) { + while (true) { + /* 2 byte length */ + nread = fread(&rlen, 2, 1, fp); + if (nread != 1) { + printf("End-Of-File\n"); + break; + } + if (rlen == 56) + streamid_raw = (short)(::rand() & 0xFFFF); + else if (rlen == 27) + ; + else { + printf("Not 56-byte and not 27-byte\n"); + break; + } + + /* read the packet */ + nread = fread(dstar_buf, rlen, 1, fp); + if (nread == 1) { + if (memcmp(dstar_buf, "DSVT", 4) != 0) { + printf("DVST not found\n"); + break; + } + + if (dstar_buf[8] != 0x20) { + printf("Not Voice type\n"); + break; + } + + if (dstar_buf[4] == 0x10) + ; + else if (dstar_buf[4] == 0x20) + ; + else { + printf("Not a valid record type\n"); + break; + } + + if (rlen == 56) { + memcpy(rptr_buf, "DSTR", 4); + rptr_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + rptr_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + rptr_buf[6] = 0x73; + rptr_buf[7] = 0x12; + rptr_buf[8] = 0x00; + rptr_buf[9] = 0x30; + rptr_buf[10] = 0x20; + memcpy(rptr_buf + 11, dstar_buf + 9, 47); + + rptr_buf[14] = (unsigned char)(streamid_raw & 0xFF); + rptr_buf[15] = (unsigned char)((streamid_raw >> 8) & 0xFF); + + memcpy(rptr_buf + 20, argv[4], strlen(argv[4])); + if (strlen(argv[4]) < 6) + memset(rptr_buf + 20 + strlen(argv[4]), ' ', 6 - strlen(argv[4])); + rptr_buf[26] = ' '; + rptr_buf[27] = 'G'; + + memcpy(rptr_buf + 28, argv[4], strlen(argv[4])); + if (strlen(argv[4]) < 6) + memset(rptr_buf + 28 + strlen(argv[4]), ' ', 6 - strlen(argv[4])); + rptr_buf[34] = ' '; + rptr_buf[35] = argv[5][0]; + + /* yrcall */ + memcpy(rptr_buf + 36, argv[9], strlen(argv[9])); + if (strlen(argv[9]) < 8) + memset(rptr_buf + 36 + strlen(argv[9]), ' ', 8 - strlen(argv[9])); + + /* mycall */ + memcpy(rptr_buf + 44, argv[8], strlen(argv[8])); + if (strlen(argv[8]) < 8) + memset(rptr_buf + 44 + strlen(argv[8]), ' ', 8 - strlen(argv[8])); + + memcpy(rptr_buf + 52, "TEST", 4); + + calcPFCS(rptr_buf); + } else { + rptr_buf[5] = (unsigned char)(G2_COUNTER & 0xff); + rptr_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff); + rptr_buf[9] = 0x13; + + if ((dstar_buf[24] != 0x55) || + (dstar_buf[25] != 0x2d) || + (dstar_buf[26] != 0x16)) { + if (TEXT_idx == 0) { + dstar_buf[24] = '@' ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 2) { + dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 5) { + dstar_buf[24] = 'A' ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 7) { + dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 10) { + dstar_buf[24] = 'B' ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 12) { + dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 15) { + dstar_buf[24] = 'C' ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else if (TEXT_idx == 17) { + dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70; + dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f; + dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93; + } else { + dstar_buf[24] = 0x70; + dstar_buf[25] = 0x4f; + dstar_buf[26] = 0x93; + } + } + memcpy(rptr_buf + 11, dstar_buf + 9, 18); + rptr_buf[14] = (unsigned char)(streamid_raw & 0xFF); + rptr_buf[15] = (unsigned char)((streamid_raw >> 8) & 0xFF); + } + + sendto(sockDst,(char *)rptr_buf,rlen + 2,0, + (struct sockaddr *)&toDst,sizeof(toDst)); + G2_COUNTER ++; + + } + usleep(delay); + } + dst_close(); + } + fclose(fp); + + printf("g2link_test_audio exiting...\n"); + return 0; } diff --git a/get_reflectors.sh b/get_reflectors.sh index 461e77c..7854b28 100755 --- a/get_reflectors.sh +++ b/get_reflectors.sh @@ -15,7 +15,9 @@ rm -f gwys.va2uv.txt wget -nv -O gwys.va3uv.txt http://www.va3uv.com/gwys.txt if [ -e gwys.va3uv.txt ]; then - awk '$1~/^REF|XRF/&&$2~/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/{print $1, $2, 20001}' gwys.va3uv.txt > gwys.txt + # Move DPlus and DExtra to port 20001 + awk '$1~/^REF|XRF/{print $1, $2, 20001}' gwys.va3uv.txt > gwys.txt + # Get the DCS reflectors too awk '$1~/^DCS/{print $1, $2, $3}' gwys.va3uv.txt >> gwys.txt else echo "Could not get gateways list from www.va3uv.com!" diff --git a/golay23.cpp b/golay23.cpp index fcde541..5db8617 100644 --- a/golay23.cpp +++ b/golay23.cpp @@ -31,9 +31,9 @@ * * Because of its relatively low length (23), dimension (12) and number of * redundant bits (11), the binary (23,12,7) Golay code can be encoded and - * decoded simply by using look-up tables. The program below uses a 16K + * decoded simply by using look-up tables. The program below uses a 16K * encoding table and an 8K decoding table. - * + * * For more information, suggestions, or other ideas on implementing error * correcting codes, please contact me at (I'm temporarily in Japan, but * below is my U.S. address): @@ -48,7 +48,7 @@ * extended Golay code. * * COPYRIGHT NOTICE: This computer program is free for non-commercial purposes. - * You may implement this program for any non-commercial application. You may + * You may implement this program for any non-commercial application. You may * also implement this program for commercial purposes, provided that you * obtain my written permission. Any modification of this program is covered * by this copyright. @@ -94,17 +94,17 @@ long arr2int(int *a, int r) * array a[1]...a[r], to a long integer \sum_{i=1}^r 2^{a[i]-1}. */ { - int i; - long mul, result = 0, temp; - - for (i=1; i<=r; i++) { - mul = 1; - temp = a[i]-1; - while (temp--) - mul = mul << 1; - result += mul; - } - return(result); + int i; + long mul, result = 0, temp; + + for (i=1; i<=r; i++) { + mul = 1; + temp = a[i]-1; + while (temp--) + mul = mul << 1; + result += mul; + } + return(result); } void nextcomb(int n, int r, int *a) @@ -112,17 +112,17 @@ void nextcomb(int n, int r, int *a) * Calculate next r-combination of an n-set. */ { - int i, j; - - a[r]++; - if (a[r] <= n) - return; - j = r - 1; - while (a[j] == n - r + j) - j--; - for (i = r; i >= j; i--) - a[i] = a[j] + i - j + 1; - return; + int i, j; + + a[r]++; + if (a[r] <= n) + return; + j = r - 1; + while (a[j] == n - r + j) + j--; + for (i = r; i >= j; i--) + a[i] = a[j] + i - j + 1; + return; } long get_syndrome(long pattern) @@ -137,15 +137,15 @@ long get_syndrome(long pattern) */ { // long aux = X22, aux2; - long aux = X22; - - if (pattern >= X11) - while (pattern & MASK12) { - while (!(aux & pattern)) - aux = aux >> 1; - pattern ^= (aux/X11) * GENPOL; - } - return(pattern); + long aux = X22; + + if (pattern >= X11) + while (pattern & MASK12) { + while (!(aux & pattern)) + aux = aux >> 1; + pattern ^= (aux/X11) * GENPOL; + } + return(pattern); } // main() @@ -153,7 +153,7 @@ long get_syndrome(long pattern) // register int i,j; // long temp; // int seed = 133757; -// +// // /* // * --------------------------------------------------------------------- // * Generate ENCODING TABLE @@ -164,13 +164,13 @@ long get_syndrome(long pattern) // * integer whose 23 least significant bits are coded bits: Of these, the // * 12 most significant bits are information bits and the 11 least // * significant bits are redundant bits (systematic encoding). -// * --------------------------------------------------------------------- +// * --------------------------------------------------------------------- // */ // for (pattern = 0; pattern < 4096; pattern++) { // temp = pattern << 11; /* multiply information by X^{11} */ // encoding_table[pattern] = temp + get_syndrome(temp);/* add redundancy */ // } -// +// // /* // * --------------------------------------------------------------------- // * Generate DECODING TABLE @@ -179,18 +179,18 @@ long get_syndrome(long pattern) // * is the most likely error pattern. First an error pattern is generated. // * Then its syndrome is calculated and used as a pointer to the table // * where the error pattern value is stored. -// * --------------------------------------------------------------------- -// * +// * --------------------------------------------------------------------- +// * // * (1) Error patterns of WEIGHT 1 (SINGLE ERRORS) // */ // decoding_table[0] = 0; // decoding_table[1] = 1; -// temp = 1; +// temp = 1; // for (i=2; i<= 23; i++) { // temp *= 2; // decoding_table[get_syndrome(temp)] = temp; // } -// /* +// /* // * (2) Error patterns of WEIGHT 2 (DOUBLE ERRORS) // */ // a[1] = 1; a[2] = 2; @@ -201,7 +201,7 @@ long get_syndrome(long pattern) // temp = arr2int(a,2); // decoding_table[get_syndrome(temp)] = temp; // } -// /* +// /* // * (3) Error patterns of WEIGHT 3 (TRIPLE ERRORS) // */ // a[1] = 1; a[2] = 2; a[3] = 3; @@ -212,7 +212,7 @@ long get_syndrome(long pattern) // temp = arr2int(a,3); // decoding_table[get_syndrome(temp)] = temp; // } -// +// // /* --------------------------------------------------------------------- // * Generate DATA // * --------------------------------------------------------------------- @@ -223,7 +223,7 @@ long get_syndrome(long pattern) // */ // data = random() & 0x00000fff; // printf("data = %#012x\n", data); -// +// // /* // * --------------------------------------------------------------------- // * ENCODING @@ -231,7 +231,7 @@ long get_syndrome(long pattern) // */ // codeword = encoding_table[data]; // printf("codeword = %#012x\n", codeword); -// +// // /* // * --------------------------------------------------------------------- // * ERRORS @@ -241,7 +241,7 @@ long get_syndrome(long pattern) // scanf("%d", &numerr); // for (i = 0; i < numerr; i++) // scanf("%d", &errpos[i]); -// +// // /* // * --------------------------------------------------------------------- // * RECEIVED VECTOR @@ -252,7 +252,7 @@ long get_syndrome(long pattern) // for (i = 0; i < numerr; i++) // recd ^= position[errpos[i]]; // printf("received vector = %#012x\n", recd); -// +// // /* // * --------------------------------------------------------------------- // * DECODING diff --git a/gwys.txt b/gwys.txt index f62457e..3b7ca0a 100644 --- a/gwys.txt +++ b/gwys.txt @@ -17,7 +17,6 @@ REF019 208.87.120.144 20001 REF020 50.199.88.20 20001 REF024 69.41.0.15 20001 REF025 173.10.178.226 20001 -REF026 206.12.104.8 20001 REF027 194.116.29.72 20001 REF028 193.190.240.229 20001 REF029 129.123.7.138 20001 @@ -31,7 +30,6 @@ REF037 208.111.3.181 20001 REF038 66.6.171.227 20001 REF039 208.93.191.20 20001 REF045 195.251.201.194 20001 -REF046 208.111.3.182 20001 REF047 157.7.142.13 20001 REF048 208.88.66.244 20001 REF050 75.147.26.195 20001 @@ -68,7 +66,7 @@ XRF021 74.204.50.67 20001 XRF023 141.75.245.225 20001 XRF025 63.133.189.2 20001 XRF026 139.13.100.34 20001 -XRF027 194.116.29.66 20001 +XRF027 194.116.29.78 20001 XRF028 193.190.240.228 20001 XRF031 83.241.141.245 20001 XRF033 46.226.178.81 20001 @@ -87,11 +85,12 @@ XRF123 213.126.90.100 20001 XRF310 199.167.193.147 20001 XRF333 37.187.103.98 20001 XRF353 94.173.206.53 20001 -XRF444 71.40.84.59 20001 +XRF444 70.125.157.44 20001 +XRF500 125.63.57.138 20001 XRF555 199.167.193.205 20001 +XRF559 98.239.113.175 20001 XRF580 67.20.31.79 20001 XRF603 74.104.179.159 20001 -XRF666 125.63.57.138 20001 XRF719 199.227.117.121 20001 XRF727 108.33.72.83 20001 XRF777 62.167.15.53 20001 @@ -101,3 +100,28 @@ XRF858 198.57.255.30 20001 XRF901 199.167.196.109 20001 XRF905 199.212.121.20 20001 XRF978 74.104.179.159 20001 +DCS001 dcs001.xreflector.net 30051 +DCS002 dcs002.xreflector.net 30051 +DCS003 dcs003.xreflector.net 30051 +DCS004 dcs004.xreflector.net 30051 +DCS005 dcs005.xreflector.net 30051 +DCS006 dcs006.xreflector.net 30051 +DCS007 dcs007.xreflector.net 30051 +DCS008 dcs008.xreflector.net 30051 +DCS009 dcs009.xreflector.net 30051 +DCS010 dcs010.xreflector.net 30051 +DCS011 dcs011.xreflector.net 30051 +DCS012 dcs012.xreflector.net 30051 +DCS013 dcs013.xreflector.net 30051 +DCS014 dcs014.xreflector.net 30051 +DCS015 dcs015.xreflector.net 30051 +DCS016 dcs016.xreflector.net 30051 +DCS017 dcs017.xreflector.net 30051 +DCS018 dcs018.xreflector.net 30051 +DCS019 dcs019.xreflector.net 30051 +DCS020 dcs020.xreflector.net 30051 +DCS021 dcs021.xreflector.net 30051 +DCS022 dcs022.xreflector.net 30051 +DCS023 dcs023.xreflector.net 30051 +DCS024 dcs024.xreflector.net 30051 +DCS025 dcs025.xreflector.net 30051