diff --git a/.vs/ConfigWinRPR/v15/Browse.VC.db b/.vs/ConfigWinRPR/v15/Browse.VC.db deleted file mode 100644 index f2d4dc9..0000000 Binary files a/.vs/ConfigWinRPR/v15/Browse.VC.db and /dev/null differ diff --git a/.vs/ConfigWinRPR/v15/ipch/AutoPCH/2888e545bd29f298/CONFIGWINRPR.ipch b/.vs/ConfigWinRPR/v15/ipch/AutoPCH/2888e545bd29f298/CONFIGWINRPR.ipch deleted file mode 100644 index ac4d240..0000000 Binary files a/.vs/ConfigWinRPR/v15/ipch/AutoPCH/2888e545bd29f298/CONFIGWINRPR.ipch and /dev/null differ diff --git a/Bpq32-HPLaptop-2.c b/Bpq32-HPLaptop-2.c deleted file mode 100644 index 0308f62..0000000 --- a/Bpq32-HPLaptop-2.c +++ /dev/null @@ -1,6603 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ -// -// 409l Oct 2001 Fix l3timeout for KISS -// -// 409m Oct 2001 Fix Crossband Digi -// -// 409n May 2002 Change error handling on load ext DLL - -// 409p March 2005 Allow Multidigit COM Ports (kiss.c) - -// 409r August 2005 Treat NULL string in Registry as use current directory -// Allow shutdown to close BPQ Applications - -// 409s October 2005 Add DLL:Export entries to API for BPQTNC2 - -// 409t January 2006 -// -// Add API for Perl "GetPerlMsg" -// Add API for BPQ1632 "GETBPQAPI" - returns address of Assembler API routine -// Add Registry Entry "BPQ Directory". If present, overrides "Config File Location" -// Add New API "GetBPQDirectory" - Returns location of config file -// Add New API "ChangeSessionCallsign" - equivalent to "*** linked to" command -// Rename BPQNODES to BPQNODES.dat -// New API "GetAttachedProcesses" - returns number of processes connected. -// Warn if user trys to close Console Window. -// Add Debug entries to record Process Attach/Detach -// Fix recovery following closure of first process - -// 409t Beta 2 February 2006 -// -// Add API Entry "GetPortNumber" -// -// 409u February 2006 -// -// Fix crash if allocate/deallocate called with stream=0 -// Add API to ch -// Display config file path -// Fix saving of Locked Node flag -// Added SAVENODES SYSOP command -// -// 409u 2 March 2006 -// -// Fix SetupBPQDirectory -// Add CopyBPQDirectory (for Basic Programs) -// -// 409u 3 March 2006 -// -// Release streams on DLL unload - -// 409v October 2006 -// -// Support Minimize to Tray for all BPQ progams -// Implement L4 application callsigns - -// 410 November 2006 -// -// Modified to compile with C++ 2005 Express Edition -// Make MCOM MTX MMASK local variables -// -// 410a January 2007 -// -// Add program name to Attach-Detach messages -// Attempt to detect processes which have died -// Fix bug in NETROM and IFrame decode which would cause crash if frame was corrupt -// Add BCALL - origin call for Beacons -// Fix KISS ACKMODE ACK processing -// - -// 410b November 2007 -// -// Allow CTEXT of up to 510, and enforce PACLEN, fragmenting if necessary - -// 410c December 2007 - -// Fix problem with NT introduced in V410a -// Display location of DLL on Console - -// 410d January 2008 - -// Fix crash in DLL Init caused by long path to program -// Invoke Appl2 alias on C command (if enabled) -// Allow C command to be disabled -// Remove debug trap in GETRAWFRAME -// Validate Alias of directly connected node, mainly for KPC3 DISABL Problem -// Move Port statup code out of DLLInit (mainly for perl) -// Changes to allow Load/Unload of bpq32.dll by appl -// CloseBPQ32 API added -// Ext Driver Close routes called -// Changes to release Mutex - -// 410e May 2008 - -// Fix missing SSID on last call of UNPROTO string (CONVTOAX25 in main.asm) -// Fix VCOM Driver (RX Len was 1 byte too long) -// Fix possible crash on L4CODE if L4DACK received out of sequence -// Add basic IP decoding - -// 410f October 2008 - -// Add IP Gateway -// Add Multiport DIGI capability -// Add GetPortDescription API -// Fix potential hangs if RNR lost -// Fix problem if External driver failes to load -// Put pushad/popad round _INITIALISEPORTS (main.asm) -// Add APIs GetApplCallVB and GetPortDescription (mainly for RMS) -// Ensure Route Qual is updated if Port Qual changed -// Add Reload Option, plus menu items for DUMP and SAVENODES - -// 410g December 2008 - -// Restore API Exports BPQHOSTAPIPTR and MONDECODEPTR (accidentally deleted) -// Fix changed init of BPQDirectory (accidentally changed) -// Fix Checks for lost processes (accidentally deleted) -// Support HDLC Cards on W2K and above -// Delete Tray List entries for crashed processes -// Add Option to NODES command to sort by Callsign -// Add options to save or clear BPQNODES before Reconfig. -// Fix Reconfig in Win98 -// Monitor buffering tweaks -// Fix Init for large (>64k) tables -// Fix Nodes count in Stats - -// 410h January 2009 - -// Add Start Minimized Option -// Changes to KISS for WIn98 Virtual COM -// Open \\.\com instead of //./COM -// Extra Dignostics - -// 410i Febuary 2009 - -// Revert KISS Changes -// Save Window positions - -// 410j June 2009 - -// Fix tidying of window List when program crashed -// Add Max Nodes to Stats -// Don't update APPLnALIAS with received NODES info -// Fix MH display in other timezones -// Fix Possible crash when processing NETROM type Zero frames (eg NRR) -// Basic INP3 Stuff -// Add extra diagnostics to Lost Process detection -// Process Netrom Record Route frames. - -// 410k June 2009 - -// Fix calculation of %retries in extended ROUTES display -// Fix corruption of ROUTES table - -// 410l October 2009 - -// Add GetVersionString API call. -// Add GetPortTableEntry API call -// Keep links to neighbouring nodes open - -// Build 2 - -// Fix PE in NOROUTETODEST (missing POP EBX) - -// 410m November 2009 - -// Changes for PACTOR and WINMOR to support the ATTACH command -// Enable INP3 if configured on a route. -// Fix count of nodes in Stats Display -// Overwrite the worst quality unused route if a call is received from a node not in your -// table when the table is full - -// Build 5 - -// Rig Control Interface -// Limit KAM VHF attach and RADIO commands to authorised programs (MailChat and BPQTerminal) - -// Build 6 - -// Fix reading INP3 Flag from BPQNODES - -// Build 7 - -// Add MAXHOPS and MAXRTT config options - -// Build 8 - -// Fix INP3 deletion of Application Nodes. -// Fix GETCALLSIGN for Pactor Sessions -// Add N Call* to display all SSID's of a call -// Fix flow control on Pactor sessions. - -// Build 9 - -// HDLC Support for XP -// Add AUTH routines - -// Build 10 - -// Fix handling commands split over more that one packet. - -// Build 11 - -// Attach cmd changes for winmor disconnecting state -// Option Interlock Winmor/Pactor ports - -// Build 12 - -// Add APPLS export for winmor -// Handle commands ending CR LF - -// Build 13 - -// Incorporate Rig Control in Kernel - -// Build 14 - -// Fix config reload for Rig COntrol - -// 410n March 2010 - -// Implement C P via PACTOR/WINMOR (for Airmail) - -// Build 2 - -// Don't flip SSID bits on Downlink Connect if uplink is Pactor/WINMOR -// Fix resetting IDLE Timer on Pactor/WINMOR sessions -// Send L4 KEEPLI messages based on IDLETIME - -// 410o July 2010 - -// Read bpqcfg.txt instead of .bin -// Support 32 bit MMASK (Allowing 32 Ports) -// Support 32 bit _APPLMASK (Allowing 32 Applications) -// Allow more commands -// Allow longer command aliases -// Fix logic error in RIGControl Port Initialisation (wasn't always raising RTS and DTR -// Clear RIGControl RTS and DTR on close - -// 410o Build 2 August 2010 - -// Fix couple of errors in config (needed APPLICATIONS and BBSCALL/ALIAS/QUAL) -// Fix Kenwood Rig Control when more than one message received at once. -// Save minimzed state of Rigcontrol Window - -// 410o Build 3 August 2010 - -// Fix reporting of set errors in scan to a random session - -// 410o Build 4 August 2010 - -// Change All xxx Ports are in use to no xxxx Ports are available if there are no sessions with _APPLMASK -// Fix validation of TRANSDELAY - -// 410o Build 5 August 2010 - -// Add Repeater Shift and Set Data Mode options to Rigcontrol (for ICOM only) -// Add WINMOR and SCS Pactor mode control option to RigControl -// Extend INFOMSG to 2000 bytes -// Improve Scan freq change lock (check both SCS and WINMOR Ports) - -// 410o Build 6 September 2010 - -// Incorporate IPGateway in main code. -// Fix GetSessionInfo for Pactor/Winmor Ports -// Add Antenna Selection to RigControl -// Allow Bandwidth options on RADIO command line (as well as in Scan definitions) - -// 410o Build 7 September 2010 - -// Move rigconrtol display to driver windows -// Move rigcontrol config to driver config. -// Allow driver and IPGateway config info in bpq32.cfg -// Move IPGateway, AXIP, VKISS, AGW and WINMOR drivers into bpq32.dll -// Add option to reread IP Gateway config. -// Fix Reinit after process with timer closes (error in TellSessions). - -// 410p Build 2 October 2010 - -// Move KAM and SCS drivers to bpq32.dll - -// 410p Build 3 October 2010 - -// Support more than one axip port. - -// 410p Build 4 October 2010 - -// Dynamically load psapi.dll (for 98/ME) - -// 410p Build 5 October 2010 - -// Incorporate TelnetServer -// Fix AXIP ReRead Config -// Report AXIP accept() fails to syslog, not a popup. - -// 410p Build 6 October 2010 - -// Includes HAL support -// Changes to Pactor Drivers disconnect code -// AXIP now sends with source port = dest port, unless overridden by SOURCEPORT param -// Config now checks for duplicate port definitions -// Add Node Map reporting -// Fix WINMOR deferred disconnect. -// Report Pactor PORTCALL to WL2K instead of RMS Applcall - -// 410p Build 7 October 2010 - -// Add In/Out flag to Map reporting, and report centre, not dial -// Write Telnet log to BPQ Directory -// Add Port to AXIP resolver display -// Send Reports to update.g8bpq.net:81 -// Add support for FT100 to Rigcontrol -// Add timeout to Rigcontrol PTT -// Add Save Registry Command - -// 410p Build 8 November 2010 - -// Add NOKEEPALIVES Port Param -// Renumbered for release - -// 410p Build 9 November 2010 - -// Get Bandwith for map report from WL2K Report Command -// Fix freq display for FT100 (was KHz, not MHz) -// Don't try to change SCS mode whilst initialising -// Allow reporting of Lat/Lon as well as Locator -// Fix Telnet Log Name -// Fix starting with Minimized windows when Minimizetotray isn't set -// Extra Program Error trapping in SessionControl -// Fix reporting same freq with different bandwidths at different times. -// Code changes to support SCS Robust Packet Mode. -// Add FT2000 to Rigcontrol -// Only Send CTEXT to connects to Node (not to connects to an Application Call) - -// Released as Build 10 - -// 410p Build 11 January 2011 - -// Fix MH Update for SCS Outgoing Calls -// Add Direct CMS Access to TelnetServer -// Restructure DISCONNECT processing to run in Timer owning process - -// 410p Build 12 January 2011 - -// Add option for Hardware PTT to use a different com port from the scan port -// Add CAT PTT for Yaesu 897 (and maybe others) -// Fix RMS Packet ports busy after restart -// Fix CMS Telnet with MAXSESSIONS > 10 - -// 410p Build 13 January 2011 - -// Fix loss of buffers in TelnetServer -// Add CMS logging. -// Add non - Promiscuous mode option for BPQETHER - -// 410p Build 14 January 2011 - -// Add support for BPQTermTCP -// Allow more that one FBBPORT -// Allow Telnet FBB mode sessions to send CRLF as well as CR on user and pass msgs -// Add session length to CMS Telnet logging. -// Return Secure Session Flag from GetConnectionInfo -// Show Uptime as dd/hh/mm - -// 4.10.16.17 March 2011 - -// Add "Close all programs" command -// Add BPQ Program Directory registry key -// Use HKEY_CURRENT_USER on Vista and above (and move registry if necessary) -// Time out IP Gateway ARP entries, and only reload ax.25 ARP entries -// Add support for SCS Tracker HF Modes -// Fix WL2K Reporting -// Report Version to WL2K -// Add Driver to support Tracker with multiple sessions (but no scanning, wl2k report, etc) - - -// Above released as 5.0.0.1 - -// 5.2.0.1 - -// Add caching of CMS Server IP addresses -// Initialise TNC State on Pactor Dialogs -// Add Shortened (6 digit) AUTH mode. -// Update MH with all frames (not just I/UI) -// Add IPV6 Support for TelnetServer and AXIP -// Fix TNC OK Test for Tracker -// Fix crash in CMS mode if terminal disconnects while tcp commect in progress -// Add WL2K reporting for Robust Packet -// Add option to suppress WL2K reporting for specific frequencies -// Fix Timeband processing for Rig Control -// New Driver for SCS Tracker allowing multiple connects, so Tracker can be used for user access -// New Driver for V4 TNC - -// 5.2.1.3 October 2011 - -// Combine busy detector on Interlocked Ports (SCS PTC, WINMOR or KAM) -// Improved program error logging -// WL2K reporting changed to new format agreed with Lee Inman - -// 5.2.3.1 January 2012 - -// Connects from the console to an APPLCALL or APPLALIAS now invoke any Command Alias that has been defined. -// Fix reporting of Tracker freqs to WL2K. -// Fix Tracker monitoring setup (sending M UISC) -// Fix possible call/application routing error on RP -// Changes for P4Dragon -// Include APRS Digi/IGate -// Tracker monitoring now includes DIGIS -// Support sending UI frames using SCSTRACKER, SCTRKMULTI and UZ7HO drivers -// Include driver for UZ7HO soundcard modem. -// Accept DRIVER as well as DLLNAME, and COMPORT as well as IOADDR in bpq32.cfg. COMPORT is decimal -// No longer supports separate config files, or BPQTELNETSERVER.exe -// Improved flow control for Telnet CMS Sessions -// Fix handling Config file without a newline after last line -// Add non - Promiscuous mode option for BPQETHER -// Change Console Window to a Dialog Box. -// Fix possible corruption and loss of buffers in Tracker drivers -// Add Beacon After Session option to Tracker and UZ7HO Drivers -// Rewrite RigControl and add "Reread Config Command" -// Support User Mode VCOM Driver for VKISS ports - -// 5.2.4.1 January 2012 - -// Remove CR from Telnet User and Password Prompts -// Add Rigcontrol to UZ7HO driver -// Fix corruption of Free Buffer Count by Rigcontol -// Fix WINMOR and V4 PTT -// Add MultiPSK Driver -// Add SendBeacon export for BPQAPRS -// Add SendChatReport function -// Fix check on length of Port Config ID String with trailing spaces -// Fix interlock when Port Number <> Port Slot -// Add NETROMCALL for L3 Activity -// Add support for APRS Application -// Fix Telnet with FBBPORT and no TCPPORT -// Add Reread APRS Config -// Fix switching to Pactor after scanning in normal packet mode (PTC) - -// 5.2.5.1 February 2012 - -// Stop reading Password file. -// Add extra MPSK commands -// Fix MPSK Transparency -// Make LOCATOR command compulsory -// Add MobileBeaconInterval APRS param -// Send Course and Speed when APRS is using GPS -// Fix Robust Packet reporting in PTC driver -// Fix corruption of some MIC-E APRS packets - -// 5.2.6.1 February 2012 - -// Convert to MDI presentation of BPQ32.dll windows -// Send APRS Status packets -// Send QUIT not EXIT in PTC Init -// Implement new WL2K reporting format and include traffic reporting info in CMS signon -// New WL2KREPORT format -// Prevent loops when APPL alias refers to itself -// Add RigControl for Flex radios and ICOM IC-M710 Marine radio - -// 5.2.7.1 - -// Fix opening more thn one console window on Win98 -// Change method of configuring multiple timelots on WL2K reporting -// Add option to update WK2K Sysop Database -// Add Web server -// Add UIONLY port option - -// 5.2.7.2 - -// Fix handling TelnetServer packets over 500 bytes in normal mode - -// 5.2.7.3 - -// Fix Igate handling packets from UIView - -// 5.2.7.4 - -// Prototype Baycom driver. - -// 5.2.7.5 - -// Set WK2K group ref to MARS (3) if using a MARS service code - -// 5.2.7.7 - -// Check for programs calling CloseBPQ32 when holding semaphore -// Try/Except round Status Timer Processing - -// 5.2.7.8 - -// More Try/Except round Timer Processing - -// 5.2.7.9 - -// Enable RX in Baycom, and remove test loopback in tx - -// 5.2.7.10 - -// Try/Except round ProcessHTTPMessage - -// 5.2.7.11 - -// BAYCOM tweaks - -// 5.2.7.13 - -// Release semaphore after program error in Timer Processing -// Check fro valid dest in REFRESHROUTE - - -// Add TNC-X KISSOPTION (includes the ACKMODE bytes in the checksum( - -// Version 5.2.9.1 Sept 2012 - -// Fix using KISS ports with COMn > 16 -// Add "KISS over UDP" driver for PI as a TNC concentrator - -// Version 6.0.1.1 - -// Convert to C for linux portability -// Try to speed up kiss polling - -// Version 6.0.2.1 - -// Fix operation on Win98 -// Fix callsign error with AGWtoBPQ -// Fix PTT problem with WINMOR -// Fix Reread telnet config -// Add Secure CMS signon -// Fix error in cashing addresses of CMS servers -// Fix Port Number when using Send Raw. -// Fix PE in KISS driver if invalid subchannel received -// Fix Orignal address of beacons -// Speed up Telnet port monitoring. -// Add TNC Emulators -// Add CountFramesQueuedOnStream API -// Limit number of frames that can be queued on a session. -// Add XDIGI feature -// Add Winmor Robust Mode switching for compatibility with new Winmor TNC -// Move most APRS code from BPQAPRS to here -// Stop corruption caused by overlong KISS frames - -// Version 6.0.3.1 - -// Add starting/killing WINMOR TNC on remote host -// Fix Program Error when APRS Item or Object name is same as call of reporting station -// Dont digi a frame that we have already digi'ed -// Add ChangeSessionIdleTime API -// Add WK2KSYSOP Command -// Add IDLETIME Command -// Fix Errors in RELAYAPPL processing -// Fix PE cauaed by invalid Rigcontrol Line - -// Version 6.0.4.1 - -// Add frequency dependent autoconnect appls for SCS Pactor -// Fix DED Monitoring of I and UI with no data -// Include AGWPE Emulator (from AGWtoBPQ) -// accept DEL (Hex 7F) as backspace in Telnet -// Fix re-running resolver on re-read AXIP config -// Speed up processing, mainly for Telnet Sessions -// Fix APRS init on restart of bpq32.exe -// Change to 2 stop bits -// Fix scrolling of WINMOR trace window -// Fix Crash when ueing DED TNC Emulator -// Fix Disconnect when using BPQDED2 Driver with Telnet Sessions -// Allow HOST applications even when CMS option is disabled -// Fix processing of APRS DIGIMAP command with no targets (didn't suppress default settings) - -// Version 6.0.5.1 January 2014 - -// Add UTF8 conversion mode to Telnet (converts non-UTF-8 chars to UTF-8) -// Add "Clear" option to MH command -// Add "Connect to RMS Relay" Option -// Revert to one stop bit on serial ports, explictly set two on FT2000 rig control -// Fix routing of first call in Robust Packet -// Add Options to switch input source on rigs with build in soundcards (sor far only IC7100 and Kenwood 590) -// Add RTS>CAT PTT option for Sound Card rigs -// Add Clear Nodes Option (NODE DEL ALL) -// SCS Pactor can set differeant APPLCALLS when scanning. -// Fix possible Scan hangup after a manual requency change with SCS Pactor -// Accept Scan entry of W0 to disable WINMOR on that frequency -// Fix corruption of NETROMCALL by SIMPLE config command -// Enforce Pactor Levels -// Add Telnet outward connect -// Add Relay/Trimode Emulation -// Fix V4 Driver -// Add PTT Mux -// Add Locked ARP Entries (via bpq32.cfg) -// Fix IDLETIME node command -// Fix STAY param on connect -// Add STAY option to Attach and Application Commands -// Fix crash on copying a large AXIP MH Window -// Fix possible crash when bpq32.exe dies -// Fix DIGIPORT for UI frames - -// Version 6.0.6.1 April 2014 - -// FLDigi Interface -// Fix "All CMS Servers are inaccessible" message so Mail Forwarding ELSE works. -// Validate INP3 messages to try to prevent crash -// Fix possible crash if an overlarge KISS frame is received -// Fix error in AXR command -// Add LF to Telnet Outward Connect signin if NEEDLF added to connect line -// Add CBELL to TNC21 emulator -// Add sent objects and third party messages to APRS Dup List -// Incorporate UIUtil -// Use Memory Mapped file to pass APRS info to BPQAPRS, and process APRS HTTP in BPQ32 -// Improvements to FLDIGI interlocking -// Fix TNC State Display for Tracker -// Cache CMS Addresses on LinBPQ -// Fix count error on DED Driver when handling 256 byte packets -// Add basic SNMP interface for MRTG -// Fix memory loss from getaddrinfo -// Process "BUSY" response from Tracker -// Handle serial port writes that don't accept all the data -// Trap Error 10038 and try to reopen socket -// Fix crash if overlong command line received - -// Version 6.0.7.1 Aptil 2014 -// Fix RigContol with no frequencies for Kenwood and Yaesu -// Add busy check to FLDIGI connects - -// Version 6.0.8.1 August 2014 - -// Use HKEY_CURRENT_USER on all OS versions -// Fix crash when APRS symbol is a space. -// Fixes for FT847 CAT -// Fix display of 3rd byte of FRMR -// Add "DEFAULT ROBUST" and "FORCE ROBUST" commands to SCSPactor Driver -// Fix possible memory corruption in WINMOR driver -// Fix FT2000 Modes -// Use new WL2K reporting system (Web API Based) -// APRS Server now cycles through hosts if DNS returns more than one -// BPQ32 can now start and stop FLDIGI -// Fix loss of AXIP Resolver when running more than one AXIP port - -// Version 6.0.9.1 November 2014 - -// Fix setting NOKEEPALIVE flag on route created from incoming L3 message -// Ignore NODES from locked route with quality 0 -// Fix seting source port in AXIP -// Fix Dual Stack (IPV4/V6) on Linux. -// Fix RELAYSOCK if IPv6 is enabled. -// Add support for FT1000 -// Fix hang when APRS Messaging packet received on RF -// Attempt to normalize Node qualies when stations use widely differing Route qualities -// Add NODES VIA command to display nodes reachable via a specified neighbour -// Fix applying "DisconnectOnClose" setting on HOST API connects (Telnet Server) -// Fix buffering large messages in Telnet Host API -// Fix occasional crash in terminal part line processing -// Add "NoFallback" command to Telnet server to disable "fallback to Relay" -// Improved support for APPLCALL scanning with Pactor -// MAXBUFFS config statement is no longer needed. -// Fix USEAPPLCALLS with Tracker when connect to APPLCALL fails -// Implement LISTEN and CQ commands -// FLDIGI driver can now start FLDIGI on a remote system. -// Add IGNOREUNLOCKEDROUTES parameter -// Fix error if too many Telnet server connections - -// Version 6.0.10.1 Feb 2015 - -// Fix crash if corrupt HTML request received. -// Allow SSID's of 'R' and 'T' on non-ax.25 ports for WL2K Radio Only network. -// Make HTTP server HTTP Version 1.1 complient - use persistent conections and close after 2.5 mins -// Add INP3ONLY flag. -// Fix program error if enter UNPROTO without a destination path -// Show client IP address on HTTP sessions in Telnet Server -// Reduce frequency and number of attempts to connect to routes when Keepalives or INP3 is set -// Add FT990 RigControl support, fix FT1000MP support. -// Support ARMV5 processors -// Changes to support LinBPQ APRS Client -// Add IC7410 to supported Soundcard rigs -// Add CAT PTT to NMEA type (for ICOM Marine Radios_ -// Fix ACKMODE -// Add KISS over TCP -// Support ACKMode on VKISS -// Improved reporting of configuration file format errors -// Experimental driver to support ARQ sessions using UI frames - -// Version 6.0.11.1 September 2015 - -// Fixes for IPGateway configuration and Virtual Circuit Mode -// Separate Portmapper from IPGateway -// Add PING Command -// Add ARDOP Driver -// Add basic APPLCALL support for PTC-PRO/Dragon 7800 Packet (using MYALIAS) -// Add "VeryOldMode" for KAM Version 5.02 -// Add KISS over TCP Slave Mode. -// Support Pactor and Packet on P4Dragon on one port -// Add "Remote Staton Quality" to Web ROUTES display -// Add Virtual Host option for IPGateway NET44 Encap -// Add NAT for local hosts to IPGateway -// Fix setting filter from RADIO command for IC7410 -// Add Memory Channel Scanning for ICOM Radios -// Try to reopen Rig Control port if it fails (could be unplugged USB) -// Fix restoring position of Monitor Window -// Stop Codec on Winmor and ARDOP when an interlocked port is attached (instead of listen false) -// Support APRS beacons in RP mode on Dragon// -// Change Virtual MAC address on IPGateway to include last octet of IP Address -// Fix "NOS Fragmentation" in IP over ax.25 Virtual Circuit Mode -// Fix sending I frames before L2 session is up -// Fix Flow control on Telnet outbound sessions. -// Fix reporting of unterminatred comments in config -// Add option for RigControl to not change mode on FT100/FT990/FT1000 -// Add "Attach and Connect" for Telnet ports - -// Version 6.0.12.1 November 2015 - -// Fix logging of IP addresses for connects to FBBPORT -// Allow lower case user and passwords in Telnet "Attach and Connect" -// Fix possible hang in KISS over TCP Slave mode -// Fix duplicating LinBPQ process if running ARDOP fails -// Allow lower case command aliases and increase alias length to 48 -// Fix saving long IP frames pending ARP resolution -// Fix dropping last entry from a RIP44 message. -// Fix displaying Digis in MH list -// Add port name to Monitor config screen port list -// Fix APRS command display filter and add port filter -// Support port names in BPQTermTCP Monitor config -// Add FINDBUFFS command to dump lost buffers to Debugview/Syslog -// Buffer Web Mgmt Edit Config output -// Add WebMail Support -// Fix not closing APRS Send WX file. -// Add RUN option to APRS Config to start APRS Client -// LinBPQ run FindLostBuffers and exit if QCOUNT < 5 -// Close and reopen ARDOP connection if nothing received for 90 secs -// Add facility to bridge traffic between ports (similar to APRS Bridge but for all frame types) -// Add KISSOPTION TRACKER to set SCS Tracker into KISS Mode - -// 6.0.13.1 - -// Allow /ex to exit UNPROTO mode -// Support ARQBW commands. -// Support IC735 -// Fix sending ARDOP beacons after a busy holdoff -// Enable BPQDED driver to beacon via non-ax.25 ports. -// Fix channel number in UZ7HO monitoring -// Add SATGate mode to APRSIS Code. -// Fix crash caused by overlong user name in telnet logon -// Add option to log L4 connects -// Add AUTOADDQuiet mode to AXIP. -// Add EXCLUDE processing -// Support WinmorControl in UZ7HO driver and fix starting TNC on Linux -// Convert calls in MAP entries to upper case. -// Support Linux COM Port names for APRS GPS -// Fix using NETROM serial protocol on ASYNC Port -// Fix setting MYLEVEL by scanner after manual level change. -// Add DEBUGLOG config param to SCS Pactor Driver to log serial port traffic -// Uue #myl to set SCS Pactor MYLEVEL, and add checklevel command -// Add Multicast RX interface to FLDIGI Driver -// Fix processing application aliases to a connect command. -// Fix Buffer loss if radio connected to PTC rig port but BPQ not configured to use it -// Save backups of bpq32.cfg when editing with Web interface and report old and new length -// Add DD command to SCS Pactor, and use it for forced disconnect. -// Add ARDOP mode select to scan config -// ARDOP changes for ARDOP V 0.5+ -// Flip SSID bits on UZ7HO downlink connects - - -// Version 6.0.14.1 - -// Fix Socket leak in ARDOP and FLDIGI drivers. -// Add option to change CMS Server hostname -// ARDOP Changes for 0.8.0+ -// Discard Terminal Keepalive message (two nulls) in ARDOP command hander -// Allow parameters to be passed to ARDOP TNC when starting it -// Fix Web update of Beacon params -// Retry connects to KISS ports after failure -// Add support for ARDOP Serial Interface Native mode. -// Fix gating APRS-IS Messages to RF -// Fix Beacons when PORTNUM used -// Make sure old monitor flag is cleared for TermTCP sessions -// Add CI-V antenna control for IC746 -// Don't allow ARDOP beacons when connected -// Add support for ARDOP Serial over I2C -// Fix possble crash when using manual RADIO messages -// Save out of sequence L2 frames for possible reuse after retry -// Add KISS command to send KISS control frame to TNC -// Stop removing unused digis from packets sent to APRS-IS - -// Processing of ARDOP PING and PINGACK responses -// Handle changed encoding of WL2K update responses. -// Allow anonymous logon to telnet -// Don't use APPL= for RP Calls in Dragon Single mode. -// Add basic messaging page to APRS Web Server -// Add debug log option to SCSTracker and TrkMulti Driver -// Support REBOOT command on LinBPQ -// Allow LISTEN command on all ports that support ax.25 monitoring - -// Version 6.0.15.1 Feb 2018 - -// partial support for ax.25 V2.2 -// Add MHU and MHL commands and MH filter option -// Fix scan interlock with ARDOP -// Add Input source seiect for IC7300 -// Remove % transparency from web terminal signon message -// Fix L4 Connects In count on stats -// Fix crash caused by corrupt CMSInfo.txt -// Add Input peaks display to ARDOP status window -// Add options to show time in local and distances in KM on APRS Web pages -// Add VARA support -// Fix WINMOR Busy left set when port Suspended -// Add ARDOP-Packet Support -// Add Antenna Switching for TS 480 -// Fix possible crash in Web Terminal -// Support different Code Pages on Console sessions -// Use new Winlink API interface (api.winlink.org) -// Support USB/ACC switching on TS590SG -// Fix scanning when ARDOP or WINMOR is used without an Interlocked Pactor port. -// Set NODECALL to first Application Callsign if NODE=0 and BBSCALL not set. -// Add RIGCONTROL TUNE and POWER commands for some ICOM and Kenwwod rigs -// Fix timing out ARDOP PENDING Lock -// Support mixed case WINLINK Passwords -// Add TUNE and POWER Rigcontol Commands for some radios -// ADD LOCALTIME and DISPKM options to APRS Digi/Igate - -// 6.0.16.1 March 2018 - -// Fix Setting data mode and filter for IC7300 radios -// Add VARA to WL2KREPORT -// Add trace to SCS Tracker status window -// Fix possible hang in IPGATEWAY -// Add BeacontoIS parameter to APRSDIGI. Allows you to stop sending beacons to APRS-IS. -// Fix sending CTEXT on WINMOR sessions - -// 6.0.17.1 November 2018 - -// Change WINMOR Restart after connection to Restart after Failure and add same option to ARDOP and VARA -// Add Abort Connection to WINMOR and VARA Interfaces -// Reinstate accidentally removed CMS Access logging -// Fix MH CLEAR -// Fix corruption of NODE table if NODES received from station with null alias -// Fix loss of buffer if session closed with something in PARTCMDBUFFER -// Fix Spurious GUARD ZONE CORRUPT message in IP Code. -// Remove "reread bpq32.cfg and reconfigure" menu options -// Add support for PTT using CM108 based soundcard interfaces -// Datestamp Telnet log files and delete old Telnet and CMSAcces logs - -// 6.0.18.1 January 2019 - -// Fix validation of NODES broadcasts -// Fix HIDENODES -// Check for failure to reread config on axip reconfigure -// Fix crash if STOPPORT or STARTPORT used on KISS over TCP port -// Send Beacons from BCALL or PORTCALL if configured -// Fix possible corruption of last entry in MH display -// Ensure RTS/DTR is down when opening PTT Port -// Remove RECONFIG command -// Preparations for 64 bit version - -// 6.0.19 Sept 2019 -// Fix UZ7HO interlock -// Add commands to set Centre Frequency and Modem with UZ7HO Soundmodem (on Windows only) -// Add option to save and restore MH lists and SAVEMH command -// Add Frequency (if known) to UZ7HO MH lists -// Add Gateway option to Telnet for PAT -// Try to fix SCS Tracker recovery -// Ensure RTS/DTR is down on CAT port if using that line for PTT -// Experimental APRS Messaging in Kernel -// Add Rigcontrol on remote PC's using WinmorControl -// ADD VARAFM and VARAFM96 WL2KREPORT modes -// Fix WL2K sysop update for new Winlink API -// Fix APRS when using PORTNUM higher than the number of ports -// Add Serial Port Type -// Add option to linbpq to log APRS-IS messages. -// Send WL2K Session Reports -// Drop Tunneled Packets from 44.192 - 44.255 -// Log incoming Telnet Connects -// Add IPV4: and IPV6: overrides on AXIP Resolver. -// Add SessionTimeLimit to HF sessions (ARDOP, SCSPactor, WINMOR, VARA) -// Add RADIO FREQ command to display current frequency - -// 6.0.20 April 2020 - -// Trap and reject YAPP file transfer request. -// Fix possible overrun of TCP to Node Buffer -// Fix possible crash if APRS WX file doesn't have a terminating newline -// Change communication with BPQAPRS.exe to restore old message popup behaviour -// Preparation for 64 bit version -// Improve flow control on SCS Dragon -// Fragment messages from network links to L2 links with smaller paclen -// Change WL2K report rate to once every two hours -// Add PASS, CTEXT and CMSG commands and Stream Switch support to TNC2 Emulator -// Add SessionTimeLimit command to HF drivers (ARDOP, SCSPactor, WINMOR, VARA) -// Add links to Ports Web Manangement Page to open individual Driver windows -// Add STOPPORT/STARTPORT support to ARDOP, KAM and SCSPactor drivers -// Add CLOSE and OPEN RADIO command so Rigcontrol port can be freed fpr other use. -// Don't try to send WL2K Traffic report if Internet is down -// Move WL2K Traffic reporting to a separate thread so it doesn't block if it can't connect to server -// ADD AGWAPPL config command to set application number. AGWMASK is still supported -// Register Node Alias with UZ7HO Driver -// Register calls when UZ7HO TNC Restarts and at intervals afterwards -// Fix crash when no IOADDR or COMPORT in async port definition -// Fix Crash with Paclink-Unix when parsing ; VE7SPR-10 DE N7NIX QTC 1 -// Only apply BBSFLAG=NOBBS to APPPLICATION 1 -// Add RIGREONFIG command -// fix APRS RECONFIG on LinBPQ -// Fix Web Terminal scroll to end problem on some browsers -// Add PTT_SETS_INPUT option for IC7600 -// Add TELRECONFIG command to reread users or whole config -// Enforce PACLEN on UZ7HO ports -// Fix PACLEN on Command Output. -// Retry axip resolver if it fails at startup -// Fix AGWAPI connect via digis -// Fix Select() for Linux in MultiPSK, UZ7HO and V4 drivers -// Limit APRS OBJECT length to 80 chars -// UZ7HO disconnect incoming call if no free streams -// Improve response to REJ (no F) followed by RR (F). -// Try to prevent more than MAXFRAME frames outstanding when transmitting -// Allow more than one instance of APRS on Linux -// Stop APRS digi by originating station -// Send driver window trace to main monitor system -// Improve handling of IPOLL messages -// Fix setting end of address bit on dest call on connects to listening sessions -// Set default BBS and CHAT application number and number of streams on LinBPQ -// Support #include in bpq32.cfg processing - -// Version 6.0.21 14 December 2020 - -// Fix occasional missing newlines in some node command reponses -// More 64 bit fixes -// Add option to stop setting PDUPLEX param in SCSPACTOR -// Try to fix buffer loss -// Remove extra space from APRS position reports -// Suppress VARA IAMALIVE messages -// Add display and control of QtSoundModem modems -// Only send "No CMS connection available" message if fallbacktorelay is set. -// Add HAMLIB backend and emulator support to RIGCONTROL -// Ensure all beacons are sent even with very short beacon intervals -// Add VARA500 WL2K Reporting Mode -// Fix problem with prpcessing frame collector -// Temporarily disable L2 and L4 collectors till I can find problem -// Fix possible problem with interactive RADIO commands not giving a response, -// Incease maximum length of NODE command responses to handle maximum length INFO message, -// Allow WL2KREPORT in CONFIG section of UZ7HO port config. -// Fix program error in processing hamlib frame -// Save RestartAfterFailure option for VARA -// Check callsign has a winlink account before sending WL2KREPORT messages -// Add Bandwidth control to VARA scanning -// Renable L2 collector -// Fix TNCPORT reconnect on Linux -// Add SecureTelnet option to limit telnet outward connect to sysop mode sessions or Application Aliases -// Add option to suppress sending call to application in Telnet HOST API -// Add FT991A support to RigControl -// Use background.jpg for Edit Config page -// Send OK response to SCS Pactor commands starting with # -// Resend ICOM PTT OFF command after 30 seconds -// Add WXCall to APRS config -// Fixes for AEAPactor -// Allow PTTMUX to use real or com0com com ports -// Fix monitoring with AGW Emulator -// Derive approx position from packets on APRS ports with a valid 6 char location -// Fix corruption of APRS message lists if the station table fills up. -// Don't accept empty username or password on Relay sessions. -// Fix occasional empty Nodes broadcasts -// Add Digis to UZ7HO Port MH list -// Add PERMITTEDAPPLS port param -// Fix WK2K Session Record Reporting for Airmail and some Pactor Modes. -// Fix handling AX/IP (proto 93) frames -// Fix possible corruption sending APRS messages -// Allow Telnet connections to be made using Connect command as well as Attach then Connect -// Fix Cancel Sysop Signin -// Save axip resolver info and restore on restart -// Add Transparent mode to Telnet Server HOST API -// Fix Tracker driver if WL2KREPRRT is in main config section -// SNMP InOctets count corrected to include all frames and encoding of zero values fixed. -// Change IP Gateway to exclude handling bits of 44 Net sold to Amazon -// Fix crash in Web terminal when processing very long lines - -// Version 6.0.22.1 August 2021 - -// Fix bug in KAM TNCEMULATOR -// Add WinRPR Driver (DED over TCP) -// Fix handling of VARA config commands FM1200 and FM9600 -// Improve Web Termanal Line folding -// Add StartTNC to WinRPR driver -// Add support for VARA2750 Mode -// Add support for VARA connects via a VARA Digipeater -// Add digis to SCSTracker and WinRPR MHeard -// Separate RIGCONTROL config from PORT config and add RigControl window -// Fix crash when a Windows HID device doesn't have a product_string -// Changes to VARA TNC connection and restart process -// Trigger FALLBACKTORELAY if attempt to connect to all CMS servers fail. -// Fix saving part lines in adif log and Winlink Session reporting -// Add port specific CTEXT -// Add FRMR monitoring to UZ7HO driver -// Add audio input switching for IC7610 -// Include Rigcontrol Support for IC-F8101E -// Process any response to KISS command -// Fix NODE ADD command -// Add noUpdate flag to AXIP MAP -// Fix clearing NOFALLBACK flag in Telnet Server -// Allow connects to RMS Relay running on another host -// Allow use of Power setting in Rigcontol scan lines for Kenwood radios -// Prevent problems caused by using "CMS" as a Node Alias -// Include standard APRS Station pages in code -// Fix VALIDCALLS processing in HF drivers -// Send Netrom Link reports to Node Map -// Add REALTELNET mode to Telnet Outward Connect -// Fix using S (Stay) parameter on Telnet connects when using CMDPORT and C HOST -// Add Default frequency to rigcontrol to set a freq/mode to return to after a connection -// Fix long (> 60 seconds) scan intervals -// Improved debugging of stuck semaphores -// Fix potential securiby bug in BPQ Web server -// Send Chat Updates to chatupdate.g8bpq.net port 81 -// Add ReportRelayTraffic to Telnet config to send WL2K traffic reports for connections to RELAY -// Add experimental Mode reporting -// Add SendTandRtoRelay param to SCS Pactor, ARDOP and VARA drivers to divert calls to CMS for -T and -R to RELAY -// Add UPNP Support - -// Version 6.0.23.1 June 2022 - -// Add option to control which applcalls are enabled in VARA -// Add support for rtl_udp to Rig Control -// Fix Telnet Auto Conneect to Application when using TermTCP or Web Terminal -// Allow setting css styles for Web Terminal -// And Kill TNC and Kill and Restart TNC commands to Web Driver Windows -// More flexible RigControl for split frequency operation, eg for QO100 -// Increase stack size for ProcessHTMLMessage (.11) -// Fix HTML Content-Type on images (.12) -// Add AIS and ADSB Support (.13) -// Compress web pages (.14) -// Change minidump routine and close after program error (.15) -// Add RMS Relay SYNC Mode (.17) -// Changes for compatibility with Winlink Hybrid -// Add Rigcontrol CMD feature to Yaesu code (21) -// More diagnostic code -// Trap potential buffer overrun in ax/tcp code -// Fix possible hang in UZ7HO driver if connect takes a long time to succeed or fail -// Add FLRIG as backend for RigControl (.24) -// Fix bug in compressing some management web pages -// Fix bugs in AGW Emulator (.25) -// Add more PTT_Sets_Freq options for split frequency working (.26) -// Allow RIGCONTROL using Radio Number (Rnn) as well as Port (.26) -// Fix Telnet negotiation and backspace processing (.29) -// Fix VARA Mode change when scanning (.30) -// Add Web Mgmt Log Display (.33) -// Fix crash when connecting to RELAY when CMS=0 (.36) -// Send OK to user for manual freq changes with hamlib or flrig -// Fix Rigcontrol leaving port disabled when using an empty timeband -// Fix processing of backspace in Telnet character processing (.40) -// Increase max size of connect script -// Fix HAMLIB Slave Thread control -// Add processing of VARA mode responses and display of VARA Mode (41) -// Fix crash when VARA session aborted on LinBPQ (43) -// Fix handling port selector (2:call or p2 call) on SCS PTC packet ports (44) -// Include APRS Map web page -// Add Enable/Disable to KAMPACTOR scan control (use P0 or P1) (45) -// Add Basic DRATS interface (46) -// Fix MYCALLS on VARA (49) -// Add FreeData driver (51) -// Add additonal Rigcontrol options for QO100 (51) -// Set Content-Type: application/pdf for pdf files downloaded via web interface (51) -// Fix sending large compressed web messages (52) -// Fix freq display when using flrig or hamlib backends to rigcontrol -// Change VARA Driver to send ABORT when Session Time limit expires -// Add Chat Log to Web Logs display -// Fix possible buffer loss in RigControl -// Allow hosts on local lan to be treated as secure -// Improve validation of data sent to Winlink SessionAdd API call -// Add support for FreeDATA modem. -// Add GetLOC API Call -// Change Leaflet link in aprs map. -// Add Connect Log (64) -// Fix crash when Resolve CMS Servers returns ipv6 addresses -// Fix Reporting P4 sessions to Winlink (68) -// Add support for FreeBSD (68) -// Fix Rigcontrol PTCPORT (69) -// Set TNC Emulator sessions as secure (72) -// Fix not always detecting loss of FLRIG (73) -// Add ? and * wildcards to NODES command (74) -// Add Port RADIO config parameter (74) - -// Version 6.0.24.1 ?? - -// Apply NODES command wildcard to alias as well a call (2) -// Add STOPPORT/STARTPORT to VARA Driver (2) -// Add bandwidth setting to FLRIG interface. (2) -// Fix N VIA (3) -// Fix NODE ADD and NODE DEL (4) -// Improvements to FLRIG Rigcontrol backend (6, 7) -// Fix UZ7HO Window Title Update -// Reject L2 calls with a blank from call (8) -// Update WinRPR Window header with BPQ Port Description (8) -// Fix error in blank call code (9) -// Change web buttons to white on black when pressed (10) -// Fix Port CTEXT paclen on Tracker and WinRPR drivers (11) -// Add RADIO PTT command for testing PTT (11) -// Fix using APPLCALLs on SCSTracker RP call (12) -// Add Rigcntol Web Page (13) -// Fix scan bandwidth change with ARDOPOFDM (13) -// Fix setting Min Pactor Level in SCSPactor (13) -// Fix length of commands sent via CMD_TO_APPL flag (14) -// Add filter by quality option to N display (15) -// Fix VARA Mode reporting to WL2K (16) -// Add FLRIG POWER and TUNE commands (18) -// Fix crash when processing "C " without a call in UZ7HO, FLDIGI or MULTIPSK drivers (19) -// FLDIGI improvements (19) -// Fix hang at start if Telnet port Number > Number of Telnet Streams (20) -// Fix processing C command if first port driver is SCSPACTROR (20) -// Fix crash in UZ7HO driver if bad raw frame received (21) -// Fix using FLARQ chat mode with FLDIGI ddriover (22) -// Fixed to KISSHF driver (23) -// Fix for application buffer loss (24) -// Add Web Sockets auto-refresh option for Webmail index page (25) -// Fix FREEDATA driver for compatibility with FreeData TNC version 0.6.4-alpha.3 (25) -// Add SmartID for bridged frames - Send ID only if packets sent recently (26) -// Add option to save and restore received APRS messages (27) -// Add mechanism to run a user program on certain events (27) -// If BeacontoIS is zero don't Gate any of our messages received locally to APRS-IS (28) -// Add Node Help command (28) -// Add APRS Igate RXOnly option (29) -// Fix RMC message handling with prefixes other than GP (29) -// Add GPSD support for APRS (30) -// Attempt to fix Tracker/WinRPR reconnect code (30) -// Changes to FreeDATA - Don't use deamon and add txlevel and send text commands (31) -// Fix interactive commands in tracker driver (33) -// Fix SESSIONTIMELIMIT processing -// Add STOPPORT/STARTPORT for UZ7HO driver -// Fix processing of extended QtSM 'g' frame (36) -// Allow setting just freq on Yaseu rigs (37) -// Enable KISSHF driver on Linux (40) -// Allow AISHOST and ADSBHOST to be a name as well as an address (41) -// Fix Interlock of incoming UZ7HO connections (41) -// Disable VARA Actions menu if not sysop (41) -// Fix Port CTEXT on UZ7HO B C or D channels (42) -// Fix repeated trigger of SessionTimeLimit (43) -// Fix posible memory corruption in UpateMH (44) -// Add PHG to APRS beacons (45) -// Dont send DM to stations in exclude list(45) -// Improvements to RMS Relay SYNC Mode (46) -// Check L4 connects against EXCLUDE list (47) -// Add vaidation of LOC in WL2K Session Reports (49) -// Change gpsd support for compatibility with Share Gps (50) - - -#define CKernel - -#include "Versions.h" - -#define _CRT_SECURE_NO_DEPRECATE - -#pragma data_seg("_BPQDATA") - -#include "time.h" -#include "stdio.h" -#include - -#include "compatbits.h" - -#include "AsmStrucs.h" - -#include "SHELLAPI.H" -#include "kernelresource.h" - -#include -#include -#include "BPQTermMDI.h" - -#include "GetVersion.h" - -#define DllImport __declspec( dllimport ) - -#define CheckGuardZone() _CheckGuardZone(__FILE__, __LINE__) -void _CheckGuardZone(char * File, int Line); - -#define CHECKLOADED 0 -#define SETAPPLFLAGS 1 -#define SENDBPQFRAME 2 -#define GETBPQFRAME 3 -#define GETSTREAMSTATUS 4 -#define CLEARSTREAMSTATUS 5 -#define BPQCONDIS 6 -#define GETBUFFERSTATUS 7 -#define GETCONNECTIONINFO 8 -#define BPQRETURN 9 // GETCALLS -//#define RAWTX 10 //IE KISS TYPE DATA -#define GETRAWFRAME 11 -#define UPDATESWITCH 12 -#define BPQALLOC 13 -//#define SENDNETFRAME 14 -#define GETTIME 15 - -extern short NUMBEROFPORTS; -extern long PORTENTRYLEN; -extern long LINKTABLELEN; -extern struct PORTCONTROL * PORTTABLE; -extern void * FREE_Q; -extern UINT APPL_Q; // Queue of frames for APRS Appl - -extern TRANSPORTENTRY * L4TABLE; -extern UCHAR NEXTID; -extern DWORD MAXCIRCUITS; -extern DWORD L4DEFAULTWINDOW; -extern DWORD L4T1; -extern APPLCALLS APPLCALLTABLE[]; -extern char * APPLS; - -extern struct WL2KInfo * WL2KReports; - -extern int NUMBEROFTNCPORTS; - - -void * VCOMExtInit(struct PORTCONTROL * PortEntry); -void * AXIPExtInit(struct PORTCONTROL * PortEntry); -void * SCSExtInit(struct PORTCONTROL * PortEntry); -void * AEAExtInit(struct PORTCONTROL * PortEntry); -void * KAMExtInit(struct PORTCONTROL * PortEntry); -void * HALExtInit(struct PORTCONTROL * PortEntry); -void * ETHERExtInit(struct PORTCONTROL * PortEntry); -void * AGWExtInit(struct PORTCONTROL * PortEntry); -void * WinmorExtInit(EXTPORTDATA * PortEntry); -void * TelnetExtInit(EXTPORTDATA * PortEntry); -//void * SoundModemExtInit(EXTPORTDATA * PortEntry); -void * TrackerExtInit(EXTPORTDATA * PortEntry); -void * TrackerMExtInit(EXTPORTDATA * PortEntry); -void * V4ExtInit(EXTPORTDATA * PortEntry); -void * UZ7HOExtInit(EXTPORTDATA * PortEntry); -void * MPSKExtInit(EXTPORTDATA * PortEntry); -void * FLDigiExtInit(EXTPORTDATA * PortEntry); -void * UIARQExtInit(EXTPORTDATA * PortEntry); -void * SerialExtInit(EXTPORTDATA * PortEntry); -void * ARDOPExtInit(EXTPORTDATA * PortEntry); -void * VARAExtInit(EXTPORTDATA * PortEntry); -void * KISSHFExtInit(EXTPORTDATA * PortEntry); -void * WinRPRExtInit(EXTPORTDATA * PortEntry); -void * HSMODEMExtInit(EXTPORTDATA * PortEntry); -void * FreeDataExtInit(EXTPORTDATA * PortEntry); - -extern char * ConfigBuffer; // Config Area -VOID REMOVENODE(dest_list * DEST); -DllExport int ConvFromAX25(unsigned char * incall,unsigned char * outcall); -DllExport int ConvToAX25(unsigned char * incall,unsigned char * outcall); -VOID GetUIConfig(); -VOID ADIFWriteFreqList(); -void SaveAIS(); -void initAIS(); -void initADSB(); - -extern BOOL ADIFLogEnabled; - -int CloseOnError = 0; - -char UIClassName[]="UIMAINWINDOW"; // the main window class name - -HWND UIhWnd; - -extern char AUTOSAVE; -extern char AUTOSAVEMH; - -extern char MYNODECALL; // 10 chars,not null terminated - -extern QCOUNT; -extern BPQVECSTRUC BPQHOSTVECTOR[]; -#define BPQHOSTSTREAMS 64 -#define IPHOSTVECTOR BPQHOSTVECTOR[BPQHOSTSTREAMS + 3] - -extern char * CONFIGFILENAME; - -DllExport BPQVECSTRUC * BPQHOSTVECPTR; - -extern int DATABASESTART; - -extern struct ROUTE * NEIGHBOURS; -extern int ROUTE_LEN; -extern int MAXNEIGHBOURS; - -extern struct DEST_LIST * DESTS; // NODE LIST -extern int DEST_LIST_LEN; -extern int MAXDESTS; // MAX NODES IN SYSTEM - -extern struct _LINKTABLE * LINKS; -extern int LINK_TABLE_LEN; -extern int MAXLINKS; - - -extern int BPQHOSTAPI(); -extern int INITIALISEPORTS(); -extern int TIMERINTERRUPT(); -extern int MONDECODE(); -extern int BPQMONOPTIONS(); -extern char PWTEXT[]; -extern char PWLen; - -extern int FINDFREEDESTINATION(); -extern int RAWTX(); -extern int RELBUFF(); -extern int SENDNETFRAME(); -extern char MYCALL[]; // 7 chars, ax.25 format - -extern HWND hIPResWnd; -extern BOOL IPMinimized; - -extern int NODESINPROGRESS; -extern VOID * CURRENTNODE; - - -BOOL Start(); - -VOID SaveWindowPos(int port); -VOID SaveAXIPWindowPos(int port); -VOID SetupRTFHddr(); -DllExport VOID APIENTRY CreateNewTrayIcon(); -int DoReceivedData(int Stream); -int DoStateChange(int Stream); -int DoMonData(int Stream); -struct ConsoleInfo * CreateChildWindow(int Stream, BOOL DuringInit); -CloseHostSessions(); -SaveHostSessions(); -VOID SaveBPQ32Windows(); -VOID CloseDriverWindow(int port); -VOID CheckWL2KReportTimer(); -VOID SetApplPorts(); -VOID WriteMiniDump(); -VOID FindLostBuffers(); -BOOL InitializeTNCEmulator(); -VOID TNCTimer(); -char * strlop(char * buf, char delim); - -DllExport int APIENTRY Get_APPLMASK(int Stream); -DllExport int APIENTRY GetStreamPID(int Stream); -DllExport int APIENTRY GetApplFlags(int Stream); -DllExport int APIENTRY GetApplNum(int Stream); -DllExport BOOL APIENTRY GetAllocationState(int Stream); -DllExport int APIENTRY GetMsg(int stream, char * msg, int * len, int * count ); -DllExport int APIENTRY RXCount(int Stream); -DllExport int APIENTRY TXCount(int Stream); -DllExport int APIENTRY MONCount(int Stream); -DllExport int APIENTRY GetCallsign(int stream, char * callsign); -DllExport VOID APIENTRY RelBuff(VOID * Msg); -void SaveMH(); -void DRATSPoll(); - -#define C_Q_ADD(s, b) _C_Q_ADD(s, b, __FILE__, __LINE__); -int _C_Q_ADD(VOID *PQ, VOID *PBUFF, char * File, int Line); - -VOID SetWindowTextSupport(); -int WritetoConsoleSupport(char * buff); -VOID PMClose(); -VOID MySetWindowText(HWND hWnd, char * Msg); -BOOL CreateMonitorWindow(char * MonSize); -VOID FormatTime3(char * Time, time_t cTime); - -char EXCEPTMSG[80] = ""; - -char SIGNONMSG[128] = ""; -char SESSIONHDDR[80] = ""; -int SESSHDDRLEN = 0; - -BOOL IncludesMail = FALSE; -BOOL IncludesChat = FALSE; // Set if pgram is running - used for Web Page Index - - -char WL2KCall[10]; -char WL2KLoc[7]; - -extern char LOCATOR[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char MAPCOMMENT[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char LOC[7]; // Maidenhead Locator for Reporting -extern char ReportDest[7]; - -VOID __cdecl Debugprintf(const char * format, ...); -VOID __cdecl Consoleprintf(const char * format, ...); - -DllExport int APIENTRY CloseBPQ32(); -DllExport char * APIENTRY GetLOC(); -DllExport int APIENTRY SessionControl(int stream, int command, int param); - -int DoRefreshWebMailIndex(); - -BOOL APIENTRY Init_IP(); -BOOL APIENTRY Poll_IP(); - -BOOL APIENTRY Init_PM(); -BOOL APIENTRY Poll_PM(); - -BOOL APIENTRY Init_APRS(); -BOOL APIENTRY Poll_APRS(); -VOID HTTPTimer(); - -BOOL APIENTRY Rig_Init(); -BOOL APIENTRY Rig_Close(); -BOOL Rig_Poll(); - -VOID IPClose(); -VOID APRSClose(); -VOID CloseTNCEmulator(); - -VOID Poll_AGW(); -BOOL AGWAPIInit(); -int AGWAPITerminate(); - -int * Flag = (int *)&Flag; // for Dump Analysis -int MAJORVERSION=4; -int MINORVERSION=9; - -struct SEM Semaphore = {0, 0, 0, 0}; -struct SEM APISemaphore = {0, 0, 0, 0}; -int SemHeldByAPI = 0; -int LastSemGets = 0; -UINT Sem_eax = 0; -UINT Sem_ebx = 0; -UINT Sem_ecx = 0; -UINT Sem_edx = 0; -UINT Sem_esi = 0; -UINT Sem_edi = 0; - -void GetSemaphore(struct SEM * Semaphore, int ID); -void FreeSemaphore(struct SEM * Semaphore); - -DllExport void * BPQHOSTAPIPTR = &BPQHOSTAPI; -//DllExport long MONDECODEPTR = (long)&MONDECODE; - -extern UCHAR BPQDirectory[]; -extern UCHAR LogDirectory[]; -extern UCHAR BPQProgramDirectory[]; - -static char BPQWinMsg[] = "BPQWindowMessage"; - -static char ClassName[] = "BPQMAINWINDOW"; - -HKEY REGTREE = HKEY_CURRENT_USER; -char REGTREETEXT[100] = "HKEY_CURRENT_USER"; - -UINT BPQMsg=0; - -#define MAXLINELEN 120 -#define MAXSCREENLEN 50 - -#define BGCOLOUR RGB(236,233,216) - -HBRUSH bgBrush = NULL; - -//int LINELEN=120; -//int SCREENLEN=50; - -//char Screen[MAXLINELEN*MAXSCREENLEN]={0}; - -//int lineno=0; -//int col=0; - -#define REPORTINTERVAL 15 * 549; // Magic Ticks Per Minute for PC's nominal 100 ms timer -int ReportTimer = 0; - -HANDLE OpenConfigFile(char * file); - -VOID SetupBPQDirectory(); -VOID SendLocation(); - -//uintptr_t _beginthread(void(*start_address)(), unsigned stack_size, int arglist); - -#define TRAY_ICON_ID 1 // ID number for the Notify Icon -#define MY_TRAY_ICON_MESSAGE WM_APP // the message ID sent to our window - -NOTIFYICONDATA niData; - -int SetupConsoleWindow(); - -BOOL StartMinimized=FALSE; -BOOL MinimizetoTray=TRUE; - -BOOL StatusMinimized = FALSE; -BOOL ConsoleMinimized = FALSE; - -HMENU trayMenu=0; - -HWND hConsWnd = NULL, hWndCons = NULL, hWndBG = NULL, ClientWnd = NULL, FrameWnd = NULL, StatusWnd = NULL; - -BOOL FrameMaximized = FALSE; - -BOOL IGateEnabled = TRUE; -extern int ISDelayTimer; // Time before trying to reopen APRS-IS link -extern int ISPort; - -UINT * WINMORTraceQ = NULL; -UINT * SetWindowTextQ = NULL; - -static RECT Rect = {100,100,400,400}; // Console Window Position -RECT FRect = {100,100,800,600}; // Frame -static RECT StatusRect = {100,100,850,500}; // Status Window - -DllExport int APIENTRY DumpSystem(); -DllExport int APIENTRY SaveNodes (); -DllExport int APIENTRY ClearNodes (); -DllExport int APIENTRY SetupTrayIcon(); - -#define Q_REM(s) _Q_REM(s, __FILE__, __LINE__) - -VOID * _Q_REM(VOID *Q, char * File, int Line); - -UINT ReleaseBuffer(UINT *BUFF); - - -VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime ); - -DllExport int APIENTRY DeallocateStream(int stream); - -int VECTORLENGTH = sizeof (struct _BPQVECSTRUC); - -int FirstEntry = 1; -BOOL CloseLast = TRUE; // If the user started BPQ32.exe, don't close it when other programs close -BOOL Closing = FALSE; // Set if Close All called - prevents respawning bpq32.exe - -BOOL BPQ32_EXE; // Set if Process is running BPQ32.exe. Not initialised. - // Used to Kill surplus BPQ32.exe processes - -DWORD Our_PID; // Our Process ID - local variable - -void * InitDone = 0; -int FirstInitDone = 0; -int PerlReinit = 0; -UINT_PTR TimerHandle = 0; -UINT_PTR SessHandle = 0; - -BOOL EventsEnabled = 0; - -unsigned int TimerInst = 0xffffffff; - -HANDLE hInstance = 0; - -int AttachedProcesses = 0; -int AttachingProcess = 0; -HINSTANCE hIPModule = 0; -HINSTANCE hRigModule = 0; - -BOOL ReconfigFlag = FALSE; -BOOL RigReconfigFlag = FALSE; -BOOL APRSReconfigFlag = FALSE; -BOOL CloseAllNeeded = FALSE; -BOOL NeedWebMailRefresh = FALSE; - -int AttachedPIDList[100] = {0}; - -HWND hWndArray[100] = {0}; -int PIDArray[100] = {0}; -char PopupText[30][100] = {""}; - -// Next 3 should be uninitialised so they are local to each process - -UCHAR MCOM; -UCHAR MTX; -ULONG MMASK; -UCHAR MUIONLY; - -UCHAR AuthorisedProgram; // Local Variable. Set if Program is on secure list - -char pgm[256]; // Uninitialised so per process - -HANDLE Mutex; - -BOOL PartLine = FALSE; -int pindex = 0; -DWORD * WritetoConsoleQ; - - -LARGE_INTEGER lpFrequency = {0}; -LARGE_INTEGER lastRunTime; -LARGE_INTEGER currentTime; - -int ticksPerMillisec; -int interval; - - -VOID CALLBACK SetupTermSessions(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime); - - -TIMERPROC lpTimerFunc = (TIMERPROC) TimerProc; -TIMERPROC lpSetupTermSessions = (TIMERPROC) SetupTermSessions; - - -BOOL ProcessConfig(); -VOID FreeConfig(); - -DllExport int APIENTRY WritetoConsole(char * buff); - -BOOLEAN CheckifBPQ32isLoaded(); -BOOLEAN StartBPQ32(); -DllExport VOID APIENTRY Send_AX(VOID * Block, DWORD len, UCHAR Port); -BOOL LoadIPDriver(); -BOOL Send_IP(VOID * Block, DWORD len); -VOID CheckforLostProcesses(); -BOOL LoadRigDriver(); -VOID SaveConfig(); -VOID CreateRegBackup(); -VOID ResolveUpdateThread(); -VOID OpenReportingSockets(); -DllExport VOID APIENTRY CloseAllPrograms(); -DllExport BOOL APIENTRY SaveReg(char * KeyIn, HANDLE hFile); -int upnpClose(); - -BOOL IPActive = FALSE; -extern BOOL IPRequired; -BOOL PMActive = FALSE; -extern BOOL PMRequired; -BOOL RigRequired = TRUE; -BOOL RigActive = FALSE; -BOOL APRSActive = FALSE; -BOOL AGWActive = FALSE; -BOOL needAIS = FALSE; -int needADSB = 0; - -extern int AGWPort; - -Tell_Sessions(); - - -typedef int (WINAPI FAR *FARPROCX)(); - -FARPROCX CreateToolHelp32SnapShotPtr; -FARPROCX Process32Firstptr; -FARPROCX Process32Nextptr; - -void LoadToolHelperRoutines() -{ - HINSTANCE ExtDriver=0; - int err; - char msg[100]; - - ExtDriver=LoadLibrary("kernel32.dll"); - - if (ExtDriver == NULL) - { - err=GetLastError(); - sprintf(msg,"BPQ32 Error loading kernel32.dll - Error code %d\n", err); - OutputDebugString(msg); - return; - } - - CreateToolHelp32SnapShotPtr = (FARPROCX)GetProcAddress(ExtDriver,"CreateToolhelp32Snapshot"); - Process32Firstptr = (FARPROCX)GetProcAddress(ExtDriver,"Process32First"); - Process32Nextptr = (FARPROCX)GetProcAddress(ExtDriver,"Process32Next"); - - if (CreateToolHelp32SnapShotPtr == 0) - { - err=GetLastError(); - sprintf(msg,"BPQ32 Error getting CreateToolhelp32Snapshot entry point - Error code %d\n", err); - OutputDebugString(msg); - return; - } -} - -BOOL GetProcess(int ProcessID, char * Program) -{ - HANDLE hProcessSnap; - PROCESSENTRY32 pe32; - int p; - - if (CreateToolHelp32SnapShotPtr==0) - { - return (TRUE); // Routine not available - } - // Take a snapshot of all processes in the system. - hProcessSnap = (HANDLE)CreateToolHelp32SnapShotPtr(TH32CS_SNAPPROCESS, 0); - if( hProcessSnap == INVALID_HANDLE_VALUE ) - { - OutputDebugString( "CreateToolhelp32Snapshot (of processes) Failed\n" ); - return( FALSE ); - } - - // Set the size of the structure before using it. - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - // Retrieve information about the first process, - // and exit if unsuccessful - if( !Process32Firstptr( hProcessSnap, &pe32 ) ) - { - OutputDebugString( "Process32First Failed\n" ); // Show cause of failure - CloseHandle( hProcessSnap ); // Must clean up the snapshot object! - return( FALSE ); - } - - // Now walk the snapshot of processes, and - // display information about each process in turn - do - { - if (ProcessID==pe32.th32ProcessID) - { - // if running on 98, program contains the full path - remove it - - for (p = (int)strlen(pe32.szExeFile); p >= 0; p--) - { - if (pe32.szExeFile[p]=='\\') - { - break; - } - } - p++; - - sprintf(Program,"%s", &pe32.szExeFile[p]); - CloseHandle( hProcessSnap ); - return( TRUE ); - } - - } while( Process32Nextptr( hProcessSnap, &pe32 ) ); - - - sprintf(Program,"PID %d Not Found", ProcessID); - CloseHandle( hProcessSnap ); - return(FALSE); -} - -BOOL IsProcess(int ProcessID) -{ - // Check that Process exists - - HANDLE hProcessSnap; - PROCESSENTRY32 pe32; - - if (CreateToolHelp32SnapShotPtr==0) return (TRUE); // Routine not available - - hProcessSnap = (HANDLE)CreateToolHelp32SnapShotPtr(TH32CS_SNAPPROCESS, 0); - - if( hProcessSnap == INVALID_HANDLE_VALUE ) - { - OutputDebugString( "CreateToolhelp32Snapshot (of processes) Failed\n" ); - return(TRUE); // Don't know, so assume ok - } - - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - if( !Process32Firstptr( hProcessSnap, &pe32 ) ) - { - OutputDebugString( "Process32First Failed\n" ); // Show cause of failure - CloseHandle( hProcessSnap ); // Must clean up the snapshot object! - return(TRUE); // Don't know, so assume ok - } - - do - { - if (ProcessID==pe32.th32ProcessID) - { - CloseHandle( hProcessSnap ); - return( TRUE ); - } - - } while( Process32Nextptr( hProcessSnap, &pe32 ) ); - - CloseHandle( hProcessSnap ); - return(FALSE); -} - -#include "DbgHelp.h" - -VOID MonitorThread(int x) -{ - // Thread to detect killed processes. Runs in process owning timer. - - // Obviously can't detect loss of timer owning thread! - - do - { - if (Semaphore.Gets == LastSemGets && Semaphore.Flag) - { - // It is stuck - try to release - - Debugprintf ("Semaphore locked - Process ID = %d, Held By %d", - Semaphore.SemProcessID, SemHeldByAPI); - - // Write a minidump - - WriteMiniDump(); - - Semaphore.Flag = 0; - } - - LastSemGets = Semaphore.Gets; - - Sleep(30000); - CheckforLostProcesses(); - - } while (TRUE); -} - -VOID CheckforLostProcesses() -{ - UCHAR buff[100]; - char Log[80]; - int i, n, ProcessID; - - for (n=0; n < AttachedProcesses; n++) - { - ProcessID=AttachedPIDList[n]; - - if (!IsProcess(ProcessID)) - { - // Process has died - Treat as a detach - - sprintf(Log,"BPQ32 Process %d Died\n", ProcessID); - OutputDebugString(Log); - - // Remove Tray Icon Entry - - for( i = 0; i < 100; ++i ) - { - if (PIDArray[i] == ProcessID) - { - hWndArray[i] = 0; - sprintf(Log,"BPQ32 Removing Tray Item %s\n", PopupText[i]); - OutputDebugString(Log); - DeleteMenu(trayMenu,TRAYBASEID+i,MF_BYCOMMAND); - } - } - - // If process had the semaphore, release it - - if (Semaphore.Flag == 1 && ProcessID == Semaphore.SemProcessID) - { - OutputDebugString("BPQ32 Process was holding Semaphore - attempting recovery\r\n"); - Debugprintf("Last Sem Call %d %x %x %x %x %x %x", SemHeldByAPI, - Sem_eax, Sem_ebx, Sem_ecx, Sem_edx, Sem_esi, Sem_edi); - - Semaphore.Flag = 0; - SemHeldByAPI = 0; - } - - for (i=1;i<65;i++) - { - if (BPQHOSTVECTOR[i-1].STREAMOWNER == AttachedPIDList[n]) - { - DeallocateStream(i); - } - } - - if (TimerInst == ProcessID) - { - KillTimer(NULL,TimerHandle); - TimerHandle=0; - TimerInst=0xffffffff; -// Tell_Sessions(); - OutputDebugString("BPQ32 Process was running timer \n"); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - - } - - // Remove this entry from PID List - - for (i=n; i< AttachedProcesses; i++) - { - AttachedPIDList[i]=AttachedPIDList[i+1]; - } - AttachedProcesses--; - - sprintf(buff,"BPQ32 Lost Process - %d Process(es) Attached\n", AttachedProcesses); - OutputDebugString(buff); - } - } -} -VOID MonitorTimerThread(int x) -{ - // Thread to detect killed timer process. Runs in all other BPQ32 processes. - - do { - - Sleep(60000); - - if (TimerInst != 0xffffffff && !IsProcess(TimerInst)) - { - // Timer owning Process has died - Force a new timer to be created - // New timer thread will detect lost process and tidy up - - Debugprintf("BPQ32 Process %d with Timer died", TimerInst); - - // If process was holding the semaphore, release it - - if (Semaphore.Flag == 1 && TimerInst == Semaphore.SemProcessID) - { - OutputDebugString("BPQ32 Process was holding Semaphore - attempting recovery\r\n"); - Debugprintf("Last Sem Call %d %x %x %x %x %x %x", SemHeldByAPI, - Sem_eax, Sem_ebx, Sem_ecx, Sem_edx, Sem_esi, Sem_edi); - Semaphore.Flag = 0; - SemHeldByAPI = 0; - } - -// KillTimer(NULL,TimerHandle); -// TimerHandle=0; -// TimerInst=0xffffffff; -// Tell_Sessions(); - - CheckforLostProcesses(); // Normally only done in timer thread, which is now dead - - // Timer can only run in BPQ32.exe - - TimerInst=0xffffffff; // So we dont keep doing it - TimerHandle = 0; // So new process attaches - - if (Closing == FALSE && AttachingProcess == FALSE) - { - OutputDebugString("BPQ32 Reloading BPQ32.exe\n"); - StartBPQ32(); - } - -// if (MinimizetoTray) -// Shell_NotifyIcon(NIM_DELETE,&niData); - } - - } while (TRUE); -} - -VOID WritetoTraceSupport(struct TNCINFO * TNC, char * Msg, int Len); - -VOID TimerProcX(); - -VOID CALLBACK TimerProc( - HWND hwnd, // handle of window for timer messages - UINT uMsg, // WM_TIMER message - UINT idEvent, // timer identifier - DWORD dwTime) // current system time -{ - KillTimer(NULL,TimerHandle); - TimerProcX(); - TimerHandle = SetTimer(NULL,0,100,lpTimerFunc); -} -VOID TimerProcX() -{ - struct _EXCEPTION_POINTERS exinfo; - - // - // Get semaphore before proceeeding - // - - GetSemaphore(&Semaphore, 2); - - // Get time since last run - - QueryPerformanceCounter(¤tTime); - - interval = (int)(currentTime.QuadPart - lastRunTime.QuadPart) / ticksPerMillisec; - lastRunTime.QuadPart = currentTime.QuadPart; - - //Debugprintf("%d", interval); - - // Process WINMORTraceQ - - while (WINMORTraceQ) - { - UINT * Buffer = Q_REM(&WINMORTraceQ); - struct TNCINFO * TNC = (struct TNCINFO * )Buffer[1]; - int Len = Buffer[2]; - char * Msg = (char *)&Buffer[3]; - - WritetoTraceSupport(TNC, Msg, Len); - RelBuff(Buffer); - } - - if (SetWindowTextQ) - SetWindowTextSupport(); - - while (WritetoConsoleQ) - { - UINT * Buffer = Q_REM(&WritetoConsoleQ); - WritetoConsoleSupport((char *)&Buffer[2]); - RelBuff(Buffer); - } - - strcpy(EXCEPTMSG, "Timer ReconfigProcessing"); - - __try - { - - if (trayMenu == NULL) - SetupTrayIcon(); - - // See if reconfigure requested - - if (CloseAllNeeded) - { - CloseAllNeeded = FALSE; - CloseAllPrograms(); - } - - if (ReconfigFlag) - { - // Only do it it timer owning process, or we could get in a real mess! - - if(TimerInst == GetCurrentProcessId()) - { - int i; - BPQVECSTRUC * HOSTVEC; - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - WSADATA WsaData; // receives data from WSAStartup - RECT cRect; - - ReconfigFlag = FALSE; - - SetupBPQDirectory(); - - WritetoConsole("Reconfiguring ...\n\n"); - OutputDebugString("BPQ32 Reconfiguring ...\n"); - - GetWindowRect(FrameWnd, &FRect); - - SaveWindowPos(40); // Rigcontrol - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - CloseDriverWindow(PORTVEC->PORTCONTROL.PORTNUMBER); - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); // Close External Ports - } - } - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - IPClose(); - PMClose(); - APRSClose(); - Rig_Close(); - CloseTNCEmulator(); - if (AGWActive) - AGWAPITerminate(); - - WSACleanup(); - - WL2KReports = NULL; - - Sleep(2000); - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - - Start(); - - INITIALISEPORTS(); // Restart Ports - - SetApplPorts(); - - FreeConfig(); - - for (i=1; i<68; i++) // Include Telnet, APRS and IP Vec - { - HOSTVEC=&BPQHOSTVECTOR[i-1]; - - HOSTVEC->HOSTTRACEQ=0; // Clear header (pool has been reinitialized - - if (HOSTVEC->HOSTSESSION !=0) - { - // Had a connection - - HOSTVEC->HOSTSESSION=0; - HOSTVEC->HOSTFLAGS |=3; // Disconnected - - PostMessage(HOSTVEC->HOSTHANDLE, BPQMsg, i, 4); - } - } - - // Free the APRS Appl Q - - APPL_Q = 0; - - OpenReportingSockets(); - - WritetoConsole("\n\nReconfiguration Complete\n"); - - if (IPRequired) IPActive = Init_IP(); - if (PMRequired) PMActive = Init_PM(); - - APRSActive = Init_APRS(); - - if (ISPort == 0) - IGateEnabled = 0; - - CheckDlgButton(hConsWnd, IDC_ENIGATE, IGateEnabled); - - GetClientRect(hConsWnd, &cRect); - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - { - ShowWindow(GetDlgItem(hConsWnd, IDC_GPS), SW_HIDE); - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - } - InvalidateRect(hConsWnd, NULL, TRUE); - - RigActive = Rig_Init(); - - if (NUMBEROFTNCPORTS) - { - FreeSemaphore(&Semaphore); - InitializeTNCEmulator(); - GetSemaphore(&Semaphore, 0); - } - - FreeSemaphore(&Semaphore); - AGWActive = AGWAPIInit(); - GetSemaphore(&Semaphore, 0); - - OutputDebugString("BPQ32 Reconfiguration Complete\n"); - } - } - - - if (RigReconfigFlag) - { - // Only do it it timer owning process, or we could get in a real mess! - - if(TimerInst == GetCurrentProcessId()) - { - RigReconfigFlag = FALSE; - CloseDriverWindow(40); - Rig_Close(); - Sleep(6000); // Allow any CATPTT, HAMLIB and FLRIG threads to close - RigActive = Rig_Init(); - - WritetoConsole("Rigcontrol Reconfiguration Complete\n"); - } - } - - if (APRSReconfigFlag) - { - // Only do it it timer owning process, or we could get in a real mess! - - if(TimerInst == GetCurrentProcessId()) - { - APRSReconfigFlag = FALSE; - APRSClose(); - APRSActive = Init_APRS(); - - WritetoConsole("APRS Reconfiguration Complete\n"); - } - } - - } - #include "StdExcept.c" - - if (Semaphore.Flag && Semaphore.SemProcessID == GetCurrentProcessId()) - FreeSemaphore(&Semaphore); - - } - - strcpy(EXCEPTMSG, "Timer Processing"); - - __try - { - if (IPActive) Poll_IP(); - if (PMActive) Poll_PM(); - if (RigActive) Rig_Poll(); - - if (NeedWebMailRefresh) - DoRefreshWebMailIndex(); - - CheckGuardZone(); - - if (APRSActive) - { - Poll_APRS(); - CheckGuardZone(); - } - - CheckWL2KReportTimer(); - - CheckGuardZone(); - - TIMERINTERRUPT(); - - CheckGuardZone(); - - FreeSemaphore(&Semaphore); // SendLocation needs to get the semaphore - - if (NUMBEROFTNCPORTS) - TNCTimer(); - - if (AGWActive) - Poll_AGW(); - - DRATSPoll(); - - CheckGuardZone(); - - strcpy(EXCEPTMSG, "HTTP Timer Processing"); - - HTTPTimer(); - - CheckGuardZone(); - - strcpy(EXCEPTMSG, "WL2K Report Timer Processing"); - - if (ReportTimer) - { - ReportTimer--; - - if (ReportTimer == 0) - { - ReportTimer = REPORTINTERVAL; - SendLocation(); - } - } - } - - #include "StdExcept.c" - - if (Semaphore.Flag && Semaphore.SemProcessID == GetCurrentProcessId()) - FreeSemaphore(&Semaphore); - - } - - CheckGuardZone(); - - return; -} - -HANDLE NPHandle; - -int (WINAPI FAR *GetModuleFileNameExPtr)() = NULL; -int (WINAPI FAR *EnumProcessesPtr)() = NULL; - -FirstInit() -{ - WSADATA WsaData; // receives data from WSAStartup - HINSTANCE ExtDriver=0; - RECT cRect; - - - // First Time Ports and Timer init - - // Moved from DLLINIT to sort out perl problem, and meet MS Guidelines on minimising DLLMain - - // Call wsastartup - most systems need winsock, and duplicate statups could be a problem - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - // Load Psapi.dll if possible - - ExtDriver=LoadLibrary("Psapi.dll"); - - SetupTrayIcon(); - - if (ExtDriver) - { - GetModuleFileNameExPtr = (FARPROCX)GetProcAddress(ExtDriver,"GetModuleFileNameExA"); - EnumProcessesPtr = (FARPROCX)GetProcAddress(ExtDriver,"EnumProcesses"); - } - INITIALISEPORTS(); - - OpenReportingSockets(); - - WritetoConsole("\n"); - WritetoConsole("Port Initialisation Complete\n"); - - if (IPRequired) IPActive = Init_IP(); - if (PMRequired) PMActive = Init_PM(); - - APRSActive = Init_APRS(); - - if (APRSActive) - { - hWndBG = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 0,0,40,546, hConsWnd, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Enable IGate", WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, - 8,0,90,24, hConsWnd, (HMENU)-1, hInstance, NULL); - - CreateWindowEx(0, "BUTTON", "", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP, - 95,1,18,24, hConsWnd, (HMENU)IDC_ENIGATE, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "IGate State - Disconnected", - WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 125, 0, 195, 24, hConsWnd, (HMENU)IGATESTATE, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "IGATE Stats - Msgs 0 Local Stns 0", - WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 320, 0, 240, 24, hConsWnd, (HMENU)IGATESTATS, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "GPS Off", - WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 560, 0, 80, 24, hConsWnd, (HMENU)IDC_GPS, hInstance, NULL); - } - - if (ISPort == 0) - IGateEnabled = 0; - - CheckDlgButton(hConsWnd, IDC_ENIGATE, IGateEnabled); - - GetClientRect(hConsWnd, &cRect); - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - { - ShowWindow(GetDlgItem(hConsWnd, IDC_GPS), SW_HIDE); - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - } - InvalidateRect(hConsWnd, NULL, TRUE); - - RigActive = Rig_Init(); - - _beginthread(MonitorThread,0,0); - - TimerHandle=SetTimer(NULL,0,100,lpTimerFunc); - TimerInst=GetCurrentProcessId(); - SessHandle = SetTimer(NULL, 0, 5000, lpSetupTermSessions); - - // If ARIF reporting is enabled write a Trimode Like ini for RMS Analyser - - if (ADIFLogEnabled) - ADIFWriteFreqList(); - - OutputDebugString("BPQ32 Port Initialisation Complete\n"); - - if (needAIS) - initAIS(); - - if (needADSB) - initADSB(); - - return 0; -} - -Check_Timer() -{ - if (Closing) - return 0; - - if (Semaphore.Flag) - return 0; - - if (InitDone == (void *)-1) - { - GetSemaphore(&Semaphore, 3); - Sleep(15000); - FreeSemaphore(&Semaphore); - exit (0); - } - - if (FirstInitDone == 0) - { - GetSemaphore(&Semaphore, 3); - - if (_stricmp(pgm, "bpq32.exe") == 0) - { - FirstInit(); - FreeSemaphore(&Semaphore); - if (NUMBEROFTNCPORTS) - InitializeTNCEmulator(); - - AGWActive = AGWAPIInit(); - FirstInitDone=1; // Only init in BPQ32.exe - return 0; - } - else - { - FreeSemaphore(&Semaphore); - return 0; - } - } - - if (TimerHandle == 0 && FirstInitDone == 1) - { - WSADATA WsaData; // receives data from WSAStartup - HINSTANCE ExtDriver=0; - RECT cRect; - - // Only attach timer to bpq32.exe - - if (_stricmp(pgm, "bpq32.exe") != 0) - { - return 0; - } - - GetSemaphore(&Semaphore, 3); - OutputDebugString("BPQ32 Reinitialising External Ports and Attaching Timer\n"); - - if (!ProcessConfig()) - { - ShowWindow(hConsWnd, SW_RESTORE); - SendMessage(hConsWnd, WM_PAINT, 0, 0); - SetForegroundWindow(hConsWnd); - - InitDone = (void *)-1; - FreeSemaphore(&Semaphore); - - MessageBox(NULL,"Configuration File Error","BPQ32",MB_ICONSTOP); - - exit (0); - } - - GetVersionInfo("bpq32.dll"); - - SetupConsoleWindow(); - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - Consoleprintf("Reinitialising..."); - - SetupBPQDirectory(); - - Sleep(1000); // Allow time for sockets to close - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - // Load Psapi.dll if possible - - ExtDriver = LoadLibrary("Psapi.dll"); - - SetupTrayIcon(); - - if (ExtDriver) - { - GetModuleFileNameExPtr = (FARPROCX)GetProcAddress(ExtDriver,"GetModuleFileNameExA"); - EnumProcessesPtr = (FARPROCX)GetProcAddress(ExtDriver,"EnumProcesses"); - } - - Start(); - - INITIALISEPORTS(); - - OpenReportingSockets(); - - NODESINPROGRESS = 0; - CURRENTNODE = 0; - - SetApplPorts(); - - WritetoConsole("\n\nPort Reinitialisation Complete\n"); - - BPQMsg = RegisterWindowMessage(BPQWinMsg); - - CreateMutex(NULL,TRUE,"BPQLOCKMUTEX"); - -// NPHandle=CreateNamedPipe("\\\\.\\pipe\\BPQ32pipe", -// PIPE_ACCESS_DUPLEX,0,64,4096,4096,1000,NULL); - - if (IPRequired) IPActive = Init_IP(); - if (PMRequired) PMActive = Init_PM(); - - RigActive = Rig_Init(); - APRSActive = Init_APRS(); - - if (ISPort == 0) - IGateEnabled = 0; - - CheckDlgButton(hConsWnd, IDC_ENIGATE, IGateEnabled); - - GetClientRect(hConsWnd, &cRect); - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - { - ShowWindow(GetDlgItem(hConsWnd, IDC_GPS), SW_HIDE); - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - } - InvalidateRect(hConsWnd, NULL, TRUE); - - FreeConfig(); - - _beginthread(MonitorThread,0,0); - - ReportTimer = 0; - - OpenReportingSockets(); - - FreeSemaphore(&Semaphore); - - if (NUMBEROFTNCPORTS) - InitializeTNCEmulator(); - - AGWActive = AGWAPIInit(); - - if (StartMinimized) - if (MinimizetoTray) - ShowWindow(FrameWnd, SW_HIDE); - else - ShowWindow(FrameWnd, SW_SHOWMINIMIZED); - else - ShowWindow(FrameWnd, SW_RESTORE); - - TimerHandle=SetTimer(NULL,0,100,lpTimerFunc); - TimerInst=GetCurrentProcessId(); - SessHandle = SetTimer(NULL, 0, 5000, lpSetupTermSessions); - - return (1); - } - - return (0); -} - -DllExport INT APIENTRY CheckTimer() -{ - return Check_Timer(); -} - -Tell_Sessions() -{ - // - // Post a message to all listening sessions, so they call the - // API, and cause a new timer to be allocated - // - HWND hWnd; - int i; - - for (i=1;i<65;i++) - { - if (BPQHOSTVECTOR[i-1].HOSTFLAGS & 0x80) - { - hWnd = BPQHOSTVECTOR[i-1].HOSTHANDLE; - PostMessage(hWnd, BPQMsg,i, 1); - PostMessage(hWnd, BPQMsg,i, 2); - } - } - return (0); -} - -BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved) -{ - DWORD n; - char buf[350]; - - int i; - unsigned int ProcessID; - - OSVERSIONINFO osvi; - - memset(&osvi, 0, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - - GetVersionEx(&osvi); - - - switch( ul_reason_being_called ) - { - case DLL_PROCESS_ATTACH: - - if (sizeof(HDLCDATA) > PORTENTRYLEN + 200) // 200 bytes of Hardwaredata - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"BPQ32 Too much HDLC data - Recompile","BPQ32", MB_OK); - return 0; - } - - if (sizeof(LINKTABLE) != LINK_TABLE_LEN) - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"L2 LINK Table .c and .asm mismatch - fix and rebuild","BPQ32", MB_OK); - return 0; - } - if (sizeof(struct ROUTE) != ROUTE_LEN) - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"ROUTE Table .c and .asm mismatch - fix and rebuild", "BPQ32", MB_OK); - return 0; - } - - if (sizeof(struct DEST_LIST) != DEST_LIST_LEN) - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"NODES Table .c and .asm mismatch - fix and rebuild", "BPQ32", MB_OK); - return 0; - } - - GetSemaphore(&Semaphore, 4); - - BPQHOSTVECPTR = &BPQHOSTVECTOR[0]; - - LoadToolHelperRoutines(); - - Our_PID = GetCurrentProcessId(); - - QueryPerformanceFrequency(&lpFrequency); - - ticksPerMillisec = (int)lpFrequency.QuadPart / 1000; - - lastRunTime.QuadPart = lpFrequency.QuadPart; - - GetProcess(Our_PID, pgm); - - if (_stricmp(pgm, "regsvr32.exe") == 0 || _stricmp(pgm, "bpqcontrol.exe") == 0) - { - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 1; - } - - if (_stricmp(pgm,"BPQ32.exe") == 0) - BPQ32_EXE = TRUE; - - if (_stricmp(pgm,"BPQMailChat.exe") == 0) - IncludesMail = TRUE; - - if (_stricmp(pgm,"BPQMail.exe") == 0) - IncludesMail = TRUE; - - if (_stricmp(pgm,"BPQChat.exe") == 0) - IncludesChat = TRUE; - - if (FirstEntry) // If loaded by BPQ32.exe, dont close it at end - { - FirstEntry = 0; - if (BPQ32_EXE) - CloseLast = FALSE; - } - else - { - if (BPQ32_EXE && AttachingProcess == 0) - { - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - MessageBox(NULL,"BPQ32.exe is already running\r\n\r\nIt should only be run once", "BPQ32", MB_OK); - return 0; - } - } - - if (_stricmp(pgm,"BPQTelnetServer.exe") == 0) - { - MessageBox(NULL,"BPQTelnetServer is no longer supported\r\n\r\nUse the TelnetServer in BPQ32.dll", "BPQ32", MB_OK); - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 0; - } - - if (_stricmp(pgm,"BPQUIUtil.exe") == 0) - { - MessageBox(NULL,"BPQUIUtil is now part of BPQ32.dll\r\nBPQUIUtil.exe cannot be run\r\n", "BPQ32", MB_OK); - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 0; - } - - if (_stricmp(pgm,"BPQMailChat.exe") == 0) - { - MessageBox(NULL,"BPQMailChat is obsolete. Run BPQMail.exe and/or BPQChat.exe instead", "BPQ32", MB_OK); - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 0; - } - AuthorisedProgram = TRUE; - - if (InitDone == 0) - { -// #pragma warning(push) -// #pragma warning(disable : 4996) - -// if (_winver < 0x0600) -// #pragma warning(pop) -// { -// // Below Vista -// -// REGTREE = HKEY_LOCAL_MACHINE; -// strcpy(REGTREETEXT, "HKEY_LOCAL_MACHINE"); -// } - - hInstance=hInst; - - Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"BPQLOCKMUTEX"); - - if (Mutex != NULL) - { - OutputDebugString("Another BPQ32.dll is loaded\n"); - i=MessageBox(NULL,"BPQ32 DLL already loaded from another directory\nIf you REALLY want this, hit OK, else hit Cancel","BPQ32",MB_OKCANCEL); - FreeSemaphore(&Semaphore); - - if (i != IDOK) return (0); - - CloseHandle(Mutex); - } - - if (!BPQ32_EXE) - { - if (CheckifBPQ32isLoaded() == FALSE) // Start BPQ32.exe if needed - { - // Wasn't Loaded, so we have started it, and should let it init system - - goto SkipInit; - } - } - - GetVersionInfo("bpq32.dll"); - - sprintf (SIGNONMSG, "G8BPQ AX25 Packet Switch System Version %s %s\r\n%s\r\n", - TextVerstring, Datestring, VerCopyright); - - SESSHDDRLEN = sprintf(SESSIONHDDR, "G8BPQ Network System %s for Win32 (", TextVerstring); - - SetupConsoleWindow(); - SetupBPQDirectory(); - - if (!ProcessConfig()) - { - StartMinimized = FALSE; - MinimizetoTray = FALSE; - ShowWindow(FrameWnd, SW_MAXIMIZE); - ShowWindow(hConsWnd, SW_MAXIMIZE); - ShowWindow(StatusWnd, SW_HIDE); - - SendMessage(hConsWnd, WM_PAINT, 0, 0); - SetForegroundWindow(hConsWnd); - - InitDone = (void *)-1; - FreeSemaphore(&Semaphore); - - MessageBox(NULL,"Configuration File Error\r\nProgram will close in 15 seconds","BPQ32",MB_ICONSTOP); - - return (0); - } - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - - if (Start() !=0) - { - Sleep(3000); - FreeSemaphore(&Semaphore); - return (0); - } - else - { - SetApplPorts(); - - GetUIConfig(); - - InitDone = &InitDone; - BPQMsg = RegisterWindowMessage(BPQWinMsg); -// TimerHandle=SetTimer(NULL,0,100,lpTimerFunc); -// TimerInst=GetCurrentProcessId(); - -/* Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"BPQLOCKMUTEX"); - - if (Mutex != NULL) - { - OutputDebugString("Another BPQ32.dll is loaded\n"); - MessageBox(NULL,"BPQ32 DLL already loaded from another directory","BPQ32",MB_ICONSTOP); - FreeSemaphore(&Semaphore); - return (0); - } - -*/ - Mutex=CreateMutex(NULL,TRUE,"BPQLOCKMUTEX"); - -// CreatePipe(&H1,&H2,NULL,1000); - -// GetLastError(); - -// NPHandle=CreateNamedPipe("\\\\.\\pipe\\BPQ32pipe", -// PIPE_ACCESS_DUPLEX,0,64,4096,4096,1000,NULL); - -// GetLastError(); - -/* - // - // Read SYSOP password - // - - if (PWTEXT[0] == 0) - { - handle = OpenConfigFile("PASSWORD.BPQ"); - - if (handle == INVALID_HANDLE_VALUE) - { - WritetoConsole("Can't open PASSWORD.BPQ\n"); - PWLen=0; - PWTEXT[0]=0; - } - else - { - ReadFile(handle,PWTEXT,78,&n,NULL); - CloseHandle(handle); - } - } -*/ - for (i=0;PWTEXT[i] > 0x20;i++); //Scan for cr or null - PWLen=i; - - } - } - else - { - if (InitDone != &InitDone) - { - MessageBox(NULL,"BPQ32 DLL already loaded at another address","BPQ32",MB_ICONSTOP); - FreeSemaphore(&Semaphore); - return (0); - } - } - - // Run timer monitor thread in all processes - it is possible for the TImer thread not to be the first thread -SkipInit: - - _beginthread(MonitorTimerThread,0,0); - - FreeSemaphore(&Semaphore); - - AttachedPIDList[AttachedProcesses++] = GetCurrentProcessId(); - - if (_stricmp(pgm,"bpq32.exe") == 0 && AttachingProcess == 1) AttachingProcess = 0; - - GetProcess(GetCurrentProcessId(),pgm); - n=sprintf(buf,"BPQ32 DLL Attach complete - Program %s - %d Process(es) Attached\n",pgm,AttachedProcesses); - OutputDebugString(buf); - - // Set up local variables - - MCOM=1; - MTX=1; - MMASK=0xffffffff; - -// if (StartMinimized) -// if (MinimizetoTray) -// ShowWindow(FrameWnd, SW_HIDE); -// else -// ShowWindow(FrameWnd, SW_SHOWMINIMIZED); -// else -// ShowWindow(FrameWnd, SW_RESTORE); - - return 1; - - case DLL_THREAD_ATTACH: - - return 1; - - case DLL_THREAD_DETACH: - - return 1; - - case DLL_PROCESS_DETACH: - - if (_stricmp(pgm,"BPQMailChat.exe") == 0) - IncludesMail = FALSE; - - if (_stricmp(pgm,"BPQChat.exe") == 0) - IncludesChat = FALSE; - - ProcessID=GetCurrentProcessId(); - - Debugprintf("BPQ32 Process %d Detaching", ProcessID); - - // Release any streams that the app has failed to release - - for (i=1;i<65;i++) - { - if (BPQHOSTVECTOR[i-1].STREAMOWNER == ProcessID) - { - // If connected, disconnect - - SessionControl(i, 2, 0); - DeallocateStream(i); - } - } - - // Remove any Tray Icon Entries - - for( i = 0; i < 100; ++i ) - { - if (PIDArray[i] == ProcessID) - { - char Log[80]; - hWndArray[i] = 0; - sprintf(Log,"BPQ32 Removing Tray Item %s\n", PopupText[i]); - OutputDebugString(Log); - DeleteMenu(trayMenu,TRAYBASEID+i,MF_BYCOMMAND); - } - } - - if (Mutex) CloseHandle(Mutex); - - // Remove our entry from PID List - - for (i=0; i< AttachedProcesses; i++) - if (AttachedPIDList[i] == ProcessID) - break; - - for (; i< AttachedProcesses; i++) - { - AttachedPIDList[i]=AttachedPIDList[i+1]; - } - - AttachedProcesses--; - - if (TimerInst == ProcessID) - { - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - - OutputDebugString("BPQ32 Process with Timer closing\n"); - - // Call Port Close Routines - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR && PORTVEC->DLLhandle == NULL) // Don't call if real .dll - it's not there! - { - SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); // Close External Ports - } - } - - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - - IPClose(); - PMClose(); - APRSClose(); - Rig_Close(); - CloseTNCEmulator(); - if (AGWActive) - AGWAPITerminate(); - - upnpClose(); - - WSACleanup(); - WSAGetLastError(); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - if (hConsWnd) DestroyWindow(hConsWnd); - - KillTimer(NULL,TimerHandle); - TimerHandle=0; - TimerInst=0xffffffff; - - if (AttachedProcesses && Closing == FALSE && AttachingProcess == 0) // Other processes - { - OutputDebugString("BPQ32 Reloading BPQ32.exe\n"); - StartBPQ32(); - } - } - else - { - // Not Timer Process - - if (AttachedProcesses == 1 && CloseLast) // Only bpq32.exe left - { - Debugprintf("Only BPQ32.exe running - close it"); - CloseAllNeeded = TRUE; - } - } - - if (AttachedProcesses < 2) - { - if (AUTOSAVE == 1) - SaveNodes(); - if (AUTOSAVEMH) - SaveMH(); - - if (needAIS) - SaveAIS(); - } - if (AttachedProcesses == 0) - { - Closing = TRUE; - KillTimer(NULL,TimerHandle); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - // Unload External Drivers - - { - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10 && PORTVEC->DLLhandle) - FreeLibrary(PORTVEC->DLLhandle); - - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - } - } - - GetProcess(GetCurrentProcessId(),pgm); - n=sprintf(buf,"BPQ32 DLL Detach complete - Program %s - %d Process(es) Attached\n",pgm,AttachedProcesses); - OutputDebugString(buf); - - return 1; - } - return 1; -} - -DllExport int APIENTRY CloseBPQ32() -{ - // Unload External Drivers - - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - int i; - int ProcessID = GetCurrentProcessId(); - - if (Semaphore.Flag == 1 && ProcessID == Semaphore.SemProcessID) - { - OutputDebugString("BPQ32 Process holding Semaphore called CloseBPQ32 - attempting recovery\r\n"); - Debugprintf("Last Sem Call %d %x %x %x %x %x %x", SemHeldByAPI, - Sem_eax, Sem_ebx, Sem_ecx, Sem_edx, Sem_esi, Sem_edi); - - Semaphore.Flag = 0; - SemHeldByAPI = 0; - } - - if (TimerInst == ProcessID) - { - OutputDebugString("BPQ32 Process with Timer called CloseBPQ32\n"); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); - } - } - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - KillTimer(NULL,TimerHandle); - TimerHandle=0; - TimerInst=0xffffffff; - - IPClose(); - PMClose(); - APRSClose(); - Rig_Close(); - if (AGWActive) - AGWAPITerminate(); - - upnpClose(); - - CloseTNCEmulator(); - WSACleanup(); - - if (hConsWnd) DestroyWindow(hConsWnd); - - Debugprintf("AttachedProcesses %d ", AttachedProcesses); - - if (AttachedProcesses > 1 && Closing == FALSE && AttachingProcess == 0) // Other processes - { - OutputDebugString("BPQ32 Reloading BPQ32.exe\n"); - StartBPQ32(); - } - } - - return 0; -} - -BOOL CopyReg(HKEY hKeyIn, HKEY hKeyOut); - -VOID SetupBPQDirectory() -{ - HKEY hKey = 0; - HKEY hKeyIn = 0; - HKEY hKeyOut = 0; - int disp; - int retCode,Type,Vallen=MAX_PATH,i; - char msg[512]; - char ValfromReg[MAX_PATH] = ""; - char DLLName[256]="Not Known"; - char LogDir[256]; - char Time[64]; - -/* -•NT4 was/is '4' -•Win 95 is 4.00.950 -•Win 98 is 4.10.1998 -•Win 98 SE is 4.10.2222 -•Win ME is 4.90.3000 -•2000 is NT 5.0.2195 -•XP is actually 5.1 -•Vista is 6.0 -•Win7 is 6.1 - - i = _osver; / Build - i = _winmajor; - i = _winminor; -*/ -/* -#pragma warning(push) -#pragma warning(disable : 4996) - -if (_winver < 0x0600) -#pragma warning(pop) - { - // Below Vista - - REGTREE = HKEY_LOCAL_MACHINE; - strcpy(REGTREETEXT, "HKEY_LOCAL_MACHINE"); - ValfromReg[0] = 0; - } - else -*/ - { - if (_stricmp(pgm, "regsvr32.exe") == 0) - { - Debugprintf("BPQ32 loaded by regsvr32.exe - Registry not copied"); - } - else - { - // If necessary, move reg from HKEY_LOCAL_MACHINE to HKEY_CURRENT_USER - - retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_READ, - &hKeyIn); - - retCode = RegCreateKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\G8BPQ\\BPQ32", 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKeyOut, &disp); - - // See if Version Key exists in HKEY_CURRENT_USER - if it does, we have already done the copy - - Vallen = MAX_PATH; - retCode = RegQueryValueEx(hKeyOut, "Version" ,0 , &Type,(UCHAR *)&msg, &Vallen); - - if (retCode != ERROR_SUCCESS) - if (hKeyIn) - CopyReg(hKeyIn, hKeyOut); - - RegCloseKey(hKeyIn); - RegCloseKey(hKeyOut); - } - } - - GetModuleFileName(hInstance,DLLName,256); - - BPQDirectory[0]=0; - - retCode = RegOpenKeyEx (REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (retCode == ERROR_SUCCESS) - { - // Try "BPQ Directory" - - Vallen = MAX_PATH; - retCode = RegQueryValueEx(hKey,"BPQ Directory",0, - &Type,(UCHAR *)&ValfromReg,&Vallen); - - if (retCode == ERROR_SUCCESS) - { - if (strlen(ValfromReg) == 2 && ValfromReg[0] == '"' && ValfromReg[1] == '"') - ValfromReg[0]=0; - } - - if (ValfromReg[0] == 0) - { - // BPQ Directory absent or = "" - try "Config File Location" - - Vallen = MAX_PATH; - - retCode = RegQueryValueEx(hKey,"Config File Location",0, - &Type,(UCHAR *)&ValfromReg,&Vallen); - - if (retCode == ERROR_SUCCESS) - { - if (strlen(ValfromReg) == 2 && ValfromReg[0] == '"' && ValfromReg[1] == '"') - ValfromReg[0]=0; - } - } - - if (ValfromReg[0] == 0) GetCurrentDirectory(MAX_PATH, ValfromReg); - - // Get StartMinimized and MinimizetoTray flags - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Start Minimized", 0, &Type, (UCHAR *)&StartMinimized, &Vallen); - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Minimize to Tray", 0, &Type, (UCHAR *)&MinimizetoTray, &Vallen); - - ExpandEnvironmentStrings(ValfromReg, BPQDirectory, MAX_PATH); - - // Also get "BPQ Program Directory" - - ValfromReg[0] = 0; - Vallen = MAX_PATH; - - retCode = RegQueryValueEx(hKey, "BPQ Program Directory",0 , &Type, (UCHAR *)&ValfromReg, &Vallen); - - if (retCode == ERROR_SUCCESS) - ExpandEnvironmentStrings(ValfromReg, BPQProgramDirectory, MAX_PATH); - - // And Log Directory - - ValfromReg[0] = 0; - Vallen = MAX_PATH; - - retCode = RegQueryValueEx(hKey, "Log Directory",0 , &Type, (UCHAR *)&ValfromReg, &Vallen); - - if (retCode == ERROR_SUCCESS) - ExpandEnvironmentStrings(ValfromReg, LogDirectory, MAX_PATH); - - RegCloseKey(hKey); - } - - if (LogDirectory[0] == 0) - strcpy(LogDirectory, BPQDirectory); - - if (BPQProgramDirectory[0] == 0) - strcpy(BPQProgramDirectory, BPQDirectory); - - sprintf(msg,"BPQ32 Ver %s Loaded from: %s by %s\n", VersionString, DLLName, pgm); - WritetoConsole(msg); - OutputDebugString(msg); - FormatTime3(Time, time(NULL)); - sprintf(msg,"Loaded %s\n", Time); - WritetoConsole(msg); - OutputDebugString(msg); - -#pragma warning(push) -#pragma warning(disable : 4996) - -#if _MSC_VER >= 1400 - -#define _winmajor 6 -#define _winminor 0 - -#endif - - i=sprintf(msg,"Windows Ver %d.%d, Using Registry Key %s\n" ,_winmajor, _winminor, REGTREETEXT); - -#pragma warning(pop) - - WritetoConsole(msg); - OutputDebugString(msg); - - i=sprintf(msg,"BPQ32 Using config from: %s\n\n",BPQDirectory); - WritetoConsole(&msg[6]); - msg[i-1]=0; - OutputDebugString(msg); - - // Don't write the Version Key if loaded by regsvr32.exe (Installer is running with Admin rights, - // so will write the wrong tree on ) - - if (_stricmp(pgm, "regsvr32.exe") == 0) - { - Debugprintf("BPQ32 loaded by regsvr32.exe - Version String not written"); - } - else - { - retCode = RegCreateKeyEx(REGTREE, "SOFTWARE\\G8BPQ\\BPQ32", 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - sprintf(msg,"%d,%d,%d,%d", Ver[0], Ver[1], Ver[2], Ver[3]); - retCode = RegSetValueEx(hKey, "Version",0, REG_SZ,(BYTE *)msg, strlen(msg) + 1); - - RegCloseKey(hKey); - } - - // Make sure Logs Directory exists - - sprintf(LogDir, "%s/Logs", LogDirectory); - - CreateDirectory(LogDir, NULL); - - return; -} - -HANDLE OpenConfigFile(char *fn) -{ - HANDLE handle; - UCHAR Value[MAX_PATH]; - FILETIME LastWriteTime; - SYSTEMTIME Time; - char Msg[256]; - - - // If no directory, use current - if (BPQDirectory[0] == 0) - { - strcpy(Value,fn); - } - else - { - strcpy(Value,BPQDirectory); - strcat(Value,"\\"); - strcat(Value,fn); - } - - handle = CreateFile(Value, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - GetFileTime(handle, NULL, NULL, &LastWriteTime); - FileTimeToSystemTime(&LastWriteTime, &Time); - - sprintf(Msg,"BPQ32 Config File %s Created %.2d:%.2d %d/%.2d/%.2d\n", Value, - Time.wHour, Time.wMinute, Time.wYear, Time.wMonth, Time.wDay); - - OutputDebugString(Msg); - - return(handle); -} - -#ifdef _WIN64 -int BPQHOSTAPI() -{ - return 0; -} -#endif - - -DllExport int APIENTRY GETBPQAPI() -{ - return (int)BPQHOSTAPI; -} - -//DllExport UINT APIENTRY GETMONDECODE() -//{ -// return (UINT)MONDECODE; -//} - - -DllExport INT APIENTRY BPQAPI(int Fn, char * params) -{ - -/* -; -; BPQ HOST MODE SUPPORT CODE -; -; 22/11/95 -; -; MOVED FROM TNCODE.ASM COS CONITIONALS WERE GETTING TOO COMPLICATED -; (OS2 VERSION HAD UPSET KANT VERISON -; -; -*/ - - -/* - - BPQHOSTPORT: -; -; SPECIAL INTERFACE, MAINLY FOR EXTERNAL HOST MODE SUPPORT PROGS -; -; COMMANDS SUPPORTED ARE -; -; AH = 0 Get node/switch version number and description. On return -; AH='B',AL='P',BH='Q',BL=' ' -; DH = major version number and DL = minor version number. -; -; -; AH = 1 Set application mask to value in DL (or even DX if 16 -; applications are ever to be supported). -; -; Set application flag(s) to value in CL (or CX). -; whether user gets connected/disconnected messages issued -; by the node etc. -; -; -; AH = 2 Send frame in ES:SI (length CX) -; -; -; AH = 3 Receive frame into buffer at ES:DI, length of frame returned -; in CX. BX returns the number of outstanding frames still to -; be received (ie. after this one) or zero if no more frames -; (ie. this is last one). -; -; -; -; AH = 4 Get stream status. Returns: -; -; CX = 0 if stream disconnected or CX = 1 if stream connected -; DX = 0 if no change of state since last read, or DX = 1 if -; the connected/disconnected state has changed since -; last read (ie. delta-stream status). -; -; -; -; AH = 6 Session control. -; -; CX = 0 Conneect - _APPLMASK in DL -; CX = 1 connect -; CX = 2 disconnect -; CX = 3 return user to node -; -; -; AH = 7 Get buffer counts for stream. Returns: -; -; AX = number of status change messages to be received -; BX = number of frames queued for receive -; CX = number of un-acked frames to be sent -; DX = number of buffers left in node -; SI = number of trace frames queued for receive -; -;AH = 8 Port control/information. Called with a stream number -; in AL returns: -; -; AL = Radio port on which channel is connected (or zero) -; AH = SESSION TYPE BITS -; BX = L2 paclen for the radio port -; CX = L2 maxframe for the radio port -; DX = L4 window size (if L4 circuit, or zero) -; ES:DI = CALLSIGN - -;AH = 9 Fetch node/application callsign & alias. AL = application -; number: -; -; 0 = node -; 1 = BBS -; 2 = HOST -; 3 = SYSOP etc. etc. -; -; Returns string with alias & callsign or application name in -; user's buffer pointed to by ES:SI length CX. For example: -; -; "WORCS:G8TIC" or "TICPMS:G8TIC-10". -; -; -; AH = 10 Unproto transmit frame. Data pointed to by ES:SI, of -; length CX, is transmitted as a HDLC frame on the radio -; port (not stream) in AL. -; -; -; AH = 11 Get Trace (RAW Data) Frame into ES:DI, -; Length to CX, Timestamp to AX -; -; -; AH = 12 Update Switch. At the moment only Beacon Text may be updated -; DX = Function -; 1=update BT. ES:SI, Len CX = Text -; 2=kick off nodes broadcast -; -; AH = 13 Allocate/deallocate stream -; If AL=0, return first free stream -; If AL>0, CL=1, Allocate stream. If aleady allocated, -; return CX nonzero, else allocate, and return CX=0 -; If AL>0, CL=2, Release stream -; -; -; AH = 14 Internal Interface for IP Router -; -; Send frame - to NETROM L3 if DL=0 -; to L2 Session if DL<>0 -; -; -; AH = 15 Get interval timer - - -*/ - - - switch(Fn) - { - - case CHECKLOADED: - - params[0]=MAJORVERSION; - params[1]=MINORVERSION; - params[2]=QCOUNT; - - return (1); - } - return 0; -} - -DllExport int APIENTRY InitSwitch() -{ - return (0); -} - -/*DllExport int APIENTRY SwitchTimer() -{ - GetSemaphore((&Semaphore); - - TIMERINTERRUPT(); - - FreeSemaphore(&Semaphore); - - return (0); -} -*/ -DllExport int APIENTRY GetFreeBuffs() -{ -// Returns number of free buffers -// (BPQHOST function 7 (part)). - return (QCOUNT); -} - -DllExport UCHAR * APIENTRY GetNodeCall() -{ - return (&MYNODECALL); -} - - -DllExport UCHAR * APIENTRY GetNodeAlias() -{ - return (&MYALIASTEXT[0]); -} - -DllExport UCHAR * APIENTRY GetBBSCall() -{ - return (UCHAR *)(&APPLCALLTABLE[0].APPLCALL_TEXT); -} - - -DllExport UCHAR * APIENTRY GetBBSAlias() -{ - return (UCHAR *)(&APPLCALLTABLE[0].APPLALIAS_TEXT); -} - -DllExport VOID APIENTRY GetApplCallVB(int Appl, char * ApplCall) -{ - if (Appl < 1 || Appl > NumberofAppls ) return; - - strncpy(ApplCall,(char *)&APPLCALLTABLE[Appl-1].APPLCALL_TEXT, 10); -} - -BOOL UpdateNodesForApp(int Appl); - -DllExport BOOL APIENTRY SetApplCall(int Appl, char * NewCall) -{ - char Call[10]=" "; - int i; - - if (Appl < 1 || Appl > NumberofAppls ) return FALSE; - - i=strlen(NewCall); - - if (i > 10) i=10; - - strncpy(Call,NewCall,i); - - strncpy((char *)&APPLCALLTABLE[Appl-1].APPLCALL_TEXT,Call,10); - - if (!ConvToAX25(Call,APPLCALLTABLE[Appl-1].APPLCALL)) return FALSE; - - UpdateNodesForApp(Appl); - - return TRUE; - -} - -DllExport BOOL APIENTRY SetApplAlias(int Appl, char * NewCall) -{ - char Call[10]=" "; - int i; - - if (Appl < 1 || Appl > NumberofAppls ) return FALSE; - - i=strlen(NewCall); - - if (i > 10) i=10; - - strncpy(Call,NewCall,i); - - strncpy((char *)&APPLCALLTABLE[Appl-1].APPLALIAS_TEXT,Call,10); - - if (!ConvToAX25(Call,APPLCALLTABLE[Appl-1].APPLALIAS)) return FALSE; - - UpdateNodesForApp(Appl); - - return TRUE; - -} - - - -DllExport BOOL APIENTRY SetApplQual(int Appl, int NewQual) -{ - if (Appl < 1 || Appl > NumberofAppls ) return FALSE; - - APPLCALLTABLE[Appl-1].APPLQUAL=NewQual; - - UpdateNodesForApp(Appl); - - return TRUE; - -} - - -BOOL UpdateNodesForApp(int Appl) -{ - int App=Appl-1; - int DestLen = sizeof (struct DEST_LIST); - int n = MAXDESTS; - - struct DEST_LIST * DEST = APPLCALLTABLE[App].NODEPOINTER; - APPLCALLS * APPL=&APPLCALLTABLE[App]; - - if (DEST == NULL) - { - // No dest at the moment. If we have valid call and Qual, create an entry - - if (APPLCALLTABLE[App].APPLQUAL == 0) return FALSE; - - if (APPLCALLTABLE[App].APPLCALL[0] < 41) return FALSE; - - - GetSemaphore(&Semaphore, 5); - - DEST = DESTS; - - while (n--) - { - if (DEST->DEST_CALL[0] == 0) // Spare - break; - } - - if (n == 0) - { - // no dests - - FreeSemaphore(&Semaphore); - return FALSE; - } - - NUMBEROFNODES++; - APPL->NODEPOINTER = DEST; - - memmove (DEST->DEST_CALL,APPL->APPLCALL,13); - - DEST->DEST_STATE=0x80; // SPECIAL ENTRY - - DEST->NRROUTE[0].ROUT_QUALITY = (BYTE)APPL->APPLQUAL; - DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; - - FreeSemaphore(&Semaphore); - - return TRUE; - } - - // We have a destination. If Quality is zero, remove it, else update it - - if (APPLCALLTABLE[App].APPLQUAL == 0) - { - GetSemaphore(&Semaphore, 6); - - REMOVENODE(DEST); // Clear buffers, Remove from Sorted Nodes chain, and zap entry - - APPL->NODEPOINTER=NULL; - - FreeSemaphore(&Semaphore); - return FALSE; - - } - - if (APPLCALLTABLE[App].APPLCALL[0] < 41) return FALSE; - - GetSemaphore(&Semaphore, 7); - - memmove (DEST->DEST_CALL,APPL->APPLCALL,13); - - DEST->DEST_STATE=0x80; // SPECIAL ENTRY - - DEST->NRROUTE[0].ROUT_QUALITY = (BYTE)APPL->APPLQUAL; - DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; - - FreeSemaphore(&Semaphore); - return TRUE; - -} - - -DllExport UCHAR * APIENTRY GetSignOnMsg() -{ - return (&SIGNONMSG[0]); -} - - -DllExport HKEY APIENTRY GetRegistryKey() -{ - return REGTREE; -} - -DllExport char * APIENTRY GetRegistryKeyText() -{ - return REGTREETEXT;; -} - -DllExport UCHAR * APIENTRY GetBPQDirectory() -{ - while (BPQDirectory[0] == 0) - { - Debugprintf("BPQ Directory not set up - waiting"); - Sleep(1000); - } - return (&BPQDirectory[0]); -} - -DllExport UCHAR * APIENTRY GetProgramDirectory() -{ - return (&BPQProgramDirectory[0]); -} - -DllExport UCHAR * APIENTRY GetLogDirectory() -{ - return (&LogDirectory[0]); -} - -// Version for Visual Basic - -DllExport char * APIENTRY CopyBPQDirectory(char * dir) -{ - return (strcpy(dir,BPQDirectory)); -} - -DllExport int APIENTRY GetMsgPerl(int stream, char * msg) -{ - int len,count; - - GetMsg(stream, msg, &len, &count ); - - return len; -} - -int Rig_Command(int Session, char * Command); - -BOOL Rig_CommandInt(int Session, char * Command) -{ - return Rig_Command(Session, Command); -} - -DllExport int APIENTRY BPQSetHandle(int Stream, HWND hWnd) -{ - BPQHOSTVECTOR[Stream-1].HOSTHANDLE=hWnd; - return (0); -} - -#define L4USER 0 - -BPQVECSTRUC * PORTVEC ; - -VOID * InitializeExtDriver(PEXTPORTDATA PORTVEC) -{ - HINSTANCE ExtDriver=0; - char msg[128]; - int err=0; - HKEY hKey=0; - UCHAR Value[MAX_PATH]; - - // If no directory, use current - - if (BPQDirectory[0] == 0) - { - strcpy(Value,PORTVEC->PORT_DLL_NAME); - } - else - { - strcpy(Value,BPQDirectory); - strcat(Value,"\\"); - strcat(Value,PORTVEC->PORT_DLL_NAME); - } - - // Several Drivers are now built into bpq32.dll - - _strupr(Value); - - if (strstr(Value, "BPQVKISS")) - return VCOMExtInit; - - if (strstr(Value, "BPQAXIP")) - return AXIPExtInit; - - if (strstr(Value, "BPQETHER")) - return ETHERExtInit; - - if (strstr(Value, "BPQTOAGW")) - return AGWExtInit; - - if (strstr(Value, "AEAPACTOR")) - return AEAExtInit; - - if (strstr(Value, "HALDRIVER")) - return HALExtInit; - - if (strstr(Value, "KAMPACTOR")) - return KAMExtInit; - - if (strstr(Value, "SCSPACTOR")) - return SCSExtInit; - - if (strstr(Value, "WINMOR")) - return WinmorExtInit; - - if (strstr(Value, "V4")) - return V4ExtInit; - - if (strstr(Value, "TELNET")) - return TelnetExtInit; - -// if (strstr(Value, "SOUNDMODEM")) -// return SoundModemExtInit; - - if (strstr(Value, "SCSTRACKER")) - return TrackerExtInit; - - if (strstr(Value, "TRKMULTI")) - return TrackerMExtInit; - - if (strstr(Value, "UZ7HO")) - return UZ7HOExtInit; - - if (strstr(Value, "MULTIPSK")) - return MPSKExtInit; - - if (strstr(Value, "FLDIGI")) - return FLDigiExtInit; - - if (strstr(Value, "UIARQ")) - return UIARQExtInit; - -// if (strstr(Value, "BAYCOM")) -// return (UINT) BaycomExtInit; - - if (strstr(Value, "VARA")) - return VARAExtInit; - - if (strstr(Value, "ARDOP")) - return ARDOPExtInit; - - if (strstr(Value, "SERIAL")) - return SerialExtInit; - - if (strstr(Value, "KISSHF")) - return KISSHFExtInit; - - if (strstr(Value, "WINRPR")) - return WinRPRExtInit; - - if (strstr(Value, "HSMODEM")) - return HSMODEMExtInit; - - if (strstr(Value, "FREEDATA")) - return FreeDataExtInit; - - ExtDriver = LoadLibrary(Value); - - if (ExtDriver == NULL) - { - err=GetLastError(); - - sprintf(msg,"Error loading Driver %s - Error code %d", - PORTVEC->PORT_DLL_NAME,err); - - MessageBox(NULL,msg,"BPQ32",MB_ICONSTOP); - - return(0); - } - - PORTVEC->DLLhandle=ExtDriver; - - return (GetProcAddress(ExtDriver,"_ExtInit@4")); - -} - -/* -_DATABASE LABEL BYTE - -FILLER DB 14 DUP (0) ; PROTECTION AGENST BUFFER PROBLEMS! - DB MAJORVERSION,MINORVERSION -_NEIGHBOURS DD 0 - DW TYPE ROUTE -_MAXNEIGHBOURS DW 20 ; MAX ADJACENT NODES - -_DESTS DD 0 ; NODE LIST - DW TYPE DEST_LIST -MAXDESTS DW 100 ; MAX NODES IN SYSTEM -*/ - - -DllExport int APIENTRY GetAttachedProcesses() -{ - return (AttachedProcesses); -} - -DllExport int * APIENTRY GetAttachedProcessList() -{ - return (&AttachedPIDList[0]); -} - -DllExport int * APIENTRY SaveNodesSupport() -{ - return (&DATABASESTART); -} - -// -// Internal BPQNODES support -// - -#define UCHAR unsigned char - -/* -ROUTE ADD G1HTL-1 2 200 0 0 0 -ROUTE ADD G4IRX-3 2 200 0 0 0 -NODE ADD MAPPLY:G1HTL-1 G1HTL-1 2 200 G4IRX-3 2 98 -NODE ADD NOT:GB7NOT G1HTL-1 2 199 G4IRX-3 2 98 - -*/ - -struct DEST_LIST * Dests; -struct ROUTE * Routes; - -int MaxNodes; -int MaxRoutes; -int NodeLen; -int RouteLen; - -int count; -int cursor; - -int len,i; - -ULONG cnt; -char Normcall[10]; -char Portcall[10]; -char Alias[7]; - -char line[100]; - -HANDLE handle; - -int APIENTRY Restart() -{ - int i, Count = AttachedProcesses; - HANDLE hProc; - DWORD PID; - - for (i = 0; i < Count; i++) - { - PID = AttachedPIDList[i]; - - // Kill Timer Owner last - - if (TimerInst != PID) - { - hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID); - - if (hProc) - { - TerminateProcess(hProc, 0); - CloseHandle(hProc); - } - } - } - - hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, TimerInst); - - if (hProc) - { - TerminateProcess(hProc, 0); - CloseHandle(hProc); - } - - - return 0; -} - -int APIENTRY Reboot() -{ - // Run shutdown -r -f - - STARTUPINFO SInfo; - PROCESS_INFORMATION PInfo; - char Cmd[] = "shutdown -r -f"; - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - return CreateProcess(NULL, Cmd, NULL, NULL, FALSE,0 ,NULL ,NULL, &SInfo, &PInfo); -} -/* -int APIENTRY Reconfig() -{ - if (!ProcessConfig()) - { - return (0); - } - SaveNodes(); - WritetoConsole("Nodes Saved\n"); - ReconfigFlag=TRUE; - WritetoConsole("Reconfig requested ... Waiting for Timer Poll\n"); - return 1; -} -*/ -// Code to support minimizing all BPQ Apps to a single Tray ICON - -// As we can't minimize the console window to the tray, I'll use an ordinary -// window instead. This also gives me somewhere to post the messages to - - -char AppName[] = "BPQ32"; -char Title[80] = "BPQ32.dll Console"; - -int NewLine(); - -char FrameClassName[] = TEXT("MdiFrame"); - -HWND ClientWnd; //This stores the MDI client area window handle - -LOGFONT LFTTYFONT ; - -HFONT hFont ; - -HMENU hPopMenu, hWndMenu; -HMENU hMainFrameMenu = NULL; -HMENU hBaseMenu = NULL; -HMENU hConsMenu = NULL; -HMENU hTermMenu = NULL; -HMENU hMonMenu = NULL; -HMENU hTermActMenu, hTermCfgMenu, hTermEdtMenu, hTermHlpMenu; -HMENU hMonActMenu, hMonCfgMenu, hMonEdtMenu, hMonHlpMenu; - - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - -DllExport int APIENTRY DeleteTrayMenuItem(HWND hWnd); - -#define BPQMonitorAvail 1 -#define BPQDataAvail 2 -#define BPQStateChange 4 - -VOID GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value); -SOCKET OpenWL2KHTTPSock(); -SendHTTPRequest(SOCKET sock, char * Request, char * Params, int Len, char * Return); - -BOOL GetWL2KSYSOPInfo(char * Call, char * _REPLYBUFFER); -BOOL UpdateWL2KSYSOPInfo(char * Call, char * SQL); - - -static INT_PTR CALLBACK ConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_INITDIALOG: - { - char _REPLYBUFFER[1000] = ""; - char Value[1000]; - - if (GetWL2KSYSOPInfo(WL2KCall, _REPLYBUFFER)) - { -// if (strstr(_REPLYBUFFER, "\"ErrorMessage\":") == 0) - - GetJSONValue(_REPLYBUFFER, "\"SysopName\":", Value); - SetDlgItemText(hDlg, NAME, Value); - - GetJSONValue(_REPLYBUFFER, "\"GridSquare\":", Value); - SetDlgItemText(hDlg, IDC_Locator, Value); - - GetJSONValue(_REPLYBUFFER, "\"StreetAddress1\":", Value); - SetDlgItemText(hDlg, ADDR1, Value); - - GetJSONValue(_REPLYBUFFER, "\"StreetAddress2\":", Value); - SetDlgItemText(hDlg, ADDR2, Value); - - GetJSONValue(_REPLYBUFFER, "\"City\":", Value); - SetDlgItemText(hDlg, CITY, Value); - - GetJSONValue(_REPLYBUFFER, "\"State\":", Value); - SetDlgItemText(hDlg, STATE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Country\":", Value); - SetDlgItemText(hDlg, COUNTRY, Value); - - GetJSONValue(_REPLYBUFFER, "\"PostalCode\":", Value); - SetDlgItemText(hDlg, POSTCODE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Email\":", Value); - SetDlgItemText(hDlg, EMAIL, Value); - - GetJSONValue(_REPLYBUFFER, "\"Website\":", Value); - SetDlgItemText(hDlg, WEBSITE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Phones\":", Value); - SetDlgItemText(hDlg, PHONE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Comments\":", Value); - SetDlgItemText(hDlg, ADDITIONALDATA, Value); - - } - - return (INT_PTR)TRUE; - } - case WM_COMMAND: - - switch(LOWORD(wParam)) - { - - case ID_SAVE: - { - char Name[100]; - char PasswordText[100]; - char LocatorText[100]; - char Addr1[100]; - char Addr2[100]; - char City[100]; - char State[100]; - char Country[100]; - char PostCode[100]; - char Email[100]; - char Website[100]; - char Phone[100]; - char Data[100]; - - SOCKET sock; - - int Len; - char Message[2048]; - char Reply[2048] = ""; - - - GetDlgItemText(hDlg, NAME, Name, 99); - GetDlgItemText(hDlg, IDC_Password, PasswordText, 99); - GetDlgItemText(hDlg, IDC_Locator, LocatorText, 99); - GetDlgItemText(hDlg, ADDR1, Addr1, 99); - GetDlgItemText(hDlg, ADDR2, Addr2, 99); - GetDlgItemText(hDlg, CITY, City, 99); - GetDlgItemText(hDlg, STATE, State, 99); - GetDlgItemText(hDlg, COUNTRY, Country, 99); - GetDlgItemText(hDlg, POSTCODE, PostCode, 99); - GetDlgItemText(hDlg, EMAIL, Email, 99); - GetDlgItemText(hDlg, WEBSITE, Website, 99); - GetDlgItemText(hDlg, PHONE, Phone, 99); - GetDlgItemText(hDlg, ADDITIONALDATA, Data, 99); - - -//{"Callsign":"String","GridSquare":"String","SysopName":"String", -//"StreetAddress1":"String","StreetAddress2":"String","City":"String", -//"State":"String","Country":"String","PostalCode":"String","Email":"String", -//"Phones":"String","Website":"String","Comments":"String"} - - Len = sprintf(Message, - "\"Callsign\":\"%s\"," - "\"Password\":\"%s\"," - "\"GridSquare\":\"%s\"," - "\"SysopName\":\"%s\"," - "\"StreetAddress1\":\"%s\"," - "\"StreetAddress2\":\"%s\"," - "\"City\":\"%s\"," - "\"State\":\"%s\"," - "\"Country\":\"%s\"," - "\"PostalCode\":\"%s\"," - "\"Email\":\"%s\"," - "\"Phones\":\"%s\"," - "\"Website\":\"%s\"," - "\"Comments\":\"%s\"", - - WL2KCall, PasswordText, LocatorText, Name, Addr1, Addr2, City, State, Country, PostCode, Email, Phone, Website, Data); - - Debugprintf("Sending %s", Message); - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - char * ptr; - - SendHTTPRequest(sock, - "/sysop/add", Message, Len, Reply); - - ptr = strstr(Reply, "\"ErrorCode\":"); - - if (ptr) - { - ptr = strstr(ptr, "Message"); - if (ptr) - { - ptr += 10; - strlop(ptr, '"'); - MessageBox(NULL ,ptr, "Error", MB_OK); - } - } - else - MessageBox(NULL, "Sysop Record Updated", "BPQ32", MB_OK); - - } - closesocket(sock); - } - - case ID_CANCEL: - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - break; - } - } - return (INT_PTR)FALSE; -} - - - -LRESULT CALLBACK UIWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -VOID WINAPI OnTabbedDialogInit(HWND hDlg); - -LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - POINT pos; - BOOL ret; - - CLIENTCREATESTRUCT MDIClientCreateStruct; // Structure to be used for MDI client area - //HWND m_hwndSystemInformation = 0; - - if (message == BPQMsg) - { - if (lParam & BPQDataAvail) - DoReceivedData(wParam); - - if (lParam & BPQMonitorAvail) - DoMonData(wParam); - - if (lParam & BPQStateChange) - DoStateChange(wParam); - - return (0); - } - - switch (message) - { - case MY_TRAY_ICON_MESSAGE: - - switch(lParam) - { - case WM_RBUTTONUP: - case WM_LBUTTONUP: - - GetCursorPos(&pos); - - // SetForegroundWindow(FrameWnd); - - TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, FrameWnd, 0); - return 0; - } - - break; - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - case WM_SIZING: - case WM_SIZE: - - SendMessage(ClientWnd, WM_MDIICONARRANGE, 0 ,0); - break; - - case WM_NCCREATE: - - ret = DefFrameProc(hWnd, ClientWnd, message, wParam, lParam); - return TRUE; - - case WM_CREATE: - - // On creation of main frame, create the MDI client area - - MDIClientCreateStruct.hWindowMenu = NULL; - MDIClientCreateStruct.idFirstChild = IDM_FIRSTCHILD; - - ClientWnd = CreateWindow(TEXT("MDICLIENT"), // predefined value for MDI client area - NULL, // no caption required - WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, - 0, // No need to give any x/y or height/width since this client - // will just be used to get client windows created, effectively - // in the main window we will be seeing the mainframe window client area itself. - 0, - 0, - 0, - hWnd, - NULL, - hInstance, - (void *) &MDIClientCreateStruct); - - - return 0; - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - if (wmId >= TRAYBASEID && wmId < (TRAYBASEID + 100)) - { - handle=hWndArray[wmId-TRAYBASEID]; - - if (handle == FrameWnd) - ShowWindow(handle, SW_NORMAL); - - if (handle == FrameWnd && FrameMaximized == TRUE) - PostMessage(handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); - else - PostMessage(handle, WM_SYSCOMMAND, SC_RESTORE, 0); - - SetForegroundWindow(handle); - return 0; - } - - switch(wmId) - { - struct ConsoleInfo * Cinfo = NULL; - - case ID_NEWWINDOW: - Cinfo = CreateChildWindow(0, FALSE); - if (Cinfo) - SendMessage(ClientWnd, WM_MDIACTIVATE, (WPARAM)Cinfo->hConsole, 0); - break; - - case ID_WINDOWS_CASCADE: - SendMessage(ClientWnd, WM_MDICASCADE, 0, 0); - return 0; - - case ID_WINDOWS_TILE: - SendMessage(ClientWnd, WM_MDITILE , MDITILE_HORIZONTAL, 0); - return 0; - - case BPQCLOSEALL: - CloseAllPrograms(); - // SendMessage(ClientWnd, WM_MDIICONARRANGE, 0 ,0); - - return 0; - - case BPQUICONFIG: - { - int err, i=0; - char Title[80]; - WNDCLASS wc; - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = UIWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - - wc.lpszMenuName = NULL; - wc.lpszClassName = UIClassName; - - RegisterClass(&wc); - - UIhWnd = CreateDialog(hInstance, UIClassName, 0, NULL); - - if (!UIhWnd) - { - err=GetLastError(); - return FALSE; - } - - wsprintf(Title,"BPQ32 Beacon Configuration"); - MySetWindowText(UIhWnd, Title); - ShowWindow(UIhWnd, SW_NORMAL); - - OnTabbedDialogInit(UIhWnd); // Set up pages - - // UpdateWindow(UIhWnd); - return 0; - } - - - case IDD_WL2KSYSOP: - - if (WL2KCall[0] == 0) - { - MessageBox(NULL,"WL2K Reporting is not configured","BPQ32", MB_OK); - break; - } - - DialogBox(hInstance, MAKEINTRESOURCE(IDD_WL2KSYSOP), hWnd, ConfigWndProc); - break; - - - // Handle MDI Window commands - - default: - { - if(wmId >= IDM_FIRSTCHILD) - { - DefFrameProc(hWnd, ClientWnd, message, wParam, lParam); - } - else - { - HWND hChild = (HWND)SendMessage(ClientWnd, WM_MDIGETACTIVE,0,0); - - if(hChild) - SendMessage(hChild, WM_COMMAND, wParam, lParam); - } - } - } - - break; - - case WM_INITMENUPOPUP: - { - HWND hChild = (HWND)SendMessage(ClientWnd, WM_MDIGETACTIVE,0,0); - - if(hChild) - SendMessage(hChild, WM_INITMENUPOPUP, wParam, lParam); - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_MAXIMIZE: - - FrameMaximized = TRUE; - break; - - case SC_RESTORE: - - FrameMaximized = FALSE; - break; - - case SC_MINIMIZE: - - if (MinimizetoTray) - { - ShowWindow(hWnd, SW_HIDE); - return TRUE; - } - } - - return (DefFrameProc(hWnd, ClientWnd, message, wParam, lParam)); - - case WM_CLOSE: - - PostQuitMessage(0); - - if (MinimizetoTray) - DeleteTrayMenuItem(hWnd); - - break; - - default: - return (DefFrameProc(hWnd, ClientWnd, message, wParam, lParam)); - - } - return (DefFrameProc(hWnd, ClientWnd, message, wParam, lParam)); -} - -int OffsetH, OffsetW; - -int SetupConsoleWindow() -{ - WNDCLASS wc; - int i; - int retCode, Type, Vallen; - HKEY hKey=0; - char Size[80]; - WNDCLASSEX wndclassMainFrame; - RECT CRect; - - retCode = RegOpenKeyEx (REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"FrameWindowSize",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size,"%d,%d,%d,%d",&FRect.left,&FRect.right,&FRect.top,&FRect.bottom); - - if (FRect.top < - 500 || FRect.left < - 500) - { - FRect.left = 0; - FRect.top = 0; - FRect.right = 600; - FRect.bottom = 400; - } - - - Vallen=80; - retCode = RegQueryValueEx(hKey,"WindowSize",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size,"%d,%d,%d,%d,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom, &ConsoleMinimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - Vallen=80; - - retCode = RegQueryValueEx(hKey,"StatusWindowSize",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size, "%d,%d,%d,%d,%d", &StatusRect.left, &StatusRect.right, - &StatusRect.top, &StatusRect.bottom, &StatusMinimized); - - if (StatusRect.top < - 500 || StatusRect.left < - 500) - { - StatusRect.left = 0; - StatusRect.top = 0; - StatusRect.right = 850; - StatusRect.bottom = 500; - } - - - // Get StartMinimized and MinimizetoTray flags - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Start Minimized", 0, &Type, (UCHAR *)&StartMinimized, &Vallen); - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Minimize to Tray", 0, &Type, (UCHAR *)&MinimizetoTray, &Vallen); - } - - wndclassMainFrame.cbSize = sizeof(WNDCLASSEX); - wndclassMainFrame.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wndclassMainFrame.lpfnWndProc = FrameWndProc; - wndclassMainFrame.cbClsExtra = 0; - wndclassMainFrame.cbWndExtra = 0; - wndclassMainFrame.hInstance = hInstance; - wndclassMainFrame.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON)); - wndclassMainFrame.hCursor = LoadCursor(NULL, IDC_ARROW); - wndclassMainFrame.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH); - wndclassMainFrame.lpszMenuName = NULL; - wndclassMainFrame.lpszClassName = FrameClassName; - wndclassMainFrame.hIconSm = NULL; - - if(!RegisterClassEx(&wndclassMainFrame)) - { - return 0; - } - - pindex = 0; - PartLine = FALSE; - - bgBrush = CreateSolidBrush(BGCOLOUR); - -// hMainFrameMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MAINFRAME_MENU)); - - hBaseMenu = LoadMenu(hInstance, MAKEINTRESOURCE(CONS_MENU)); - hConsMenu = GetSubMenu(hBaseMenu, 1); - hWndMenu = GetSubMenu(hBaseMenu, 0); - - hTermMenu = LoadMenu(hInstance, MAKEINTRESOURCE(TERM_MENU)); - hTermActMenu = GetSubMenu(hTermMenu, 1); - hTermCfgMenu = GetSubMenu(hTermMenu, 2); - hTermEdtMenu = GetSubMenu(hTermMenu, 3); - hTermHlpMenu = GetSubMenu(hTermMenu, 4); - - hMonMenu = LoadMenu(hInstance, MAKEINTRESOURCE(MON_MENU)); - hMonCfgMenu = GetSubMenu(hMonMenu, 1); - hMonEdtMenu = GetSubMenu(hMonMenu, 2); - hMonHlpMenu = GetSubMenu(hMonMenu, 3); - - hMainFrameMenu = CreateMenu(); - AppendMenu(hMainFrameMenu, MF_STRING + MF_POPUP, (UINT)hWndMenu, "Window"); - - //Create the main MDI frame window - - ClientWnd = NULL; - - FrameWnd = CreateWindow(FrameClassName, - "BPQ32 Console", - WS_OVERLAPPEDWINDOW |WS_CLIPCHILDREN, - FRect.left, - FRect.top, - FRect.right - FRect.left, - FRect.bottom - FRect.top, - NULL, // handle to parent window - hMainFrameMenu, // handle to menu - hInstance, // handle to the instance of module - NULL); // Long pointer to a value to be passed to the window through the - // CREATESTRUCT structure passed in the lParam parameter the WM_CREATE message - - - // Get Client Params - - if (FrameWnd == 0) - { - Debugprintf("SetupConsoleWindow Create Frame failed %d", GetLastError()); - return 0; - } - - ShowWindow(FrameWnd, SW_RESTORE); - - - GetWindowRect(FrameWnd, &FRect); - OffsetH = FRect.bottom - FRect.top; - OffsetW = FRect.right - FRect.left; - GetClientRect(FrameWnd, &CRect); - OffsetH -= CRect.bottom; - OffsetW -= CRect.right; - OffsetH -= 4; - - // Create Console Window - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = 0; - wc.lpszClassName = ClassName; - - i=RegisterClass(&wc); - - sprintf (Title, "BPQ32.dll Console Version %s", VersionString); - - hConsWnd = CreateMDIWindow(ClassName, "Console", 0, - 0,0,0,0, ClientWnd, hInstance, 1234); - - i = GetLastError(); - - if (!hConsWnd) { - return (FALSE); - } - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)StatusWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = 0; - wc.lpszClassName = "Status"; - - i=RegisterClass(&wc); - - if (StatusRect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - StatusRect.top; - StatusRect.top += Error; - StatusRect.bottom += Error; - } - - StatusWnd = CreateMDIWindow("Status", "Stream Status", 0, - StatusRect.left, StatusRect.top, StatusRect.right - StatusRect.left, - StatusRect.bottom - StatusRect.top, ClientWnd, hInstance, 1234); - - SetTimer(StatusWnd, 1, 1000, NULL); - - hPopMenu = GetSubMenu(hBaseMenu, 1) ; - - if (MinimizetoTray) - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_UNCHECKED); - - if (StartMinimized) - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_UNCHECKED); - - DrawMenuBar(hConsWnd); - - // setup default font information - - LFTTYFONT.lfHeight = 12; - LFTTYFONT.lfWidth = 8 ; - LFTTYFONT.lfEscapement = 0 ; - LFTTYFONT.lfOrientation = 0 ; - LFTTYFONT.lfWeight = 0 ; - LFTTYFONT.lfItalic = 0 ; - LFTTYFONT.lfUnderline = 0 ; - LFTTYFONT.lfStrikeOut = 0 ; - LFTTYFONT.lfCharSet = 0; - LFTTYFONT.lfOutPrecision = OUT_DEFAULT_PRECIS ; - LFTTYFONT.lfClipPrecision = CLIP_DEFAULT_PRECIS ; - LFTTYFONT.lfQuality = DEFAULT_QUALITY ; - LFTTYFONT.lfPitchAndFamily = FIXED_PITCH; - lstrcpy(LFTTYFONT.lfFaceName, "FIXEDSYS" ) ; - - hFont = CreateFontIndirect(&LFTTYFONT) ; - - SetWindowText(hConsWnd,Title); - - if (Rect.right < 100 || Rect.bottom < 100) - { - GetWindowRect(hConsWnd, &Rect); - } - - if (Rect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - Rect.top; - Rect.top += Error; - Rect.bottom += Error; - } - - - MoveWindow(hConsWnd, Rect.left - (OffsetW /2), Rect.top - OffsetH, Rect.right-Rect.left, Rect.bottom-Rect.top, TRUE); - - MoveWindow(StatusWnd, StatusRect.left - (OffsetW /2), StatusRect.top - OffsetH, - StatusRect.right-StatusRect.left, StatusRect.bottom-StatusRect.top, TRUE); - - hWndCons = CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "", - WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | LBS_NOSEL | WS_VSCROLL | WS_HSCROLL, - Rect.left, Rect.top, Rect.right - Rect.left, Rect.bottom - Rect.top, - hConsWnd, NULL, hInstance, NULL); - -// SendMessage(hWndCons, WM_SETFONT, hFont, 0); - - SendMessage(hWndCons, LB_SETHORIZONTALEXTENT , 1000, 0); - - if (ConsoleMinimized) - ShowWindow(hConsWnd, SW_SHOWMINIMIZED); - else - ShowWindow(hConsWnd, SW_RESTORE); - - if (StatusMinimized) - ShowWindow(StatusWnd, SW_SHOWMINIMIZED); - else - ShowWindow(StatusWnd, SW_RESTORE); - - ShowWindow(FrameWnd, SW_RESTORE); - - - LoadLibrary("riched20.dll"); - - if (StartMinimized) - if (MinimizetoTray) - ShowWindow(FrameWnd, SW_HIDE); - else - ShowWindow(FrameWnd, SW_SHOWMINIMIZED); - else - ShowWindow(FrameWnd, SW_RESTORE); - - CreateMonitorWindow(Size); - - return 0; -} - -DllExport int APIENTRY SetupTrayIcon() -{ - if (MinimizetoTray == 0) - return 0; - - trayMenu = CreatePopupMenu(); - - for( i = 0; i < 100; ++i ) - { - if (strcmp(PopupText[i],"BPQ32 Console") == 0) - { - hWndArray[i] = FrameWnd; - goto doneit; - } - } - - for( i = 0; i < 100; ++i ) - { - if (hWndArray[i] == 0) - { - hWndArray[i] = FrameWnd; - strcpy(PopupText[i],"BPQ32 Console"); - break; - } - } -doneit: - - for( i = 0; i < 100; ++i ) - { - if (hWndArray[i] != 0) - AppendMenu(trayMenu,MF_STRING,TRAYBASEID+i,PopupText[i]); - } - - // Set up Tray ICON - - ZeroMemory(&niData,sizeof(NOTIFYICONDATA)); - - niData.cbSize = sizeof(NOTIFYICONDATA); - - // the ID number can be any UINT you choose and will - // be used to identify your icon in later calls to - // Shell_NotifyIcon - - niData.uID = TRAY_ICON_ID; - - // state which structure members are valid - // here you can also choose the style of tooltip - // window if any - specifying a balloon window: - // NIF_INFO is a little more complicated - - strcpy(niData.szTip,"BPQ32 Windows"); - - niData.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; - - // load the icon note: you should destroy the icon - // after the call to Shell_NotifyIcon - - niData.hIcon = - - //LoadIcon(NULL, IDI_APPLICATION); - - (HICON)LoadImage( hInstance, - MAKEINTRESOURCE(BPQICON), - IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - LR_DEFAULTCOLOR); - - - // set the window you want to receive event messages - - niData.hWnd = FrameWnd; - - // set the message to send - // note: the message value should be in the - // range of WM_APP through 0xBFFF - - niData.uCallbackMessage = MY_TRAY_ICON_MESSAGE; - - // Call Shell_NotifyIcon. NIM_ADD adds a new tray icon - - if (Shell_NotifyIcon(NIM_ADD,&niData)) - Debugprintf("BPQ32 Create Tray Icon Ok"); -// else -// Debugprintf("BPQ32 Create Tray Icon failed %d", GetLastError()); - - return 0; -} - -VOID SaveConfig() -{ - HKEY hKey=0; - int retCode, disp; - - retCode = RegCreateKeyEx(REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, // Reserved - 0, // Class - 0, // Options - KEY_ALL_ACCESS, - NULL, // Security Attrs - &hKey, - &disp); - - if (retCode == ERROR_SUCCESS) - { - retCode = RegSetValueEx(hKey, "Start Minimized", 0, REG_DWORD, (UCHAR *)&StartMinimized, 4); - retCode = RegSetValueEx(hKey, "Minimize to Tray", 0, REG_DWORD, (UCHAR *)&MinimizetoTray, 4); - } -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - POINT pos; - HWND handle; - RECT cRect; - - switch (message) - { - case WM_MDIACTIVATE: - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - // GetSubMenu function should retrieve a handle to the drop-down menu or submenu. - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)hConsMenu, "Actions"); - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - DrawMenuBar(FrameWnd); - - return TRUE; //DefMDIChildProc(hWnd, message, wParam, lParam); - - case MY_TRAY_ICON_MESSAGE: - - switch(lParam) - { - case WM_RBUTTONUP: - case WM_LBUTTONUP: - - GetCursorPos(&pos); - - SetForegroundWindow(hWnd); - - TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, hWnd, 0); - return 0; - } - - break; - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - if (wmId == IDC_ENIGATE) - { - int retCode, disp; - HKEY hKey=0; - - IGateEnabled = IsDlgButtonChecked(hWnd, IDC_ENIGATE); - - if (IGateEnabled) - ISDelayTimer = 60; - - retCode = RegCreateKeyEx(REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, // Reserved - 0, // Class - 0, // Options - KEY_ALL_ACCESS, - NULL, // Security Attrs - &hKey, - &disp); - - if (retCode == ERROR_SUCCESS) - { - retCode = RegSetValueEx(hKey,"IGateEnabled", 0 , REG_DWORD,(BYTE *)&IGateEnabled, 4); - RegCloseKey(hKey); - } - - return 0; - } - - if (wmId == BPQSAVENODES) - { - SaveNodes(); - WritetoConsole("Nodes Saved\n"); - return 0; - } - if (wmId == BPQCLEARRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - - ClearNodes(); - WritetoConsole("Nodes file Cleared\n"); - ReconfigFlag=TRUE; - WritetoConsole("Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - if (wmId == BPQRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - SaveNodes(); - WritetoConsole("Nodes Saved\n"); - ReconfigFlag=TRUE; - WritetoConsole("Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - - if (wmId == SCANRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - - RigReconfigFlag = TRUE; - WritetoConsole("Rigcontrol Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - - if (wmId == APRSRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - - APRSReconfigFlag=TRUE; - WritetoConsole("APRS Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - if (wmId == BPQDUMP) - { - DumpSystem(); - return 0; - } - - if (wmId == BPQCLOSEALL) - { - CloseAllPrograms(); - return 0; - } - - if (wmId == BPQUICONFIG) - { - int err, i=0; - char Title[80]; - WNDCLASS wc; - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = UIWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - - wc.lpszMenuName = NULL; - wc.lpszClassName = UIClassName; - - RegisterClass(&wc); - - UIhWnd = CreateDialog(hInstance, UIClassName,0,NULL); - - if (!UIhWnd) - { - err=GetLastError(); - return FALSE; - } - - wsprintf(Title,"BPQ32 Beacon Utility Version"); - MySetWindowText(UIhWnd, Title); - return 0; - } - - if (wmId == BPQSAVEREG) - { - CreateRegBackup(); - return 0; - } - - if (wmId == BPQMINTOTRAY) - { - MinimizetoTray = !MinimizetoTray; - - if (MinimizetoTray) - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_UNCHECKED); - - SaveConfig(); - return 0; - } - - if (wmId == BPQSTARTMIN) - { - StartMinimized = !StartMinimized; - - if (StartMinimized) - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_UNCHECKED); - - SaveConfig(); - return 0; - } - - if (wmId >= TRAYBASEID && wmId < (TRAYBASEID + 100)) - { - handle=hWndArray[wmId-TRAYBASEID]; - - if (handle == FrameWnd && FrameMaximized == TRUE) - PostMessage(handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); - else - PostMessage(handle, WM_SYSCOMMAND, SC_RESTORE, 0); - - SetForegroundWindow(handle); - return 0; - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_MINIMIZE: - - ConsoleMinimized = TRUE; - break; - - case SC_RESTORE: - - ConsoleMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - - case WM_SIZE: - - GetClientRect(hWnd, &cRect); - - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - -// InvalidateRect(hWnd, NULL, TRUE); - break; - -/* - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - - hOldFont = SelectObject( hdc, hFont) ; - - for (i=0; i 300) - len = 300; - - memcpy(&buffptr[2], buff, len + 1); - - C_Q_ADD(&WritetoConsoleQ, buffptr); - - return 0; -} - -int WritetoConsoleSupport(char * buff) -{ - - int len=strlen(buff); - char Temp[2000]= ""; - char * ptr; - - if (PartLine) - { - SendMessage(hWndCons, LB_GETTEXT, pindex, (LPARAM)(LPCTSTR) Temp); - SendMessage(hWndCons, LB_DELETESTRING, pindex, 0); - PartLine = FALSE; - } - - if ((strlen(Temp) + strlen(buff)) > 1990) - Temp[0] = 0; // Should never have anything this long - - strcat(Temp, buff); - - ptr = strchr(Temp, '\n'); - - if (ptr) - *ptr = 0; - else - PartLine = TRUE; - - pindex=SendMessage(hWndCons, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR) Temp); - return 0; - } - -DllExport VOID APIENTRY BPQOutputDebugString(char * String) -{ - OutputDebugString(String); - return; - } - -HANDLE handle; -char fn[]="BPQDUMP"; -ULONG cnt; -char * stack; -//char screen[1920]; -//COORD ReadCoord; - -#define DATABYTES 400000 - -extern UCHAR DATAAREA[]; - -DllExport int APIENTRY DumpSystem() -{ - char fn[200]; - char Msg[250]; - - sprintf(fn,"%s\\BPQDUMP",BPQDirectory); - - handle = CreateFile(fn, - GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - -#ifndef _WIN64 - - _asm { - - mov stack,esp - } - - WriteFile(handle,stack,128,&cnt,NULL); -#endif - -// WriteFile(handle,Screen,MAXLINELEN*MAXSCREENLEN,&cnt,NULL); - - WriteFile(handle,DATAAREA, DATABYTES,&cnt,NULL); - - CloseHandle(handle); - - sprintf(Msg, "Dump to %s Completed\n", fn); - WritetoConsole(Msg); - - FindLostBuffers(); - - return (0); -} - -BOOLEAN CheckifBPQ32isLoaded() -{ - HANDLE Mutex; - - // See if BPQ32 is running - if we create it in the NTVDM address space by - // loading bpq32.dll it will not work. - - Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"BPQLOCKMUTEX"); - - if (Mutex == NULL) - { - if (AttachingProcess == 0) // Already starting BPQ32 - { - OutputDebugString("BPQ32 No other bpq32 programs running - Loading BPQ32.exe\n"); - StartBPQ32(); - } - return FALSE; - } - - CloseHandle(Mutex); - - return TRUE; -} - -BOOLEAN StartBPQ32() -{ - UCHAR Value[100]; - - char bpq[]="BPQ32.exe"; - char *fn=(char *)&bpq; - HKEY hKey=0; - int ret,Type,Vallen=99; - - char Errbuff[100]; - char buff[20]; - - STARTUPINFO StartupInfo; // pointer to STARTUPINFO - PROCESS_INFORMATION ProcessInformation; // pointer to PROCESS_INFORMATION - - AttachingProcess = 1; - -// Get address of BPQ Directory - - Value[0]=0; - - ret = RegOpenKeyEx (REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (ret == ERROR_SUCCESS) - { - ret = RegQueryValueEx(hKey, "BPQ Program Directory", 0, &Type,(UCHAR *)&Value, &Vallen); - - if (ret == ERROR_SUCCESS) - { - if (strlen(Value) == 2 && Value[0] == '"' && Value[1] == '"') - Value[0]=0; - } - - - if (Value[0] == 0) - { - - // BPQ Directory absent or = "" - "try Config File Location" - - ret = RegQueryValueEx(hKey,"BPQ Directory",0, - &Type,(UCHAR *)&Value,&Vallen); - - if (ret == ERROR_SUCCESS) - { - if (strlen(Value) == 2 && Value[0] == '"' && Value[1] == '"') - Value[0]=0; - } - - } - RegCloseKey(hKey); - } - - if (Value[0] == 0) - { - strcpy(Value,fn); - } - else - { - strcat(Value,"\\"); - strcat(Value,fn); - } - - StartupInfo.cb=sizeof(StartupInfo); - StartupInfo.lpReserved=NULL; - StartupInfo.lpDesktop=NULL; - StartupInfo.lpTitle=NULL; - StartupInfo.dwFlags=0; - StartupInfo.cbReserved2=0; - StartupInfo.lpReserved2=NULL; - - if (!CreateProcess(Value,NULL,NULL,NULL,FALSE, - CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, - NULL,NULL,&StartupInfo,&ProcessInformation)) - { - ret=GetLastError(); - - _itoa(ret,buff,10); - - strcpy(Errbuff, "BPQ32 Load "); - strcat(Errbuff,Value); - strcat(Errbuff," failed "); - strcat(Errbuff,buff); - OutputDebugString(Errbuff); - AttachingProcess = 0; - return FALSE; - } - - return TRUE; -} - - -DllExport BPQVECSTRUC * APIENTRY GetIPVectorAddr() -{ - return &IPHOSTVECTOR; -} - -DllExport UINT APIENTRY GETSENDNETFRAMEADDR() -{ - return (UINT)&SENDNETFRAME; -} - -DllExport VOID APIENTRY RelBuff(VOID * Msg) -{ - UINT * pointer, * BUFF = Msg; - - if (Semaphore.Flag == 0) - Debugprintf("ReleaseBuffer called without semaphore"); - - pointer = FREE_Q; - - *BUFF =(UINT)pointer; - - FREE_Q = BUFF; - - QCOUNT++; - - return; -} - -extern int MINBUFFCOUNT; - -DllExport VOID * APIENTRY GetBuff() -{ - UINT * Temp = Q_REM(&FREE_Q); - - if (Semaphore.Flag == 0) - Debugprintf("GetBuff called without semaphore"); - - if (Temp) - { - QCOUNT--; - - if (QCOUNT < MINBUFFCOUNT) - MINBUFFCOUNT = QCOUNT; - } - - return Temp; -} - - -VOID __cdecl Debugprintf(const char * format, ...) -{ - char Mess[10000]; - va_list(arglist); - - va_start(arglist, format); - vsprintf(Mess, format, arglist); - strcat(Mess, "\r\n"); - OutputDebugString(Mess); - - return; -} - -unsigned short int compute_crc(unsigned char *buf, int txlen); - -extern SOCKADDR_IN reportdest; - -extern SOCKET ReportSocket; - -extern SOCKADDR_IN Chatreportdest; - -DllExport VOID APIENTRY SendChatReport(SOCKET ChatReportSocket, char * buff, int txlen) -{ - unsigned short int crc = compute_crc(buff, txlen); - - crc ^= 0xffff; - - buff[txlen++] = (crc&0xff); - buff[txlen++] = (crc>>8); - - sendto(ChatReportSocket, buff, txlen, 0, (LPSOCKADDR)&Chatreportdest, sizeof(Chatreportdest)); -} - -VOID CreateRegBackup() -{ - char Backup1[MAX_PATH]; - char Backup2[MAX_PATH]; - char RegFileName[MAX_PATH]; - char Msg[80]; - HANDLE handle; - int len, written; - char RegLine[300]; - -// SHELLEXECUTEINFO sei; -// STARTUPINFO SInfo; -// PROCESS_INFORMATION PInfo; - - sprintf(RegFileName, "%s\\BPQ32.reg", BPQDirectory); - - // Keep 4 Generations - - strcpy(Backup2, RegFileName); - strcat(Backup2, ".bak.3"); - - strcpy(Backup1, RegFileName); - strcat(Backup1, ".bak.2"); - - DeleteFile(Backup2); // Remove old .bak.3 - MoveFile(Backup1, Backup2); // Move .bak.2 to .bak.3 - - strcpy(Backup2, RegFileName); - strcat(Backup2, ".bak.1"); - - MoveFile(Backup2, Backup1); // Move .bak.1 to .bak.2 - - strcpy(Backup1, RegFileName); - strcat(Backup1, ".bak"); - - MoveFile(Backup1, Backup2); //Move .bak to .bak.1 - - strcpy(Backup2, RegFileName); - strcat(Backup2, ".bak"); - - CopyFile(RegFileName, Backup2, FALSE); // Copy to .bak - - handle = CreateFile(RegFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if (handle == INVALID_HANDLE_VALUE) - { - sprintf(Msg, "Failed to open Registry Save File\n"); - WritetoConsole(Msg); - return; - } - - len = sprintf(RegLine, "Windows Registry Editor Version 5.00\r\n\r\n"); - WriteFile(handle, RegLine, len, &written, NULL); - - if (SaveReg("Software\\G8BPQ\\BPQ32", handle)) - WritetoConsole("Registry Save complete\n"); - else - WritetoConsole("Registry Save failed\n"); - - CloseHandle(handle); - return ; -/* - - if (REGTREE == HKEY_LOCAL_MACHINE) // < Vista - { - sprintf(cmd, - "regedit /E \"%s\\BPQ32.reg\" %s\\Software\\G8BPQ\\BPQ32", BPQDirectory, REGTREETEXT); - - ZeroMemory(&SInfo, sizeof(SInfo)); - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0 ,NULL, NULL, &SInfo, &PInfo) == 0) - { - sprintf(Msg, "Error: CreateProcess for regedit failed 0%d\n", GetLastError() ); - WritetoConsole(Msg); - return; - } - } - else - { - - sprintf(cmd, - "/E \"%s\\BPQ32.reg\" %s\\Software\\G8BPQ\\BPQ32", BPQDirectory, REGTREETEXT); - - ZeroMemory(&sei, sizeof(sei)); - - sei.cbSize = sizeof(SHELLEXECUTEINFOW); - sei.hwnd = hWnd; - sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI; - sei.lpVerb = "runas"; - sei.lpFile = "regedit.exe"; - sei.lpParameters = cmd; - sei.nShow = SW_SHOWNORMAL; - - if (!ShellExecuteEx(&sei)) - { - sprintf(Msg, "Error: ShellExecuteEx for regedit failed %d\n", GetLastError() ); - WritetoConsole(Msg); - return; - } - } - - sprintf(Msg, "Registry Save Initiated\n", fn); - WritetoConsole(Msg); - - return ; -*/ -} - -BOOL CALLBACK EnumForCloseProc(HWND hwnd, LPARAM lParam) -{ - struct TNCINFO * TNC = (struct TNCINFO *)lParam; - UINT ProcessId; - - GetWindowThreadProcessId(hwnd, &ProcessId); - - for (i=0; i< AttachedProcesses; i++) - { - if (AttachedPIDList[i] == ProcessId) - { - Debugprintf("BPQ32 Close All Closing PID %d", ProcessId); - PostMessage(hwnd, WM_CLOSE, 1, 1); - // AttachedPIDList[i] = 0; // So we don't do it again - break; - } - } - - return (TRUE); -} -DllExport BOOL APIENTRY RestoreFrameWindow() -{ - return ShowWindow(FrameWnd, SW_RESTORE); -} - -DllExport VOID APIENTRY CreateNewTrayIcon() -{ - Shell_NotifyIcon(NIM_DELETE,&niData); - trayMenu = NULL; -} - -DllExport VOID APIENTRY CloseAllPrograms() -{ -// HANDLE hProc; - - // Close all attached BPQ32 programs - - Closing = TRUE; - - ShowWindow(FrameWnd, SW_RESTORE); - - GetWindowRect(FrameWnd, &FRect); - - SaveBPQ32Windows(); - CloseHostSessions(); - - if (AttachedProcesses == 1) - CloseBPQ32(); - - Debugprintf("BPQ32 Close All Processes %d PIDS %d %d %d %d", AttachedProcesses, AttachedPIDList[0], - AttachedPIDList[1], AttachedPIDList[2], AttachedPIDList[3]); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - EnumWindows(EnumForCloseProc, (LPARAM)NULL); -} - -#define MAX_KEY_LENGTH 255 -#define MAX_VALUE_NAME 16383 -#define MAX_VALUE_DATA 65536 - -BOOL CopyReg(HKEY hKeyIn, HKEY hKeyOut) -{ - TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name - DWORD cbName; // size of name string - TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name - DWORD cchClassName = MAX_PATH; // size of class string - DWORD cSubKeys=0; // number of subkeys - DWORD cbMaxSubKey; // longest subkey size - DWORD cchMaxClass; // longest class string - DWORD cValues; // number of values for key - DWORD cchMaxValue; // longest value name - DWORD cbMaxValueData; // longest value data - DWORD cbSecurityDescriptor; // size of security descriptor - FILETIME ftLastWriteTime; // last write time - - DWORD i, retCode; - - TCHAR achValue[MAX_VALUE_NAME]; - DWORD cchValue = MAX_VALUE_NAME; - - // Get the class name and the value count. - retCode = RegQueryInfoKey( - hKeyIn, // key handle - achClass, // buffer for class name - &cchClassName, // size of class string - NULL, // reserved - &cSubKeys, // number of subkeys - &cbMaxSubKey, // longest subkey size - &cchMaxClass, // longest class string - &cValues, // number of values for this key - &cchMaxValue, // longest value name - &cbMaxValueData, // longest value data - &cbSecurityDescriptor, // security descriptor - &ftLastWriteTime); // last write time - - // Enumerate the subkeys, until RegEnumKeyEx fails. - - if (cSubKeys) - { - Debugprintf( "\nNumber of subkeys: %d\n", cSubKeys); - - for (i=0; i 76) - { - len = sprintf(RegLine, "%s\\\r\n", RegLine); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - - len = sprintf(RegLine, "%s%02x,", RegLine, Value[k]); - } - RegLine[--len] = 0x0d; - RegLine[++len] = 0x0a; - len++; - - break; - - case REG_DWORD: //( 4 ) // 32-bit number -// case REG_DWORD_LITTLE_ENDIAN: //( 4 ) // 32-bit number (same as REG_DWORD) - - memcpy(&Intval, Value, 4); - len = sprintf(RegLine, "\"%s\"=dword:%08x\r\n", achValue, Intval); - break; - - case REG_DWORD_BIG_ENDIAN: //( 5 ) // 32-bit number - break; - case REG_LINK: //( 6 ) // Symbolic Link (unicode) - break; - case REG_MULTI_SZ: //( 7 ) // Multiple Unicode strings - - len = sprintf(RegLine, "\"%s\"=hex(7):%02x,00,", achValue, Value[0]); - for (k = 1; k < ValLen; k++) - { - if (len > 76) - { - len = sprintf(RegLine, "%s\\\r\n", RegLine); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - len = sprintf(RegLine, "%s%02x,", RegLine, Value[k]); - if (len > 76) - { - len = sprintf(RegLine, "%s\\\r\n", RegLine); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - } - len = sprintf(RegLine, "%s00,", RegLine); - } - - RegLine[--len] = 0x0d; - RegLine[++len] = 0x0a; - len++; - break; - - case REG_RESOURCE_LIST: //( 8 ) // Resource list in the resource map - break; - case REG_FULL_RESOURCE_DESCRIPTOR: //( 9 ) // Resource list in the hardware description - break; - case REG_RESOURCE_REQUIREMENTS_LIST://( 10 ) - break; - case REG_QWORD: //( 11 ) // 64-bit number -// case REG_QWORD_LITTLE_ENDIAN: //( 11 ) // 64-bit number (same as REG_QWORD) - break; - - } - - WriteFile(hFile, RegLine, len, &written, NULL); - } - } - } - - WriteFile(hFile, "\r\n", 2, &written, NULL); - - // Enumerate the subkeys, until RegEnumKeyEx fails. - - if (cSubKeys) - { - for (i=0; i> 1; - } - - Flags=GetApplFlags(i); - - if (OneBits > 1) - sprintf(&NewScreen[(i+1)*54],"%2d%s%3d %3d %3d %03x %3x %10s%-20s", - i, flag, RXCount(i), TXCount(i), MONCount(i), Mask, Flags, callsign, - BPQHOSTVECTOR[i-1].PgmName); - else - sprintf(&NewScreen[(i+1)*54],"%2d%s%3d %3d %3d %3d %3x %10s%-20s", - i, flag, RXCount(i), TXCount(i), MONCount(i), AppNumber, Flags, callsign, - BPQHOSTVECTOR[i-1].PgmName); - - } - } - - #include "StdExcept.c" - - if (Semaphore.Flag && Semaphore.SemProcessID == GetCurrentProcessId()) - FreeSemaphore(&Semaphore); - - } - - if (memcmp(Screen, NewScreen, 33 * 108) == 0) // No Change - return 0; - - memcpy(Screen, NewScreen, 33 * 108); - InvalidateRect(StatusWnd,NULL,FALSE); - - return(0); -} - -LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - PAINTSTRUCT ps; - HDC hdc; - HFONT hOldFont ; - HGLOBAL hMem; - MINMAXINFO * mmi; - int i; - - switch (message) - { - case WM_TIMER: - - if (Semaphore.Flag == 0) - DoStatus(); - break; - - case WM_MDIACTIVATE: - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)hConsMenu, "Actions"); - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - } - else - { - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - DrawMenuBar(FrameWnd); - - return TRUE; //DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_GETMINMAXINFO: - - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = 850; - mmi->ptMaxSize.y = 500; - mmi->ptMaxTrackSize.x = 850; - mmi->ptMaxTrackSize.y = 500; - - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - //Parse the menu selections: - - switch (wmId) - { - -/* - case BPQSTREAMS: - - CheckMenuItem(hMenu,BPQSTREAMS,MF_CHECKED); - CheckMenuItem(hMenu,BPQIPSTATUS,MF_UNCHECKED); - - StreamDisplay = TRUE; - - break; - - case BPQIPSTATUS: - - CheckMenuItem(hMenu,BPQSTREAMS,MF_UNCHECKED); - CheckMenuItem(hMenu,BPQIPSTATUS,MF_CHECKED); - - StreamDisplay = FALSE; - memset(Screen, ' ', 4000); - - - break; - -*/ - - case BPQCOPY: - - // - // Copy buffer to clipboard - // - hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 33*110); - - if (hMem != 0) - { - if (OpenClipboard(hWnd)) - { -// CopyScreentoBuffer(GlobalLock(hMem)); - GlobalUnlock(hMem); - EmptyClipboard(); - SetClipboardData(CF_TEXT,hMem); - CloseClipboard(); - } - else - { - GlobalFree(hMem); - } - - } - - break; - - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_MAXIMIZE: - - break; - - case SC_MINIMIZE: - - StatusMinimized = TRUE; - break; - - case SC_RESTORE: - - StatusMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - - hOldFont = SelectObject( hdc, hFont) ; - - for (i=0; i<33; i++) - { - TextOut(hdc,0,i*14,&Screen[i*108],108); - } - - SelectObject( hdc, hOldFont ) ; - EndPaint (hWnd, &ps); - - break; - - case WM_DESTROY: - -// PostQuitMessage(0); - - break; - - - default: - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - } - return (0); -} - -VOID SaveMDIWindowPos(HWND hWnd, char * RegKey, char * Value, BOOL Minimized) -{ - HKEY hKey=0; - char Size[80]; - char Key[80]; - int retCode, disp; - RECT Rect; - - if (IsWindow(hWnd) == FALSE) - return; - - ShowWindow(hWnd, SW_RESTORE); - - if (GetWindowRect(hWnd, &Rect) == FALSE) - return; - - // Make relative to Frame - - Rect.top -= FRect.top ; - Rect.left -= FRect.left; - Rect.bottom -= FRect.top; - Rect.right -= FRect.left; - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\%s", RegKey); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, - KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - sprintf(Size,"%d,%d,%d,%d,%d", Rect.left, Rect.right, Rect.top ,Rect.bottom, Minimized); - retCode = RegSetValueEx(hKey, Value, 0, REG_SZ,(BYTE *)&Size, strlen(Size)); - RegCloseKey(hKey); - } -} - -extern int GPSPort; -extern char LAT[]; // in standard APRS Format -extern char LON[]; // in standard APRS Format - -VOID SaveBPQ32Windows() -{ - HKEY hKey=0; - char Size[80]; - int retCode, disp; - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - int i; - - retCode = RegCreateKeyEx(REGTREE, "SOFTWARE\\G8BPQ\\BPQ32", 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - sprintf(Size,"%d,%d,%d,%d", FRect.left, FRect.right, FRect.top, FRect.bottom); - retCode = RegSetValueEx(hKey, "FrameWindowSize", 0, REG_SZ, (BYTE *)&Size, strlen(Size)); - - // Save GPS Position - - if (GPSPort) - { - sprintf(Size, "%s, %s", LAT, LON); - retCode = RegSetValueEx(hKey, "GPS", 0, REG_SZ,(BYTE *)&Size, strlen(Size)); - } - - RegCloseKey(hKey); - } - - SaveMDIWindowPos(StatusWnd, "", "StatusWindowSize", StatusMinimized); - SaveMDIWindowPos(hConsWnd, "", "WindowSize", ConsoleMinimized); - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - } - } - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - SaveWindowPos(40); // Rigcontrol - - - if (hIPResWnd) - SaveMDIWindowPos(hIPResWnd, "", "IPResSize", IPMinimized); - - SaveHostSessions(); -} - -DllExport BOOL APIENTRY CheckIfOwner() -{ - // - // Returns TRUE if current process is root process - // that loaded the DLL - // - - if (TimerInst == GetCurrentProcessId()) - - return (TRUE); - else - return (FALSE); -} - -VOID GetParam(char * input, char * key, char * value) -{ - char * ptr = strstr(input, key); - char Param[2048]; - char * ptr1, * ptr2; - char c; - - if (ptr) - { - ptr2 = strchr(ptr, '&'); - if (ptr2) *ptr2 = 0; - strcpy(Param, ptr + strlen(key)); - if (ptr2) *ptr2 = '&'; // Restore string - - // Undo any % transparency - - ptr1 = Param; - ptr2 = Param; - - c = *(ptr1++); - - while (c) - { - if (c == '%') - { - int n; - int m = *(ptr1++) - '0'; - if (m > 9) m = m - 7; - n = *(ptr1++) - '0'; - if (n > 9) n = n - 7; - - *(ptr2++) = m * 16 + n; - } - else if (c == '+') - *(ptr2++) = ' '; - else - *(ptr2++) = c; - - c = *(ptr1++); - } - - *(ptr2++) = 0; - - strcpy(value, Param); - } -} - -int GetListeningPortsPID(int Port) -{ - MIB_TCPTABLE_OWNER_PID * TcpTable = NULL; - PMIB_TCPROW_OWNER_PID Row; - int dwSize = 0; - DWORD n; - - // Get PID of process for this TCP Port - - // Get Length of table - - GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0); - - TcpTable = malloc(dwSize); - - if (TcpTable == NULL) - return 0; - - GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0); - - for (n = 0; n < TcpTable->dwNumEntries; n++) - { - Row = &TcpTable->table[n]; - - if (Row->dwLocalPort == Port && Row->dwState == MIB_TCP_STATE_LISTEN) - { - return Row->dwOwningPid; - break; - } - } - return 0; // Not found -} - -DllExport char * APIENTRY GetLOC() -{ - return LOC; -} - -// UZ7HO Dll PTT interface - -// 1 ext_PTT_info -// 2 ext_PTT_settings -// 3 ext_PTT_OFF -// 4 ext_PTT_ON -// 5 ext_PTT_close -// 6 ext_PTT_open - -extern struct RIGINFO * DLLRIG; // Rig record for dll PTT interface (currently only for UZ7HO); - -VOID Rig_PTT(struct TNCINFO * TNC, BOOL PTTState); -VOID Rig_PTTEx(struct RIGINFO * RIG, BOOL PTTState, struct TNCINFO * TNC); - -int WINAPI ext_PTT_info() -{ - return 0; -} - -int WINAPI ext_PTT_settings() -{ - return 0; -} - -int WINAPI ext_PTT_OFF(int Port) -{ - if (DLLRIG) - Rig_PTTEx(DLLRIG, 0, 0); - - return 0; -} - -int WINAPI ext_PTT_ON(int Port) -{ - if (DLLRIG) - Rig_PTTEx(DLLRIG, 1, 0); - - return 0; -} -int WINAPI ext_PTT_close() -{ - if (DLLRIG) - Rig_PTTEx(DLLRIG, 0, 0); - - return 0; -} - -DllExport INT WINAPI ext_PTT_open() -{ - return 1; -} - -char * stristr (char *ch1, char *ch2) -{ - char *chN1, *chN2; - char *chNdx; - char *chRet = NULL; - - chN1 = _strdup(ch1); - chN2 = _strdup(ch2); - - if (chN1 && chN2) - { - chNdx = chN1; - while (*chNdx) - { - *chNdx = (char) tolower(*chNdx); - chNdx ++; - } - chNdx = chN2; - - while (*chNdx) - { - *chNdx = (char) tolower(*chNdx); - chNdx ++; - } - - chNdx = strstr(chN1, chN2); - - if (chNdx) - chRet = ch1 + (chNdx - chN1); - } - - free (chN1); - free (chN2); - return chRet; -} - - - diff --git a/Bpq32-HPLaptop.c b/Bpq32-HPLaptop.c deleted file mode 100644 index b434efb..0000000 --- a/Bpq32-HPLaptop.c +++ /dev/null @@ -1,6541 +0,0 @@ -/* -Copyright 2001-2015 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ -// -// 409l Oct 2001 Fix l3timeout for KISS -// -// 409m Oct 2001 Fix Crossband Digi -// -// 409n May 2002 Change error handling on load ext DLL - -// 409p March 2005 Allow Multidigit COM Ports (kiss.c) - -// 409r August 2005 Treat NULL string in Registry as use current directory -// Allow shutdown to close BPQ Applications - -// 409s October 2005 Add DLL:Export entries to API for BPQTNC2 - -// 409t January 2006 -// -// Add API for Perl "GetPerlMsg" -// Add API for BPQ1632 "GETBPQAPI" - returns address of Assembler API routine -// Add Registry Entry "BPQ Directory". If present, overrides "Config File Location" -// Add New API "GetBPQDirectory" - Returns location of config file -// Add New API "ChangeSessionCallsign" - equivalent to "*** linked to" command -// Rename BPQNODES to BPQNODES.dat -// New API "GetAttachedProcesses" - returns number of processes connected. -// Warn if user trys to close Console Window. -// Add Debug entries to record Process Attach/Detach -// Fix recovery following closure of first process - -// 409t Beta 2 February 2006 -// -// Add API Entry "GetPortNumber" -// -// 409u February 2006 -// -// Fix crash if allocate/deallocate called with stream=0 -// Add API to ch -// Display config file path -// Fix saving of Locked Node flag -// Added SAVENODES SYSOP command -// -// 409u 2 March 2006 -// -// Fix SetupBPQDirectory -// Add CopyBPQDirectory (for Basic Programs) -// -// 409u 3 March 2006 -// -// Release streams on DLL unload - -// 409v October 2006 -// -// Support Minimize to Tray for all BPQ progams -// Implement L4 application callsigns - -// 410 November 2006 -// -// Modified to compile with C++ 2005 Express Edition -// Make MCOM MTX MMASK local variables -// -// 410a January 2007 -// -// Add program name to Attach-Detach messages -// Attempt to detect processes which have died -// Fix bug in NETROM and IFrame decode which would cause crash if frame was corrupt -// Add BCALL - origin call for Beacons -// Fix KISS ACKMODE ACK processing -// - -// 410b November 2007 -// -// Allow CTEXT of up to 510, and enforce PACLEN, fragmenting if necessary - -// 410c December 2007 - -// Fix problem with NT introduced in V410a -// Display location of DLL on Console - -// 410d January 2008 - -// Fix crash in DLL Init caused by long path to program -// Invoke Appl2 alias on C command (if enabled) -// Allow C command to be disabled -// Remove debug trap in GETRAWFRAME -// Validate Alias of directly connected node, mainly for KPC3 DISABL Problem -// Move Port statup code out of DLLInit (mainly for perl) -// Changes to allow Load/Unload of bpq32.dll by appl -// CloseBPQ32 API added -// Ext Driver Close routes called -// Changes to release Mutex - -// 410e May 2008 - -// Fix missing SSID on last call of UNPROTO string (CONVTOAX25 in main.asm) -// Fix VCOM Driver (RX Len was 1 byte too long) -// Fix possible crash on L4CODE if L4DACK received out of sequence -// Add basic IP decoding - -// 410f October 2008 - -// Add IP Gateway -// Add Multiport DIGI capability -// Add GetPortDescription API -// Fix potential hangs if RNR lost -// Fix problem if External driver failes to load -// Put pushad/popad round _INITIALISEPORTS (main.asm) -// Add APIs GetApplCallVB and GetPortDescription (mainly for RMS) -// Ensure Route Qual is updated if Port Qual changed -// Add Reload Option, plus menu items for DUMP and SAVENODES - -// 410g December 2008 - -// Restore API Exports BPQHOSTAPIPTR and MONDECODEPTR (accidentally deleted) -// Fix changed init of BPQDirectory (accidentally changed) -// Fix Checks for lost processes (accidentally deleted) -// Support HDLC Cards on W2K and above -// Delete Tray List entries for crashed processes -// Add Option to NODES command to sort by Callsign -// Add options to save or clear BPQNODES before Reconfig. -// Fix Reconfig in Win98 -// Monitor buffering tweaks -// Fix Init for large (>64k) tables -// Fix Nodes count in Stats - -// 410h January 2009 - -// Add Start Minimized Option -// Changes to KISS for WIn98 Virtual COM -// Open \\.\com instead of //./COM -// Extra Dignostics - -// 410i Febuary 2009 - -// Revert KISS Changes -// Save Window positions - -// 410j June 2009 - -// Fix tidying of window List when program crashed -// Add Max Nodes to Stats -// Don't update APPLnALIAS with received NODES info -// Fix MH display in other timezones -// Fix Possible crash when processing NETROM type Zero frames (eg NRR) -// Basic INP3 Stuff -// Add extra diagnostics to Lost Process detection -// Process Netrom Record Route frames. - -// 410k June 2009 - -// Fix calculation of %retries in extended ROUTES display -// Fix corruption of ROUTES table - -// 410l October 2009 - -// Add GetVersionString API call. -// Add GetPortTableEntry API call -// Keep links to neighbouring nodes open - -// Build 2 - -// Fix PE in NOROUTETODEST (missing POP EBX) - -// 410m November 2009 - -// Changes for PACTOR and WINMOR to support the ATTACH command -// Enable INP3 if configured on a route. -// Fix count of nodes in Stats Display -// Overwrite the worst quality unused route if a call is received from a node not in your -// table when the table is full - -// Build 5 - -// Rig Control Interface -// Limit KAM VHF attach and RADIO commands to authorised programs (MailChat and BPQTerminal) - -// Build 6 - -// Fix reading INP3 Flag from BPQNODES - -// Build 7 - -// Add MAXHOPS and MAXRTT config options - -// Build 8 - -// Fix INP3 deletion of Application Nodes. -// Fix GETCALLSIGN for Pactor Sessions -// Add N Call* to display all SSID's of a call -// Fix flow control on Pactor sessions. - -// Build 9 - -// HDLC Support for XP -// Add AUTH routines - -// Build 10 - -// Fix handling commands split over more that one packet. - -// Build 11 - -// Attach cmd changes for winmor disconnecting state -// Option Interlock Winmor/Pactor ports - -// Build 12 - -// Add APPLS export for winmor -// Handle commands ending CR LF - -// Build 13 - -// Incorporate Rig Control in Kernel - -// Build 14 - -// Fix config reload for Rig COntrol - -// 410n March 2010 - -// Implement C P via PACTOR/WINMOR (for Airmail) - -// Build 2 - -// Don't flip SSID bits on Downlink Connect if uplink is Pactor/WINMOR -// Fix resetting IDLE Timer on Pactor/WINMOR sessions -// Send L4 KEEPLI messages based on IDLETIME - -// 410o July 2010 - -// Read bpqcfg.txt instead of .bin -// Support 32 bit MMASK (Allowing 32 Ports) -// Support 32 bit _APPLMASK (Allowing 32 Applications) -// Allow more commands -// Allow longer command aliases -// Fix logic error in RIGControl Port Initialisation (wasn't always raising RTS and DTR -// Clear RIGControl RTS and DTR on close - -// 410o Build 2 August 2010 - -// Fix couple of errors in config (needed APPLICATIONS and BBSCALL/ALIAS/QUAL) -// Fix Kenwood Rig Control when more than one message received at once. -// Save minimzed state of Rigcontrol Window - -// 410o Build 3 August 2010 - -// Fix reporting of set errors in scan to a random session - -// 410o Build 4 August 2010 - -// Change All xxx Ports are in use to no xxxx Ports are available if there are no sessions with _APPLMASK -// Fix validation of TRANSDELAY - -// 410o Build 5 August 2010 - -// Add Repeater Shift and Set Data Mode options to Rigcontrol (for ICOM only) -// Add WINMOR and SCS Pactor mode control option to RigControl -// Extend INFOMSG to 2000 bytes -// Improve Scan freq change lock (check both SCS and WINMOR Ports) - -// 410o Build 6 September 2010 - -// Incorporate IPGateway in main code. -// Fix GetSessionInfo for Pactor/Winmor Ports -// Add Antenna Selection to RigControl -// Allow Bandwidth options on RADIO command line (as well as in Scan definitions) - -// 410o Build 7 September 2010 - -// Move rigconrtol display to driver windows -// Move rigcontrol config to driver config. -// Allow driver and IPGateway config info in bpq32.cfg -// Move IPGateway, AXIP, VKISS, AGW and WINMOR drivers into bpq32.dll -// Add option to reread IP Gateway config. -// Fix Reinit after process with timer closes (error in TellSessions). - -// 410p Build 2 October 2010 - -// Move KAM and SCS drivers to bpq32.dll - -// 410p Build 3 October 2010 - -// Support more than one axip port. - -// 410p Build 4 October 2010 - -// Dynamically load psapi.dll (for 98/ME) - -// 410p Build 5 October 2010 - -// Incorporate TelnetServer -// Fix AXIP ReRead Config -// Report AXIP accept() fails to syslog, not a popup. - -// 410p Build 6 October 2010 - -// Includes HAL support -// Changes to Pactor Drivers disconnect code -// AXIP now sends with source port = dest port, unless overridden by SOURCEPORT param -// Config now checks for duplicate port definitions -// Add Node Map reporting -// Fix WINMOR deferred disconnect. -// Report Pactor PORTCALL to WL2K instead of RMS Applcall - -// 410p Build 7 October 2010 - -// Add In/Out flag to Map reporting, and report centre, not dial -// Write Telnet log to BPQ Directory -// Add Port to AXIP resolver display -// Send Reports to update.g8bpq.net:81 -// Add support for FT100 to Rigcontrol -// Add timeout to Rigcontrol PTT -// Add Save Registry Command - -// 410p Build 8 November 2010 - -// Add NOKEEPALIVES Port Param -// Renumbered for release - -// 410p Build 9 November 2010 - -// Get Bandwith for map report from WL2K Report Command -// Fix freq display for FT100 (was KHz, not MHz) -// Don't try to change SCS mode whilst initialising -// Allow reporting of Lat/Lon as well as Locator -// Fix Telnet Log Name -// Fix starting with Minimized windows when Minimizetotray isn't set -// Extra Program Error trapping in SessionControl -// Fix reporting same freq with different bandwidths at different times. -// Code changes to support SCS Robust Packet Mode. -// Add FT2000 to Rigcontrol -// Only Send CTEXT to connects to Node (not to connects to an Application Call) - -// Released as Build 10 - -// 410p Build 11 January 2011 - -// Fix MH Update for SCS Outgoing Calls -// Add Direct CMS Access to TelnetServer -// Restructure DISCONNECT processing to run in Timer owning process - -// 410p Build 12 January 2011 - -// Add option for Hardware PTT to use a different com port from the scan port -// Add CAT PTT for Yaesu 897 (and maybe others) -// Fix RMS Packet ports busy after restart -// Fix CMS Telnet with MAXSESSIONS > 10 - -// 410p Build 13 January 2011 - -// Fix loss of buffers in TelnetServer -// Add CMS logging. -// Add non - Promiscuous mode option for BPQETHER - -// 410p Build 14 January 2011 - -// Add support for BPQTermTCP -// Allow more that one FBBPORT -// Allow Telnet FBB mode sessions to send CRLF as well as CR on user and pass msgs -// Add session length to CMS Telnet logging. -// Return Secure Session Flag from GetConnectionInfo -// Show Uptime as dd/hh/mm - -// 4.10.16.17 March 2011 - -// Add "Close all programs" command -// Add BPQ Program Directory registry key -// Use HKEY_CURRENT_USER on Vista and above (and move registry if necessary) -// Time out IP Gateway ARP entries, and only reload ax.25 ARP entries -// Add support for SCS Tracker HF Modes -// Fix WL2K Reporting -// Report Version to WL2K -// Add Driver to support Tracker with multiple sessions (but no scanning, wl2k report, etc) - - -// Above released as 5.0.0.1 - -// 5.2.0.1 - -// Add caching of CMS Server IP addresses -// Initialise TNC State on Pactor Dialogs -// Add Shortened (6 digit) AUTH mode. -// Update MH with all frames (not just I/UI) -// Add IPV6 Support for TelnetServer and AXIP -// Fix TNC OK Test for Tracker -// Fix crash in CMS mode if terminal disconnects while tcp commect in progress -// Add WL2K reporting for Robust Packet -// Add option to suppress WL2K reporting for specific frequencies -// Fix Timeband processing for Rig Control -// New Driver for SCS Tracker allowing multiple connects, so Tracker can be used for user access -// New Driver for V4 TNC - -// 5.2.1.3 October 2011 - -// Combine busy detector on Interlocked Ports (SCS PTC, WINMOR or KAM) -// Improved program error logging -// WL2K reporting changed to new format agreed with Lee Inman - -// 5.2.3.1 January 2012 - -// Connects from the console to an APPLCALL or APPLALIAS now invoke any Command Alias that has been defined. -// Fix reporting of Tracker freqs to WL2K. -// Fix Tracker monitoring setup (sending M UISC) -// Fix possible call/application routing error on RP -// Changes for P4Dragon -// Include APRS Digi/IGate -// Tracker monitoring now includes DIGIS -// Support sending UI frames using SCSTRACKER, SCTRKMULTI and UZ7HO drivers -// Include driver for UZ7HO soundcard modem. -// Accept DRIVER as well as DLLNAME, and COMPORT as well as IOADDR in bpq32.cfg. COMPORT is decimal -// No longer supports separate config files, or BPQTELNETSERVER.exe -// Improved flow control for Telnet CMS Sessions -// Fix handling Config file without a newline after last line -// Add non - Promiscuous mode option for BPQETHER -// Change Console Window to a Dialog Box. -// Fix possible corruption and loss of buffers in Tracker drivers -// Add Beacon After Session option to Tracker and UZ7HO Drivers -// Rewrite RigControl and add "Reread Config Command" -// Support User Mode VCOM Driver for VKISS ports - -// 5.2.4.1 January 2012 - -// Remove CR from Telnet User and Password Prompts -// Add Rigcontrol to UZ7HO driver -// Fix corruption of Free Buffer Count by Rigcontol -// Fix WINMOR and V4 PTT -// Add MultiPSK Driver -// Add SendBeacon export for BPQAPRS -// Add SendChatReport function -// Fix check on length of Port Config ID String with trailing spaces -// Fix interlock when Port Number <> Port Slot -// Add NETROMCALL for L3 Activity -// Add support for APRS Application -// Fix Telnet with FBBPORT and no TCPPORT -// Add Reread APRS Config -// Fix switching to Pactor after scanning in normal packet mode (PTC) - -// 5.2.5.1 February 2012 - -// Stop reading Password file. -// Add extra MPSK commands -// Fix MPSK Transparency -// Make LOCATOR command compulsory -// Add MobileBeaconInterval APRS param -// Send Course and Speed when APRS is using GPS -// Fix Robust Packet reporting in PTC driver -// Fix corruption of some MIC-E APRS packets - -// 5.2.6.1 February 2012 - -// Convert to MDI presentation of BPQ32.dll windows -// Send APRS Status packets -// Send QUIT not EXIT in PTC Init -// Implement new WL2K reporting format and include traffic reporting info in CMS signon -// New WL2KREPORT format -// Prevent loops when APPL alias refers to itself -// Add RigControl for Flex radios and ICOM IC-M710 Marine radio - -// 5.2.7.1 - -// Fix opening more thn one console window on Win98 -// Change method of configuring multiple timelots on WL2K reporting -// Add option to update WK2K Sysop Database -// Add Web server -// Add UIONLY port option - -// 5.2.7.2 - -// Fix handling TelnetServer packets over 500 bytes in normal mode - -// 5.2.7.3 - -// Fix Igate handling packets from UIView - -// 5.2.7.4 - -// Prototype Baycom driver. - -// 5.2.7.5 - -// Set WK2K group ref to MARS (3) if using a MARS service code - -// 5.2.7.7 - -// Check for programs calling CloseBPQ32 when holding semaphore -// Try/Except round Status Timer Processing - -// 5.2.7.8 - -// More Try/Except round Timer Processing - -// 5.2.7.9 - -// Enable RX in Baycom, and remove test loopback in tx - -// 5.2.7.10 - -// Try/Except round ProcessHTTPMessage - -// 5.2.7.11 - -// BAYCOM tweaks - -// 5.2.7.13 - -// Release semaphore after program error in Timer Processing -// Check fro valid dest in REFRESHROUTE - - -// Add TNC-X KISSOPTION (includes the ACKMODE bytes in the checksum( - -// Version 5.2.9.1 Sept 2012 - -// Fix using KISS ports with COMn > 16 -// Add "KISS over UDP" driver for PI as a TNC concentrator - -// Version 6.0.1.1 - -// Convert to C for linux portability -// Try to speed up kiss polling - -// Version 6.0.2.1 - -// Fix operation on Win98 -// Fix callsign error with AGWtoBPQ -// Fix PTT problem with WINMOR -// Fix Reread telnet config -// Add Secure CMS signon -// Fix error in cashing addresses of CMS servers -// Fix Port Number when using Send Raw. -// Fix PE in KISS driver if invalid subchannel received -// Fix Orignal address of beacons -// Speed up Telnet port monitoring. -// Add TNC Emulators -// Add CountFramesQueuedOnStream API -// Limit number of frames that can be queued on a session. -// Add XDIGI feature -// Add Winmor Robust Mode switching for compatibility with new Winmor TNC -// Move most APRS code from BPQAPRS to here -// Stop corruption caused by overlong KISS frames - -// Version 6.0.3.1 - -// Add starting/killing WINMOR TNC on remote host -// Fix Program Error when APRS Item or Object name is same as call of reporting station -// Dont digi a frame that we have already digi'ed -// Add ChangeSessionIdleTime API -// Add WK2KSYSOP Command -// Add IDLETIME Command -// Fix Errors in RELAYAPPL processing -// Fix PE cauaed by invalid Rigcontrol Line - -// Version 6.0.4.1 - -// Add frequency dependent autoconnect appls for SCS Pactor -// Fix DED Monitoring of I and UI with no data -// Include AGWPE Emulator (from AGWtoBPQ) -// accept DEL (Hex 7F) as backspace in Telnet -// Fix re-running resolver on re-read AXIP config -// Speed up processing, mainly for Telnet Sessions -// Fix APRS init on restart of bpq32.exe -// Change to 2 stop bits -// Fix scrolling of WINMOR trace window -// Fix Crash when ueing DED TNC Emulator -// Fix Disconnect when using BPQDED2 Driver with Telnet Sessions -// Allow HOST applications even when CMS option is disabled -// Fix processing of APRS DIGIMAP command with no targets (didn't suppress default settings) - -// Version 6.0.5.1 January 2014 - -// Add UTF8 conversion mode to Telnet (converts non-UTF-8 chars to UTF-8) -// Add "Clear" option to MH command -// Add "Connect to RMS Relay" Option -// Revert to one stop bit on serial ports, explictly set two on FT2000 rig control -// Fix routing of first call in Robust Packet -// Add Options to switch input source on rigs with build in soundcards (sor far only IC7100 and Kenwood 590) -// Add RTS>CAT PTT option for Sound Card rigs -// Add Clear Nodes Option (NODE DEL ALL) -// SCS Pactor can set differeant APPLCALLS when scanning. -// Fix possible Scan hangup after a manual requency change with SCS Pactor -// Accept Scan entry of W0 to disable WINMOR on that frequency -// Fix corruption of NETROMCALL by SIMPLE config command -// Enforce Pactor Levels -// Add Telnet outward connect -// Add Relay/Trimode Emulation -// Fix V4 Driver -// Add PTT Mux -// Add Locked ARP Entries (via bpq32.cfg) -// Fix IDLETIME node command -// Fix STAY param on connect -// Add STAY option to Attach and Application Commands -// Fix crash on copying a large AXIP MH Window -// Fix possible crash when bpq32.exe dies -// Fix DIGIPORT for UI frames - -// Version 6.0.6.1 April 2014 - -// FLDigi Interface -// Fix "All CMS Servers are inaccessible" message so Mail Forwarding ELSE works. -// Validate INP3 messages to try to prevent crash -// Fix possible crash if an overlarge KISS frame is received -// Fix error in AXR command -// Add LF to Telnet Outward Connect signin if NEEDLF added to connect line -// Add CBELL to TNC21 emulator -// Add sent objects and third party messages to APRS Dup List -// Incorporate UIUtil -// Use Memory Mapped file to pass APRS info to BPQAPRS, and process APRS HTTP in BPQ32 -// Improvements to FLDIGI interlocking -// Fix TNC State Display for Tracker -// Cache CMS Addresses on LinBPQ -// Fix count error on DED Driver when handling 256 byte packets -// Add basic SNMP interface for MRTG -// Fix memory loss from getaddrinfo -// Process "BUSY" response from Tracker -// Handle serial port writes that don't accept all the data -// Trap Error 10038 and try to reopen socket -// Fix crash if overlong command line received - -// Version 6.0.7.1 Aptil 2014 -// Fix RigContol with no frequencies for Kenwood and Yaesu -// Add busy check to FLDIGI connects - -// Version 6.0.8.1 August 2014 - -// Use HKEY_CURRENT_USER on all OS versions -// Fix crash when APRS symbol is a space. -// Fixes for FT847 CAT -// Fix display of 3rd byte of FRMR -// Add "DEFAULT ROBUST" and "FORCE ROBUST" commands to SCSPactor Driver -// Fix possible memory corruption in WINMOR driver -// Fix FT2000 Modes -// Use new WL2K reporting system (Web API Based) -// APRS Server now cycles through hosts if DNS returns more than one -// BPQ32 can now start and stop FLDIGI -// Fix loss of AXIP Resolver when running more than one AXIP port - -// Version 6.0.9.1 November 2014 - -// Fix setting NOKEEPALIVE flag on route created from incoming L3 message -// Ignore NODES from locked route with quality 0 -// Fix seting source port in AXIP -// Fix Dual Stack (IPV4/V6) on Linux. -// Fix RELAYSOCK if IPv6 is enabled. -// Add support for FT1000 -// Fix hang when APRS Messaging packet received on RF -// Attempt to normalize Node qualies when stations use widely differing Route qualities -// Add NODES VIA command to display nodes reachable via a specified neighbour -// Fix applying "DisconnectOnClose" setting on HOST API connects (Telnet Server) -// Fix buffering large messages in Telnet Host API -// Fix occasional crash in terminal part line processing -// Add "NoFallback" command to Telnet server to disable "fallback to Relay" -// Improved support for APPLCALL scanning with Pactor -// MAXBUFFS config statement is no longer needed. -// Fix USEAPPLCALLS with Tracker when connect to APPLCALL fails -// Implement LISTEN and CQ commands -// FLDIGI driver can now start FLDIGI on a remote system. -// Add IGNOREUNLOCKEDROUTES parameter -// Fix error if too many Telnet server connections - -// Version 6.0.10.1 Feb 2015 - -// Fix crash if corrupt HTML request received. -// Allow SSID's of 'R' and 'T' on non-ax.25 ports for WL2K Radio Only network. -// Make HTTP server HTTP Version 1.1 complient - use persistent conections and close after 2.5 mins -// Add INP3ONLY flag. -// Fix program error if enter UNPROTO without a destination path -// Show client IP address on HTTP sessions in Telnet Server -// Reduce frequency and number of attempts to connect to routes when Keepalives or INP3 is set -// Add FT990 RigControl support, fix FT1000MP support. -// Support ARMV5 processors -// Changes to support LinBPQ APRS Client -// Add IC7410 to supported Soundcard rigs -// Add CAT PTT to NMEA type (for ICOM Marine Radios_ -// Fix ACKMODE -// Add KISS over TCP -// Support ACKMode on VKISS -// Improved reporting of configuration file format errors -// Experimental driver to support ARQ sessions using UI frames - -// Version 6.0.11.1 September 2015 - -// Fixes for IPGateway configuration and Virtual Circuit Mode -// Separate Portmapper from IPGateway -// Add PING Command -// Add ARDOP Driver -// Add basic APPLCALL support for PTC-PRO/Dragon 7800 Packet (using MYALIAS) -// Add "VeryOldMode" for KAM Version 5.02 -// Add KISS over TCP Slave Mode. -// Support Pactor and Packet on P4Dragon on one port -// Add "Remote Staton Quality" to Web ROUTES display -// Add Virtual Host option for IPGateway NET44 Encap -// Add NAT for local hosts to IPGateway -// Fix setting filter from RADIO command for IC7410 -// Add Memory Channel Scanning for ICOM Radios -// Try to reopen Rig Control port if it fails (could be unplugged USB) -// Fix restoring position of Monitor Window -// Stop Codec on Winmor and ARDOP when an interlocked port is attached (instead of listen false) -// Support APRS beacons in RP mode on Dragon// -// Change Virtual MAC address on IPGateway to include last octet of IP Address -// Fix "NOS Fragmentation" in IP over ax.25 Virtual Circuit Mode -// Fix sending I frames before L2 session is up -// Fix Flow control on Telnet outbound sessions. -// Fix reporting of unterminatred comments in config -// Add option for RigControl to not change mode on FT100/FT990/FT1000 -// Add "Attach and Connect" for Telnet ports - -// Version 6.0.12.1 November 2015 - -// Fix logging of IP addresses for connects to FBBPORT -// Allow lower case user and passwords in Telnet "Attach and Connect" -// Fix possible hang in KISS over TCP Slave mode -// Fix duplicating LinBPQ process if running ARDOP fails -// Allow lower case command aliases and increase alias length to 48 -// Fix saving long IP frames pending ARP resolution -// Fix dropping last entry from a RIP44 message. -// Fix displaying Digis in MH list -// Add port name to Monitor config screen port list -// Fix APRS command display filter and add port filter -// Support port names in BPQTermTCP Monitor config -// Add FINDBUFFS command to dump lost buffers to Debugview/Syslog -// Buffer Web Mgmt Edit Config output -// Add WebMail Support -// Fix not closing APRS Send WX file. -// Add RUN option to APRS Config to start APRS Client -// LinBPQ run FindLostBuffers and exit if QCOUNT < 5 -// Close and reopen ARDOP connection if nothing received for 90 secs -// Add facility to bridge traffic between ports (similar to APRS Bridge but for all frame types) -// Add KISSOPTION TRACKER to set SCS Tracker into KISS Mode - -// 6.0.13.1 - -// Allow /ex to exit UNPROTO mode -// Support ARQBW commands. -// Support IC735 -// Fix sending ARDOP beacons after a busy holdoff -// Enable BPQDED driver to beacon via non-ax.25 ports. -// Fix channel number in UZ7HO monitoring -// Add SATGate mode to APRSIS Code. -// Fix crash caused by overlong user name in telnet logon -// Add option to log L4 connects -// Add AUTOADDQuiet mode to AXIP. -// Add EXCLUDE processing -// Support WinmorControl in UZ7HO driver and fix starting TNC on Linux -// Convert calls in MAP entries to upper case. -// Support Linux COM Port names for APRS GPS -// Fix using NETROM serial protocol on ASYNC Port -// Fix setting MYLEVEL by scanner after manual level change. -// Add DEBUGLOG config param to SCS Pactor Driver to log serial port traffic -// Uue #myl to set SCS Pactor MYLEVEL, and add checklevel command -// Add Multicast RX interface to FLDIGI Driver -// Fix processing application aliases to a connect command. -// Fix Buffer loss if radio connected to PTC rig port but BPQ not configured to use it -// Save backups of bpq32.cfg when editing with Web interface and report old and new length -// Add DD command to SCS Pactor, and use it for forced disconnect. -// Add ARDOP mode select to scan config -// ARDOP changes for ARDOP V 0.5+ -// Flip SSID bits on UZ7HO downlink connects - - -// Version 6.0.14.1 - -// Fix Socket leak in ARDOP and FLDIGI drivers. -// Add option to change CMS Server hostname -// ARDOP Changes for 0.8.0+ -// Discard Terminal Keepalive message (two nulls) in ARDOP command hander -// Allow parameters to be passed to ARDOP TNC when starting it -// Fix Web update of Beacon params -// Retry connects to KISS ports after failure -// Add support for ARDOP Serial Interface Native mode. -// Fix gating APRS-IS Messages to RF -// Fix Beacons when PORTNUM used -// Make sure old monitor flag is cleared for TermTCP sessions -// Add CI-V antenna control for IC746 -// Don't allow ARDOP beacons when connected -// Add support for ARDOP Serial over I2C -// Fix possble crash when using manual RADIO messages -// Save out of sequence L2 frames for possible reuse after retry -// Add KISS command to send KISS control frame to TNC -// Stop removing unused digis from packets sent to APRS-IS - -// Processing of ARDOP PING and PINGACK responses -// Handle changed encoding of WL2K update responses. -// Allow anonymous logon to telnet -// Don't use APPL= for RP Calls in Dragon Single mode. -// Add basic messaging page to APRS Web Server -// Add debug log option to SCSTracker and TrkMulti Driver -// Support REBOOT command on LinBPQ -// Allow LISTEN command on all ports that support ax.25 monitoring - -// Version 6.0.15.1 Feb 2018 - -// partial support for ax.25 V2.2 -// Add MHU and MHL commands and MH filter option -// Fix scan interlock with ARDOP -// Add Input source seiect for IC7300 -// Remove % transparency from web terminal signon message -// Fix L4 Connects In count on stats -// Fix crash caused by corrupt CMSInfo.txt -// Add Input peaks display to ARDOP status window -// Add options to show time in local and distances in KM on APRS Web pages -// Add VARA support -// Fix WINMOR Busy left set when port Suspended -// Add ARDOP-Packet Support -// Add Antenna Switching for TS 480 -// Fix possible crash in Web Terminal -// Support different Code Pages on Console sessions -// Use new Winlink API interface (api.winlink.org) -// Support USB/ACC switching on TS590SG -// Fix scanning when ARDOP or WINMOR is used without an Interlocked Pactor port. -// Set NODECALL to first Application Callsign if NODE=0 and BBSCALL not set. -// Add RIGCONTROL TUNE and POWER commands for some ICOM and Kenwwod rigs -// Fix timing out ARDOP PENDING Lock -// Support mixed case WINLINK Passwords -// Add TUNE and POWER Rigcontol Commands for some radios -// ADD LOCALTIME and DISPKM options to APRS Digi/Igate - -// 6.0.16.1 March 2018 - -// Fix Setting data mode and filter for IC7300 radios -// Add VARA to WL2KREPORT -// Add trace to SCS Tracker status window -// Fix possible hang in IPGATEWAY -// Add BeacontoIS parameter to APRSDIGI. Allows you to stop sending beacons to APRS-IS. -// Fix sending CTEXT on WINMOR sessions - -// 6.0.17.1 November 2018 - -// Change WINMOR Restart after connection to Restart after Failure and add same option to ARDOP and VARA -// Add Abort Connection to WINMOR and VARA Interfaces -// Reinstate accidentally removed CMS Access logging -// Fix MH CLEAR -// Fix corruption of NODE table if NODES received from station with null alias -// Fix loss of buffer if session closed with something in PARTCMDBUFFER -// Fix Spurious GUARD ZONE CORRUPT message in IP Code. -// Remove "reread bpq32.cfg and reconfigure" menu options -// Add support for PTT using CM108 based soundcard interfaces -// Datestamp Telnet log files and delete old Telnet and CMSAcces logs - -// 6.0.18.1 January 2019 - -// Fix validation of NODES broadcasts -// Fix HIDENODES -// Check for failure to reread config on axip reconfigure -// Fix crash if STOPPORT or STARTPORT used on KISS over TCP port -// Send Beacons from BCALL or PORTCALL if configured -// Fix possible corruption of last entry in MH display -// Ensure RTS/DTR is down when opening PTT Port -// Remove RECONFIG command -// Preparations for 64 bit version - -// 6.0.19 Sept 2019 -// Fix UZ7HO interlock -// Add commands to set Centre Frequency and Modem with UZ7HO Soundmodem (on Windows only) -// Add option to save and restore MH lists and SAVEMH command -// Add Frequency (if known) to UZ7HO MH lists -// Add Gateway option to Telnet for PAT -// Try to fix SCS Tracker recovery -// Ensure RTS/DTR is down on CAT port if using that line for PTT -// Experimental APRS Messaging in Kernel -// Add Rigcontrol on remote PC's using WinmorControl -// ADD VARAFM and VARAFM96 WL2KREPORT modes -// Fix WL2K sysop update for new Winlink API -// Fix APRS when using PORTNUM higher than the number of ports -// Add Serial Port Type -// Add option to linbpq to log APRS-IS messages. -// Send WL2K Session Reports -// Drop Tunneled Packets from 44.192 - 44.255 -// Log incoming Telnet Connects -// Add IPV4: and IPV6: overrides on AXIP Resolver. -// Add SessionTimeLimit to HF sessions (ARDOP, SCSPactor, WINMOR, VARA) -// Add RADIO FREQ command to display current frequency - -// 6.0.20 April 2020 - -// Trap and reject YAPP file transfer request. -// Fix possible overrun of TCP to Node Buffer -// Fix possible crash if APRS WX file doesn't have a terminating newline -// Change communication with BPQAPRS.exe to restore old message popup behaviour -// Preparation for 64 bit version -// Improve flow control on SCS Dragon -// Fragment messages from network links to L2 links with smaller paclen -// Change WL2K report rate to once every two hours -// Add PASS, CTEXT and CMSG commands and Stream Switch support to TNC2 Emulator -// Add SessionTimeLimit command to HF drivers (ARDOP, SCSPactor, WINMOR, VARA) -// Add links to Ports Web Manangement Page to open individual Driver windows -// Add STOPPORT/STARTPORT support to ARDOP, KAM and SCSPactor drivers -// Add CLOSE and OPEN RADIO command so Rigcontrol port can be freed fpr other use. -// Don't try to send WL2K Traffic report if Internet is down -// Move WL2K Traffic reporting to a separate thread so it doesn't block if it can't connect to server -// ADD AGWAPPL config command to set application number. AGWMASK is still supported -// Register Node Alias with UZ7HO Driver -// Register calls when UZ7HO TNC Restarts and at intervals afterwards -// Fix crash when no IOADDR or COMPORT in async port definition -// Fix Crash with Paclink-Unix when parsing ; VE7SPR-10 DE N7NIX QTC 1 -// Only apply BBSFLAG=NOBBS to APPPLICATION 1 -// Add RIGREONFIG command -// fix APRS RECONFIG on LinBPQ -// Fix Web Terminal scroll to end problem on some browsers -// Add PTT_SETS_INPUT option for IC7600 -// Add TELRECONFIG command to reread users or whole config -// Enforce PACLEN on UZ7HO ports -// Fix PACLEN on Command Output. -// Retry axip resolver if it fails at startup -// Fix AGWAPI connect via digis -// Fix Select() for Linux in MultiPSK, UZ7HO and V4 drivers -// Limit APRS OBJECT length to 80 chars -// UZ7HO disconnect incoming call if no free streams -// Improve response to REJ (no F) followed by RR (F). -// Try to prevent more than MAXFRAME frames outstanding when transmitting -// Allow more than one instance of APRS on Linux -// Stop APRS digi by originating station -// Send driver window trace to main monitor system -// Improve handling of IPOLL messages -// Fix setting end of address bit on dest call on connects to listening sessions -// Set default BBS and CHAT application number and number of streams on LinBPQ -// Support #include in bpq32.cfg processing - -// Version 6.0.21 14 December 2020 - -// Fix occasional missing newlines in some node command reponses -// More 64 bit fixes -// Add option to stop setting PDUPLEX param in SCSPACTOR -// Try to fix buffer loss -// Remove extra space from APRS position reports -// Suppress VARA IAMALIVE messages -// Add display and control of QtSoundModem modems -// Only send "No CMS connection available" message if fallbacktorelay is set. -// Add HAMLIB backend and emulator support to RIGCONTROL -// Ensure all beacons are sent even with very short beacon intervals -// Add VARA500 WL2K Reporting Mode -// Fix problem with prpcessing frame collector -// Temporarily disable L2 and L4 collectors till I can find problem -// Fix possible problem with interactive RADIO commands not giving a response, -// Incease maximum length of NODE command responses to handle maximum length INFO message, -// Allow WL2KREPORT in CONFIG section of UZ7HO port config. -// Fix program error in processing hamlib frame -// Save RestartAfterFailure option for VARA -// Check callsign has a winlink account before sending WL2KREPORT messages -// Add Bandwidth control to VARA scanning -// Renable L2 collector -// Fix TNCPORT reconnect on Linux -// Add SecureTelnet option to limit telnet outward connect to sysop mode sessions or Application Aliases -// Add option to suppress sending call to application in Telnet HOST API -// Add FT991A support to RigControl -// Use background.jpg for Edit Config page -// Send OK response to SCS Pactor commands starting with # -// Resend ICOM PTT OFF command after 30 seconds -// Add WXCall to APRS config -// Fixes for AEAPactor -// Allow PTTMUX to use real or com0com com ports -// Fix monitoring with AGW Emulator -// Derive approx position from packets on APRS ports with a valid 6 char location -// Fix corruption of APRS message lists if the station table fills up. -// Don't accept empty username or password on Relay sessions. -// Fix occasional empty Nodes broadcasts -// Add Digis to UZ7HO Port MH list -// Add PERMITTEDAPPLS port param -// Fix WK2K Session Record Reporting for Airmail and some Pactor Modes. -// Fix handling AX/IP (proto 93) frames -// Fix possible corruption sending APRS messages -// Allow Telnet connections to be made using Connect command as well as Attach then Connect -// Fix Cancel Sysop Signin -// Save axip resolver info and restore on restart -// Add Transparent mode to Telnet Server HOST API -// Fix Tracker driver if WL2KREPRRT is in main config section -// SNMP InOctets count corrected to include all frames and encoding of zero values fixed. -// Change IP Gateway to exclude handling bits of 44 Net sold to Amazon -// Fix crash in Web terminal when processing very long lines - -// Version 6.0.22.1 August 2021 - -// Fix bug in KAM TNCEMULATOR -// Add WinRPR Driver (DED over TCP) -// Fix handling of VARA config commands FM1200 and FM9600 -// Improve Web Termanal Line folding -// Add StartTNC to WinRPR driver -// Add support for VARA2750 Mode -// Add support for VARA connects via a VARA Digipeater -// Add digis to SCSTracker and WinRPR MHeard -// Separate RIGCONTROL config from PORT config and add RigControl window -// Fix crash when a Windows HID device doesn't have a product_string -// Changes to VARA TNC connection and restart process -// Trigger FALLBACKTORELAY if attempt to connect to all CMS servers fail. -// Fix saving part lines in adif log and Winlink Session reporting -// Add port specific CTEXT -// Add FRMR monitoring to UZ7HO driver -// Add audio input switching for IC7610 -// Include Rigcontrol Support for IC-F8101E -// Process any response to KISS command -// Fix NODE ADD command -// Add noUpdate flag to AXIP MAP -// Fix clearing NOFALLBACK flag in Telnet Server -// Allow connects to RMS Relay running on another host -// Allow use of Power setting in Rigcontol scan lines for Kenwood radios -// Prevent problems caused by using "CMS" as a Node Alias -// Include standard APRS Station pages in code -// Fix VALIDCALLS processing in HF drivers -// Send Netrom Link reports to Node Map -// Add REALTELNET mode to Telnet Outward Connect -// Fix using S (Stay) parameter on Telnet connects when using CMDPORT and C HOST -// Add Default frequency to rigcontrol to set a freq/mode to return to after a connection -// Fix long (> 60 seconds) scan intervals -// Improved debugging of stuck semaphores -// Fix potential securiby bug in BPQ Web server -// Send Chat Updates to chatupdate.g8bpq.net port 81 -// Add ReportRelayTraffic to Telnet config to send WL2K traffic reports for connections to RELAY -// Add experimental Mode reporting -// Add SendTandRtoRelay param to SCS Pactor, ARDOP and VARA drivers to divert calls to CMS for -T and -R to RELAY -// Add UPNP Support - -// Version 6.0.23.1 June 2022 - -// Add option to control which applcalls are enabled in VARA -// Add support for rtl_udp to Rig Control -// Fix Telnet Auto Conneect to Application when using TermTCP or Web Terminal -// Allow setting css styles for Web Terminal -// And Kill TNC and Kill and Restart TNC commands to Web Driver Windows -// More flexible RigControl for split frequency operation, eg for QO100 -// Increase stack size for ProcessHTMLMessage (.11) -// Fix HTML Content-Type on images (.12) -// Add AIS and ADSB Support (.13) -// Compress web pages (.14) -// Change minidump routine and close after program error (.15) -// Add RMS Relay SYNC Mode (.17) -// Changes for compatibility with Winlink Hybrid -// Add Rigcontrol CMD feature to Yaesu code (21) -// More diagnostic code -// Trap potential buffer overrun in ax/tcp code -// Fix possible hang in UZ7HO driver if connect takes a long time to succeed or fail -// Add FLRIG as backend for RigControl (.24) -// Fix bug in compressing some management web pages -// Fix bugs in AGW Emulator (.25) -// Add more PTT_Sets_Freq options for split frequency working (.26) -// Allow RIGCONTROL using Radio Number (Rnn) as well as Port (.26) -// Fix Telnet negotiation and backspace processing (.29) -// Fix VARA Mode change when scanning (.30) -// Add Web Mgmt Log Display (.33) -// Fix crash when connecting to RELAY when CMS=0 (.36) -// Send OK to user for manual freq changes with hamlib or flrig -// Fix Rigcontrol leaving port disabled when using an empty timeband -// Fix processing of backspace in Telnet character processing (.40) -// Increase max size of connect script -// Fix HAMLIB Slave Thread control -// Add processing of VARA mode responses and display of VARA Mode (41) -// Fix crash when VARA session aborted on LinBPQ (43) -// Fix handling port selector (2:call or p2 call) on SCS PTC packet ports (44) -// Include APRS Map web page -// Add Enable/Disable to KAMPACTOR scan control (use P0 or P1) (45) -// Add Basic DRATS interface (46) -// Fix MYCALLS on VARA (49) -// Add FreeData driver (51) -// Add additonal Rigcontrol options for QO100 (51) -// Set Content-Type: application/pdf for pdf files downloaded via web interface (51) -// Fix sending large compressed web messages (52) -// Fix freq display when using flrig or hamlib backends to rigcontrol -// Change VARA Driver to send ABORT when Session Time limit expires -// Add Chat Log to Web Logs display -// Fix possible buffer loss in RigControl -// Allow hosts on local lan to be treated as secure -// Improve validation of data sent to Winlink SessionAdd API call -// Add support for FreeDATA modem. -// Add GetLOC API Call -// Change Leaflet link in aprs map. -// Add Connect Log (64) -// Fix crash when Resolve CMS Servers returns ipv6 addresses -// Fix Reporting P4 sessions to Winlink (68) -// Add support for FreeBSD (68) -// Fix Rigcontrol PTCPORT (69) -// Set TNC Emulator sessions as secure (72) -// Fix not always detecting loss of FLRIG (73) -// Add ? and * wildcards to NODES command (74) -// Add Port RADIO config parameter (74) - -// Version 6.0.24.1 ?? - -// Apply NODES command wildcard to alias as well a call (2) -// Add STOPPORT/STARTPORT to VARA Driver (2) -// Add bandwidth setting to FLRIG interface. (2) -// Fix N VIA (3) -// Fix NODE ADD and NODE DEL (4) - -#define CKernel - -#include "Versions.h" - -#define _CRT_SECURE_NO_DEPRECATE - -#pragma data_seg("_BPQDATA") - -#include "time.h" -#include "stdio.h" -#include - -#include "compatbits.h" - -#include "AsmStrucs.h" - -#include "SHELLAPI.H" -#include "kernelresource.h" - -#include -#include -#include "BPQTermMDI.h" - -#include "GetVersion.h" - -#define DllImport __declspec( dllimport ) - -#define CheckGuardZone() _CheckGuardZone(__FILE__, __LINE__) -void _CheckGuardZone(char * File, int Line); - -#define CHECKLOADED 0 -#define SETAPPLFLAGS 1 -#define SENDBPQFRAME 2 -#define GETBPQFRAME 3 -#define GETSTREAMSTATUS 4 -#define CLEARSTREAMSTATUS 5 -#define BPQCONDIS 6 -#define GETBUFFERSTATUS 7 -#define GETCONNECTIONINFO 8 -#define BPQRETURN 9 // GETCALLS -//#define RAWTX 10 //IE KISS TYPE DATA -#define GETRAWFRAME 11 -#define UPDATESWITCH 12 -#define BPQALLOC 13 -//#define SENDNETFRAME 14 -#define GETTIME 15 - -extern short NUMBEROFPORTS; -extern long PORTENTRYLEN; -extern long LINKTABLELEN; -extern struct PORTCONTROL * PORTTABLE; -extern void * FREE_Q; -extern UINT APPL_Q; // Queue of frames for APRS Appl - -extern TRANSPORTENTRY * L4TABLE; -extern UCHAR NEXTID; -extern DWORD MAXCIRCUITS; -extern DWORD L4DEFAULTWINDOW; -extern DWORD L4T1; -extern APPLCALLS APPLCALLTABLE[]; -extern char * APPLS; - -extern struct WL2KInfo * WL2KReports; - -extern int NUMBEROFTNCPORTS; - - -void * VCOMExtInit(struct PORTCONTROL * PortEntry); -void * AXIPExtInit(struct PORTCONTROL * PortEntry); -void * SCSExtInit(struct PORTCONTROL * PortEntry); -void * AEAExtInit(struct PORTCONTROL * PortEntry); -void * KAMExtInit(struct PORTCONTROL * PortEntry); -void * HALExtInit(struct PORTCONTROL * PortEntry); -void * ETHERExtInit(struct PORTCONTROL * PortEntry); -void * AGWExtInit(struct PORTCONTROL * PortEntry); -void * WinmorExtInit(EXTPORTDATA * PortEntry); -void * TelnetExtInit(EXTPORTDATA * PortEntry); -//void * SoundModemExtInit(EXTPORTDATA * PortEntry); -void * TrackerExtInit(EXTPORTDATA * PortEntry); -void * TrackerMExtInit(EXTPORTDATA * PortEntry); -void * V4ExtInit(EXTPORTDATA * PortEntry); -void * UZ7HOExtInit(EXTPORTDATA * PortEntry); -void * MPSKExtInit(EXTPORTDATA * PortEntry); -void * FLDigiExtInit(EXTPORTDATA * PortEntry); -void * UIARQExtInit(EXTPORTDATA * PortEntry); -void * SerialExtInit(EXTPORTDATA * PortEntry); -void * ARDOPExtInit(EXTPORTDATA * PortEntry); -void * VARAExtInit(EXTPORTDATA * PortEntry); -void * KISSHFExtInit(EXTPORTDATA * PortEntry); -void * WinRPRExtInit(EXTPORTDATA * PortEntry); -void * HSMODEMExtInit(EXTPORTDATA * PortEntry); -void * FreeDataExtInit(EXTPORTDATA * PortEntry); - -extern char * ConfigBuffer; // Config Area -VOID REMOVENODE(dest_list * DEST); -DllExport int ConvFromAX25(unsigned char * incall,unsigned char * outcall); -DllExport int ConvToAX25(unsigned char * incall,unsigned char * outcall); -VOID GetUIConfig(); -VOID ADIFWriteFreqList(); -void SaveAIS(); -void initAIS(); -void initADSB(); - -extern BOOL ADIFLogEnabled; - -int CloseOnError = 0; - -char UIClassName[]="UIMAINWINDOW"; // the main window class name - -HWND UIhWnd; - -extern char AUTOSAVE; -extern char AUTOSAVEMH; - -extern char MYNODECALL; // 10 chars,not null terminated - -extern QCOUNT; -extern BPQVECSTRUC BPQHOSTVECTOR[]; -#define BPQHOSTSTREAMS 64 -#define IPHOSTVECTOR BPQHOSTVECTOR[BPQHOSTSTREAMS + 3] - -extern char * CONFIGFILENAME; - -DllExport BPQVECSTRUC * BPQHOSTVECPTR; - -extern int DATABASESTART; - -extern struct ROUTE * NEIGHBOURS; -extern int ROUTE_LEN; -extern int MAXNEIGHBOURS; - -extern struct DEST_LIST * DESTS; // NODE LIST -extern int DEST_LIST_LEN; -extern int MAXDESTS; // MAX NODES IN SYSTEM - -extern struct _LINKTABLE * LINKS; -extern int LINK_TABLE_LEN; -extern int MAXLINKS; - - -extern int BPQHOSTAPI(); -extern int INITIALISEPORTS(); -extern int TIMERINTERRUPT(); -extern int MONDECODE(); -extern int BPQMONOPTIONS(); -extern char PWTEXT[]; -extern char PWLen; - -extern int FINDFREEDESTINATION(); -extern int RAWTX(); -extern int RELBUFF(); -extern int SENDNETFRAME(); -extern char MYCALL[]; // 7 chars, ax.25 format - -extern HWND hIPResWnd; -extern BOOL IPMinimized; - -extern int NODESINPROGRESS; -extern VOID * CURRENTNODE; - - -BOOL Start(); - -VOID SaveWindowPos(int port); -VOID SaveAXIPWindowPos(int port); -VOID SetupRTFHddr(); -DllExport VOID APIENTRY CreateNewTrayIcon(); -int DoReceivedData(int Stream); -int DoStateChange(int Stream); -int DoMonData(int Stream); -struct ConsoleInfo * CreateChildWindow(int Stream, BOOL DuringInit); -CloseHostSessions(); -SaveHostSessions(); -VOID SaveBPQ32Windows(); -VOID CloseDriverWindow(int port); -VOID CheckWL2KReportTimer(); -VOID SetApplPorts(); -VOID WriteMiniDump(); -VOID FindLostBuffers(); -BOOL InitializeTNCEmulator(); -VOID TNCTimer(); -char * strlop(char * buf, char delim); - -DllExport int APIENTRY Get_APPLMASK(int Stream); -DllExport int APIENTRY GetStreamPID(int Stream); -DllExport int APIENTRY GetApplFlags(int Stream); -DllExport int APIENTRY GetApplNum(int Stream); -DllExport BOOL APIENTRY GetAllocationState(int Stream); -DllExport int APIENTRY GetMsg(int stream, char * msg, int * len, int * count ); -DllExport int APIENTRY RXCount(int Stream); -DllExport int APIENTRY TXCount(int Stream); -DllExport int APIENTRY MONCount(int Stream); -DllExport int APIENTRY GetCallsign(int stream, char * callsign); -DllExport VOID APIENTRY RelBuff(VOID * Msg); -void SaveMH(); -void DRATSPoll(); - -#define C_Q_ADD(s, b) _C_Q_ADD(s, b, __FILE__, __LINE__); -int _C_Q_ADD(VOID *PQ, VOID *PBUFF, char * File, int Line); - -VOID SetWindowTextSupport(); -int WritetoConsoleSupport(char * buff); -VOID PMClose(); -VOID MySetWindowText(HWND hWnd, char * Msg); -BOOL CreateMonitorWindow(char * MonSize); -VOID FormatTime3(char * Time, time_t cTime); - -char EXCEPTMSG[80] = ""; - -char SIGNONMSG[128] = ""; -char SESSIONHDDR[80] = ""; -int SESSHDDRLEN = 0; - -BOOL IncludesMail = FALSE; -BOOL IncludesChat = FALSE; // Set if pgram is running - used for Web Page Index - - -char WL2KCall[10]; -char WL2KLoc[7]; - -extern char LOCATOR[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char MAPCOMMENT[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char LOC[7]; // Maidenhead Locator for Reporting -extern char ReportDest[7]; - -VOID __cdecl Debugprintf(const char * format, ...); -VOID __cdecl Consoleprintf(const char * format, ...); - -DllExport int APIENTRY CloseBPQ32(); -DllExport char * APIENTRY GetLOC(); -DllExport int APIENTRY SessionControl(int stream, int command, int param); - - -BOOL APIENTRY Init_IP(); -BOOL APIENTRY Poll_IP(); - -BOOL APIENTRY Init_PM(); -BOOL APIENTRY Poll_PM(); - -BOOL APIENTRY Init_APRS(); -BOOL APIENTRY Poll_APRS(); -VOID HTTPTimer(); - -BOOL APIENTRY Rig_Init(); -BOOL APIENTRY Rig_Close(); -BOOL Rig_Poll(); - -VOID IPClose(); -VOID APRSClose(); -VOID CloseTNCEmulator(); - -VOID Poll_AGW(); -BOOL AGWAPIInit(); -int AGWAPITerminate(); - -int * Flag = (int *)&Flag; // for Dump Analysis -int MAJORVERSION=4; -int MINORVERSION=9; - -struct SEM Semaphore = {0, 0, 0, 0}; -struct SEM APISemaphore = {0, 0, 0, 0}; -int SemHeldByAPI = 0; -int LastSemGets = 0; -UINT Sem_eax = 0; -UINT Sem_ebx = 0; -UINT Sem_ecx = 0; -UINT Sem_edx = 0; -UINT Sem_esi = 0; -UINT Sem_edi = 0; - -void GetSemaphore(struct SEM * Semaphore, int ID); -void FreeSemaphore(struct SEM * Semaphore); - -DllExport void * BPQHOSTAPIPTR = &BPQHOSTAPI; -//DllExport long MONDECODEPTR = (long)&MONDECODE; - -extern UCHAR BPQDirectory[]; -extern UCHAR LogDirectory[]; -extern UCHAR BPQProgramDirectory[]; - -static char BPQWinMsg[] = "BPQWindowMessage"; - -static char ClassName[] = "BPQMAINWINDOW"; - -HKEY REGTREE = HKEY_CURRENT_USER; -char REGTREETEXT[100] = "HKEY_CURRENT_USER"; - -UINT BPQMsg=0; - -#define MAXLINELEN 120 -#define MAXSCREENLEN 50 - -#define BGCOLOUR RGB(236,233,216) - -HBRUSH bgBrush = NULL; - -//int LINELEN=120; -//int SCREENLEN=50; - -//char Screen[MAXLINELEN*MAXSCREENLEN]={0}; - -//int lineno=0; -//int col=0; - -#define REPORTINTERVAL 15 * 549; // Magic Ticks Per Minute for PC's nominal 100 ms timer -int ReportTimer = 0; - -HANDLE OpenConfigFile(char * file); - -VOID SetupBPQDirectory(); -VOID SendLocation(); - -//uintptr_t _beginthread(void(*start_address)(), unsigned stack_size, int arglist); - -#define TRAY_ICON_ID 1 // ID number for the Notify Icon -#define MY_TRAY_ICON_MESSAGE WM_APP // the message ID sent to our window - -NOTIFYICONDATA niData; - -int SetupConsoleWindow(); - -BOOL StartMinimized=FALSE; -BOOL MinimizetoTray=TRUE; - -BOOL StatusMinimized = FALSE; -BOOL ConsoleMinimized = FALSE; - -HMENU trayMenu=0; - -HWND hConsWnd = NULL, hWndCons = NULL, hWndBG = NULL, ClientWnd = NULL, FrameWnd = NULL, StatusWnd = NULL; - -BOOL FrameMaximized = FALSE; - -BOOL IGateEnabled = TRUE; -extern int ISDelayTimer; // Time before trying to reopen APRS-IS link -extern int ISPort; - -UINT * WINMORTraceQ = NULL; -UINT * SetWindowTextQ = NULL; - -static RECT Rect = {100,100,400,400}; // Console Window Position -RECT FRect = {100,100,800,600}; // Frame -static RECT StatusRect = {100,100,850,500}; // Status Window - -DllExport int APIENTRY DumpSystem(); -DllExport int APIENTRY SaveNodes (); -DllExport int APIENTRY ClearNodes (); -DllExport int APIENTRY SetupTrayIcon(); - -#define Q_REM(s) _Q_REM(s, __FILE__, __LINE__) - -VOID * _Q_REM(VOID *Q, char * File, int Line); - -UINT ReleaseBuffer(UINT *BUFF); - - -VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime ); - -DllExport int APIENTRY DeallocateStream(int stream); - -int VECTORLENGTH = sizeof (struct _BPQVECSTRUC); - -int FirstEntry = 1; -BOOL CloseLast = TRUE; // If the user started BPQ32.exe, don't close it when other programs close -BOOL Closing = FALSE; // Set if Close All called - prevents respawning bpq32.exe - -BOOL BPQ32_EXE; // Set if Process is running BPQ32.exe. Not initialised. - // Used to Kill surplus BPQ32.exe processes - -DWORD Our_PID; // Our Process ID - local variable - -void * InitDone = 0; -int FirstInitDone = 0; -int PerlReinit = 0; -UINT_PTR TimerHandle = 0; -UINT_PTR SessHandle = 0; - -unsigned int TimerInst = 0xffffffff; - -HANDLE hInstance = 0; - -int AttachedProcesses = 0; -int AttachingProcess = 0; -HINSTANCE hIPModule = 0; -HINSTANCE hRigModule = 0; - -BOOL ReconfigFlag = FALSE; -BOOL RigReconfigFlag = FALSE; -BOOL APRSReconfigFlag = FALSE; -BOOL CloseAllNeeded = FALSE; - -int AttachedPIDList[100] = {0}; - -HWND hWndArray[100] = {0}; -int PIDArray[100] = {0}; -char PopupText[30][100] = {""}; - -// Next 3 should be uninitialised so they are local to each process - -UCHAR MCOM; -UCHAR MTX; -ULONG MMASK; -UCHAR MUIONLY; - -UCHAR AuthorisedProgram; // Local Variable. Set if Program is on secure list - -char pgm[256]; // Uninitialised so per process - -HANDLE Mutex; - -BOOL PartLine = FALSE; -int pindex = 0; -DWORD * WritetoConsoleQ; - - -LARGE_INTEGER lpFrequency = {0}; -LARGE_INTEGER lastRunTime; -LARGE_INTEGER currentTime; - -int ticksPerMillisec; -int interval; - - -VOID CALLBACK SetupTermSessions(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime); - - -TIMERPROC lpTimerFunc = (TIMERPROC) TimerProc; -TIMERPROC lpSetupTermSessions = (TIMERPROC) SetupTermSessions; - - -BOOL ProcessConfig(); -VOID FreeConfig(); - -DllExport int APIENTRY WritetoConsole(char * buff); - -BOOLEAN CheckifBPQ32isLoaded(); -BOOLEAN StartBPQ32(); -DllExport VOID APIENTRY Send_AX(VOID * Block, DWORD len, UCHAR Port); -BOOL LoadIPDriver(); -BOOL Send_IP(VOID * Block, DWORD len); -VOID CheckforLostProcesses(); -BOOL LoadRigDriver(); -VOID SaveConfig(); -VOID CreateRegBackup(); -VOID ResolveUpdateThread(); -VOID OpenReportingSockets(); -DllExport VOID APIENTRY CloseAllPrograms(); -DllExport BOOL APIENTRY SaveReg(char * KeyIn, HANDLE hFile); -int upnpClose(); - -BOOL IPActive = FALSE; -extern BOOL IPRequired; -BOOL PMActive = FALSE; -extern BOOL PMRequired; -BOOL RigRequired = TRUE; -BOOL RigActive = FALSE; -BOOL APRSActive = FALSE; -BOOL AGWActive = FALSE; -BOOL needAIS = FALSE; -int needADSB = 0; - -extern int AGWPort; - -Tell_Sessions(); - - -typedef int (WINAPI FAR *FARPROCX)(); - -FARPROCX CreateToolHelp32SnapShotPtr; -FARPROCX Process32Firstptr; -FARPROCX Process32Nextptr; - -void LoadToolHelperRoutines() -{ - HINSTANCE ExtDriver=0; - int err; - char msg[100]; - - ExtDriver=LoadLibrary("kernel32.dll"); - - if (ExtDriver == NULL) - { - err=GetLastError(); - sprintf(msg,"BPQ32 Error loading kernel32.dll - Error code %d\n", err); - OutputDebugString(msg); - return; - } - - CreateToolHelp32SnapShotPtr = (FARPROCX)GetProcAddress(ExtDriver,"CreateToolhelp32Snapshot"); - Process32Firstptr = (FARPROCX)GetProcAddress(ExtDriver,"Process32First"); - Process32Nextptr = (FARPROCX)GetProcAddress(ExtDriver,"Process32Next"); - - if (CreateToolHelp32SnapShotPtr == 0) - { - err=GetLastError(); - sprintf(msg,"BPQ32 Error getting CreateToolhelp32Snapshot entry point - Error code %d\n", err); - OutputDebugString(msg); - return; - } -} - -BOOL GetProcess(int ProcessID, char * Program) -{ - HANDLE hProcessSnap; - PROCESSENTRY32 pe32; - int p; - - if (CreateToolHelp32SnapShotPtr==0) - { - return (TRUE); // Routine not available - } - // Take a snapshot of all processes in the system. - hProcessSnap = (HANDLE)CreateToolHelp32SnapShotPtr(TH32CS_SNAPPROCESS, 0); - if( hProcessSnap == INVALID_HANDLE_VALUE ) - { - OutputDebugString( "CreateToolhelp32Snapshot (of processes) Failed\n" ); - return( FALSE ); - } - - // Set the size of the structure before using it. - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - // Retrieve information about the first process, - // and exit if unsuccessful - if( !Process32Firstptr( hProcessSnap, &pe32 ) ) - { - OutputDebugString( "Process32First Failed\n" ); // Show cause of failure - CloseHandle( hProcessSnap ); // Must clean up the snapshot object! - return( FALSE ); - } - - // Now walk the snapshot of processes, and - // display information about each process in turn - do - { - if (ProcessID==pe32.th32ProcessID) - { - // if running on 98, program contains the full path - remove it - - for (p = (int)strlen(pe32.szExeFile); p >= 0; p--) - { - if (pe32.szExeFile[p]=='\\') - { - break; - } - } - p++; - - sprintf(Program,"%s", &pe32.szExeFile[p]); - CloseHandle( hProcessSnap ); - return( TRUE ); - } - - } while( Process32Nextptr( hProcessSnap, &pe32 ) ); - - - sprintf(Program,"PID %d Not Found", ProcessID); - CloseHandle( hProcessSnap ); - return(FALSE); -} - -BOOL IsProcess(int ProcessID) -{ - // Check that Process exists - - HANDLE hProcessSnap; - PROCESSENTRY32 pe32; - - if (CreateToolHelp32SnapShotPtr==0) return (TRUE); // Routine not available - - hProcessSnap = (HANDLE)CreateToolHelp32SnapShotPtr(TH32CS_SNAPPROCESS, 0); - - if( hProcessSnap == INVALID_HANDLE_VALUE ) - { - OutputDebugString( "CreateToolhelp32Snapshot (of processes) Failed\n" ); - return(TRUE); // Don't know, so assume ok - } - - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - if( !Process32Firstptr( hProcessSnap, &pe32 ) ) - { - OutputDebugString( "Process32First Failed\n" ); // Show cause of failure - CloseHandle( hProcessSnap ); // Must clean up the snapshot object! - return(TRUE); // Don't know, so assume ok - } - - do - { - if (ProcessID==pe32.th32ProcessID) - { - CloseHandle( hProcessSnap ); - return( TRUE ); - } - - } while( Process32Nextptr( hProcessSnap, &pe32 ) ); - - CloseHandle( hProcessSnap ); - return(FALSE); -} - -#include "DbgHelp.h" - -VOID MonitorThread(int x) -{ - // Thread to detect killed processes. Runs in process owning timer. - - // Obviously can't detect loss of timer owning thread! - - do - { - if (Semaphore.Gets == LastSemGets && Semaphore.Flag) - { - // It is stuck - try to release - - Debugprintf ("Semaphore locked - Process ID = %d, Held By %d", - Semaphore.SemProcessID, SemHeldByAPI); - - // Write a minidump - - WriteMiniDump(); - - Semaphore.Flag = 0; - } - - LastSemGets = Semaphore.Gets; - - Sleep(30000); - CheckforLostProcesses(); - - } while (TRUE); -} - -VOID CheckforLostProcesses() -{ - UCHAR buff[100]; - char Log[80]; - int i, n, ProcessID; - - for (n=0; n < AttachedProcesses; n++) - { - ProcessID=AttachedPIDList[n]; - - if (!IsProcess(ProcessID)) - { - // Process has died - Treat as a detach - - sprintf(Log,"BPQ32 Process %d Died\n", ProcessID); - OutputDebugString(Log); - - // Remove Tray Icon Entry - - for( i = 0; i < 100; ++i ) - { - if (PIDArray[i] == ProcessID) - { - hWndArray[i] = 0; - sprintf(Log,"BPQ32 Removing Tray Item %s\n", PopupText[i]); - OutputDebugString(Log); - DeleteMenu(trayMenu,TRAYBASEID+i,MF_BYCOMMAND); - } - } - - // If process had the semaphore, release it - - if (Semaphore.Flag == 1 && ProcessID == Semaphore.SemProcessID) - { - OutputDebugString("BPQ32 Process was holding Semaphore - attempting recovery\r\n"); - Debugprintf("Last Sem Call %d %x %x %x %x %x %x", SemHeldByAPI, - Sem_eax, Sem_ebx, Sem_ecx, Sem_edx, Sem_esi, Sem_edi); - - Semaphore.Flag = 0; - SemHeldByAPI = 0; - } - - for (i=1;i<65;i++) - { - if (BPQHOSTVECTOR[i-1].STREAMOWNER == AttachedPIDList[n]) - { - DeallocateStream(i); - } - } - - if (TimerInst == ProcessID) - { - KillTimer(NULL,TimerHandle); - TimerHandle=0; - TimerInst=0xffffffff; -// Tell_Sessions(); - OutputDebugString("BPQ32 Process was running timer \n"); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - - } - - // Remove this entry from PID List - - for (i=n; i< AttachedProcesses; i++) - { - AttachedPIDList[i]=AttachedPIDList[i+1]; - } - AttachedProcesses--; - - sprintf(buff,"BPQ32 Lost Process - %d Process(es) Attached\n", AttachedProcesses); - OutputDebugString(buff); - } - } -} -VOID MonitorTimerThread(int x) -{ - // Thread to detect killed timer process. Runs in all other BPQ32 processes. - - do { - - Sleep(60000); - - if (TimerInst != 0xffffffff && !IsProcess(TimerInst)) - { - // Timer owning Process has died - Force a new timer to be created - // New timer thread will detect lost process and tidy up - - Debugprintf("BPQ32 Process %d with Timer died", TimerInst); - - // If process was holding the semaphore, release it - - if (Semaphore.Flag == 1 && TimerInst == Semaphore.SemProcessID) - { - OutputDebugString("BPQ32 Process was holding Semaphore - attempting recovery\r\n"); - Debugprintf("Last Sem Call %d %x %x %x %x %x %x", SemHeldByAPI, - Sem_eax, Sem_ebx, Sem_ecx, Sem_edx, Sem_esi, Sem_edi); - Semaphore.Flag = 0; - SemHeldByAPI = 0; - } - -// KillTimer(NULL,TimerHandle); -// TimerHandle=0; -// TimerInst=0xffffffff; -// Tell_Sessions(); - - CheckforLostProcesses(); // Normally only done in timer thread, which is now dead - - // Timer can only run in BPQ32.exe - - TimerInst=0xffffffff; // So we dont keep doing it - TimerHandle = 0; // So new process attaches - - if (Closing == FALSE && AttachingProcess == FALSE) - { - OutputDebugString("BPQ32 Reloading BPQ32.exe\n"); - StartBPQ32(); - } - -// if (MinimizetoTray) -// Shell_NotifyIcon(NIM_DELETE,&niData); - } - - } while (TRUE); -} - -VOID WritetoTraceSupport(struct TNCINFO * TNC, char * Msg, int Len); - -VOID TimerProcX(); - -VOID CALLBACK TimerProc( - HWND hwnd, // handle of window for timer messages - UINT uMsg, // WM_TIMER message - UINT idEvent, // timer identifier - DWORD dwTime) // current system time -{ - KillTimer(NULL,TimerHandle); - TimerProcX(); - TimerHandle = SetTimer(NULL,0,100,lpTimerFunc); -} -VOID TimerProcX() -{ - struct _EXCEPTION_POINTERS exinfo; - - // - // Get semaphore before proceeeding - // - - GetSemaphore(&Semaphore, 2); - - // Get time since last run - - QueryPerformanceCounter(¤tTime); - - interval = (int)(currentTime.QuadPart - lastRunTime.QuadPart) / ticksPerMillisec; - lastRunTime.QuadPart = currentTime.QuadPart; - - //Debugprintf("%d", interval); - - // Process WINMORTraceQ - - while (WINMORTraceQ) - { - UINT * Buffer = Q_REM(&WINMORTraceQ); - struct TNCINFO * TNC = (struct TNCINFO * )Buffer[1]; - int Len = Buffer[2]; - char * Msg = (char *)&Buffer[3]; - - WritetoTraceSupport(TNC, Msg, Len); - RelBuff(Buffer); - } - - if (SetWindowTextQ) - SetWindowTextSupport(); - - while (WritetoConsoleQ) - { - UINT * Buffer = Q_REM(&WritetoConsoleQ); - WritetoConsoleSupport((char *)&Buffer[2]); - RelBuff(Buffer); - } - - strcpy(EXCEPTMSG, "Timer ReconfigProcessing"); - - __try - { - - if (trayMenu == NULL) - SetupTrayIcon(); - - // See if reconfigure requested - - if (CloseAllNeeded) - { - CloseAllNeeded = FALSE; - CloseAllPrograms(); - } - - if (ReconfigFlag) - { - // Only do it it timer owning process, or we could get in a real mess! - - if(TimerInst == GetCurrentProcessId()) - { - int i; - BPQVECSTRUC * HOSTVEC; - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - WSADATA WsaData; // receives data from WSAStartup - RECT cRect; - - ReconfigFlag = FALSE; - - SetupBPQDirectory(); - - WritetoConsole("Reconfiguring ...\n\n"); - OutputDebugString("BPQ32 Reconfiguring ...\n"); - - GetWindowRect(FrameWnd, &FRect); - - SaveWindowPos(40); // Rigcontrol - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - CloseDriverWindow(PORTVEC->PORTCONTROL.PORTNUMBER); - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); // Close External Ports - } - } - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - IPClose(); - PMClose(); - APRSClose(); - Rig_Close(); - CloseTNCEmulator(); - if (AGWActive) - AGWAPITerminate(); - - WSACleanup(); - - WL2KReports = NULL; - - Sleep(2000); - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - - Start(); - - INITIALISEPORTS(); // Restart Ports - - SetApplPorts(); - - FreeConfig(); - - for (i=1; i<68; i++) // Include Telnet, APRS and IP Vec - { - HOSTVEC=&BPQHOSTVECTOR[i-1]; - - HOSTVEC->HOSTTRACEQ=0; // Clear header (pool has been reinitialized - - if (HOSTVEC->HOSTSESSION !=0) - { - // Had a connection - - HOSTVEC->HOSTSESSION=0; - HOSTVEC->HOSTFLAGS |=3; // Disconnected - - PostMessage(HOSTVEC->HOSTHANDLE, BPQMsg, i, 4); - } - } - - // Free the APRS Appl Q - - APPL_Q = 0; - - OpenReportingSockets(); - - WritetoConsole("\n\nReconfiguration Complete\n"); - - if (IPRequired) IPActive = Init_IP(); - if (PMRequired) PMActive = Init_PM(); - - APRSActive = Init_APRS(); - - if (ISPort == 0) - IGateEnabled = 0; - - CheckDlgButton(hConsWnd, IDC_ENIGATE, IGateEnabled); - - GetClientRect(hConsWnd, &cRect); - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - { - ShowWindow(GetDlgItem(hConsWnd, IDC_GPS), SW_HIDE); - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - } - InvalidateRect(hConsWnd, NULL, TRUE); - - RigActive = Rig_Init(); - - if (NUMBEROFTNCPORTS) - { - FreeSemaphore(&Semaphore); - InitializeTNCEmulator(); - GetSemaphore(&Semaphore, 0); - } - - FreeSemaphore(&Semaphore); - AGWActive = AGWAPIInit(); - GetSemaphore(&Semaphore, 0); - - OutputDebugString("BPQ32 Reconfiguration Complete\n"); - } - } - - - if (RigReconfigFlag) - { - // Only do it it timer owning process, or we could get in a real mess! - - if(TimerInst == GetCurrentProcessId()) - { - RigReconfigFlag = FALSE; - CloseDriverWindow(40); - Rig_Close(); - Sleep(6000); // Allow any CATPTT, HAMLIB and FLRIG threads to close - RigActive = Rig_Init(); - - WritetoConsole("Rigcontrol Reconfiguration Complete\n"); - } - } - - if (APRSReconfigFlag) - { - // Only do it it timer owning process, or we could get in a real mess! - - if(TimerInst == GetCurrentProcessId()) - { - APRSReconfigFlag = FALSE; - APRSClose(); - APRSActive = Init_APRS(); - - WritetoConsole("APRS Reconfiguration Complete\n"); - } - } - - } - #include "StdExcept.c" - - if (Semaphore.Flag && Semaphore.SemProcessID == GetCurrentProcessId()) - FreeSemaphore(&Semaphore); - - } - - strcpy(EXCEPTMSG, "Timer Processing"); - - __try - { - if (IPActive) Poll_IP(); - if (PMActive) Poll_PM(); - if (RigActive) Rig_Poll(); - - CheckGuardZone(); - - if (APRSActive) - { - Poll_APRS(); - CheckGuardZone(); - } - - CheckWL2KReportTimer(); - - CheckGuardZone(); - - TIMERINTERRUPT(); - - CheckGuardZone(); - - FreeSemaphore(&Semaphore); // SendLocation needs to get the semaphore - - if (NUMBEROFTNCPORTS) - TNCTimer(); - - if (AGWActive) - Poll_AGW(); - - DRATSPoll(); - - CheckGuardZone(); - - strcpy(EXCEPTMSG, "HTTP Timer Processing"); - - HTTPTimer(); - - CheckGuardZone(); - - strcpy(EXCEPTMSG, "WL2K Report Timer Processing"); - - if (ReportTimer) - { - ReportTimer--; - - if (ReportTimer == 0) - { - ReportTimer = REPORTINTERVAL; - SendLocation(); - } - } - } - - #include "StdExcept.c" - - if (Semaphore.Flag && Semaphore.SemProcessID == GetCurrentProcessId()) - FreeSemaphore(&Semaphore); - - } - - CheckGuardZone(); - - return; -} - -HANDLE NPHandle; - -int (WINAPI FAR *GetModuleFileNameExPtr)() = NULL; -int (WINAPI FAR *EnumProcessesPtr)() = NULL; - -FirstInit() -{ - WSADATA WsaData; // receives data from WSAStartup - HINSTANCE ExtDriver=0; - RECT cRect; - - - // First Time Ports and Timer init - - // Moved from DLLINIT to sort out perl problem, and meet MS Guidelines on minimising DLLMain - - // Call wsastartup - most systems need winsock, and duplicate statups could be a problem - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - // Load Psapi.dll if possible - - ExtDriver=LoadLibrary("Psapi.dll"); - - SetupTrayIcon(); - - if (ExtDriver) - { - GetModuleFileNameExPtr = (FARPROCX)GetProcAddress(ExtDriver,"GetModuleFileNameExA"); - EnumProcessesPtr = (FARPROCX)GetProcAddress(ExtDriver,"EnumProcesses"); - } - INITIALISEPORTS(); - - OpenReportingSockets(); - - WritetoConsole("\n"); - WritetoConsole("Port Initialisation Complete\n"); - - if (IPRequired) IPActive = Init_IP(); - if (PMRequired) PMActive = Init_PM(); - - APRSActive = Init_APRS(); - - if (APRSActive) - { - hWndBG = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 0,0,40,546, hConsWnd, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Enable IGate", WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, - 8,0,90,24, hConsWnd, (HMENU)-1, hInstance, NULL); - - CreateWindowEx(0, "BUTTON", "", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP, - 95,1,18,24, hConsWnd, (HMENU)IDC_ENIGATE, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "IGate State - Disconnected", - WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 125, 0, 195, 24, hConsWnd, (HMENU)IGATESTATE, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "IGATE Stats - Msgs 0 Local Stns 0", - WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 320, 0, 240, 24, hConsWnd, (HMENU)IGATESTATS, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "GPS Off", - WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, 560, 0, 80, 24, hConsWnd, (HMENU)IDC_GPS, hInstance, NULL); - } - - if (ISPort == 0) - IGateEnabled = 0; - - CheckDlgButton(hConsWnd, IDC_ENIGATE, IGateEnabled); - - GetClientRect(hConsWnd, &cRect); - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - { - ShowWindow(GetDlgItem(hConsWnd, IDC_GPS), SW_HIDE); - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - } - InvalidateRect(hConsWnd, NULL, TRUE); - - RigActive = Rig_Init(); - - _beginthread(MonitorThread,0,0); - - TimerHandle=SetTimer(NULL,0,100,lpTimerFunc); - TimerInst=GetCurrentProcessId(); - SessHandle = SetTimer(NULL, 0, 5000, lpSetupTermSessions); - - // If ARIF reporting is enabled write a Trimode Like ini for RMS Analyser - - if (ADIFLogEnabled) - ADIFWriteFreqList(); - - OutputDebugString("BPQ32 Port Initialisation Complete\n"); - - if (needAIS) - initAIS(); - - if (needADSB) - initADSB(); - - return 0; -} - -Check_Timer() -{ - if (Closing) - return 0; - - if (Semaphore.Flag) - return 0; - - if (InitDone == (void *)-1) - { - GetSemaphore(&Semaphore, 3); - Sleep(15000); - FreeSemaphore(&Semaphore); - exit (0); - } - - if (FirstInitDone == 0) - { - GetSemaphore(&Semaphore, 3); - - if (_stricmp(pgm, "bpq32.exe") == 0) - { - FirstInit(); - FreeSemaphore(&Semaphore); - if (NUMBEROFTNCPORTS) - InitializeTNCEmulator(); - - AGWActive = AGWAPIInit(); - FirstInitDone=1; // Only init in BPQ32.exe - return 0; - } - else - { - FreeSemaphore(&Semaphore); - return 0; - } - } - - if (TimerHandle == 0 && FirstInitDone == 1) - { - WSADATA WsaData; // receives data from WSAStartup - HINSTANCE ExtDriver=0; - RECT cRect; - - // Only attach timer to bpq32.exe - - if (_stricmp(pgm, "bpq32.exe") != 0) - { - return 0; - } - - GetSemaphore(&Semaphore, 3); - OutputDebugString("BPQ32 Reinitialising External Ports and Attaching Timer\n"); - - if (!ProcessConfig()) - { - ShowWindow(hConsWnd, SW_RESTORE); - SendMessage(hConsWnd, WM_PAINT, 0, 0); - SetForegroundWindow(hConsWnd); - - InitDone = (void *)-1; - FreeSemaphore(&Semaphore); - - MessageBox(NULL,"Configuration File Error","BPQ32",MB_ICONSTOP); - - exit (0); - } - - GetVersionInfo("bpq32.dll"); - - SetupConsoleWindow(); - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - Consoleprintf("Reinitialising..."); - - SetupBPQDirectory(); - - Sleep(1000); // Allow time for sockets to close - - WSAStartup(MAKEWORD(2, 0), &WsaData); - - // Load Psapi.dll if possible - - ExtDriver = LoadLibrary("Psapi.dll"); - - SetupTrayIcon(); - - if (ExtDriver) - { - GetModuleFileNameExPtr = (FARPROCX)GetProcAddress(ExtDriver,"GetModuleFileNameExA"); - EnumProcessesPtr = (FARPROCX)GetProcAddress(ExtDriver,"EnumProcesses"); - } - - Start(); - - INITIALISEPORTS(); - - OpenReportingSockets(); - - NODESINPROGRESS = 0; - CURRENTNODE = 0; - - SetApplPorts(); - - WritetoConsole("\n\nPort Reinitialisation Complete\n"); - - BPQMsg = RegisterWindowMessage(BPQWinMsg); - - CreateMutex(NULL,TRUE,"BPQLOCKMUTEX"); - -// NPHandle=CreateNamedPipe("\\\\.\\pipe\\BPQ32pipe", -// PIPE_ACCESS_DUPLEX,0,64,4096,4096,1000,NULL); - - if (IPRequired) IPActive = Init_IP(); - if (PMRequired) PMActive = Init_PM(); - - RigActive = Rig_Init(); - APRSActive = Init_APRS(); - - if (ISPort == 0) - IGateEnabled = 0; - - CheckDlgButton(hConsWnd, IDC_ENIGATE, IGateEnabled); - - GetClientRect(hConsWnd, &cRect); - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - { - ShowWindow(GetDlgItem(hConsWnd, IDC_GPS), SW_HIDE); - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - } - InvalidateRect(hConsWnd, NULL, TRUE); - - FreeConfig(); - - _beginthread(MonitorThread,0,0); - - ReportTimer = 0; - - OpenReportingSockets(); - - FreeSemaphore(&Semaphore); - - if (NUMBEROFTNCPORTS) - InitializeTNCEmulator(); - - AGWActive = AGWAPIInit(); - - if (StartMinimized) - if (MinimizetoTray) - ShowWindow(FrameWnd, SW_HIDE); - else - ShowWindow(FrameWnd, SW_SHOWMINIMIZED); - else - ShowWindow(FrameWnd, SW_RESTORE); - - TimerHandle=SetTimer(NULL,0,100,lpTimerFunc); - TimerInst=GetCurrentProcessId(); - SessHandle = SetTimer(NULL, 0, 5000, lpSetupTermSessions); - - return (1); - } - - return (0); -} - -DllExport INT APIENTRY CheckTimer() -{ - return Check_Timer(); -} - -Tell_Sessions() -{ - // - // Post a message to all listening sessions, so they call the - // API, and cause a new timer to be allocated - // - HWND hWnd; - int i; - - for (i=1;i<65;i++) - { - if (BPQHOSTVECTOR[i-1].HOSTFLAGS & 0x80) - { - hWnd = BPQHOSTVECTOR[i-1].HOSTHANDLE; - PostMessage(hWnd, BPQMsg,i, 1); - PostMessage(hWnd, BPQMsg,i, 2); - } - } - return (0); -} - -BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved) -{ - DWORD n; - char buf[350]; - - int i; - unsigned int ProcessID; - - OSVERSIONINFO osvi; - - memset(&osvi, 0, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - - GetVersionEx(&osvi); - - - switch( ul_reason_being_called ) - { - case DLL_PROCESS_ATTACH: - - if (sizeof(HDLCDATA) > PORTENTRYLEN + 200) // 200 bytes of Hardwaredata - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"BPQ32 Too much HDLC data - Recompile","BPQ32", MB_OK); - return 0; - } - - if (sizeof(LINKTABLE) != LINK_TABLE_LEN) - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"L2 LINK Table .c and .asm mismatch - fix and rebuild","BPQ32", MB_OK); - return 0; - } - if (sizeof(struct ROUTE) != ROUTE_LEN) - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"ROUTE Table .c and .asm mismatch - fix and rebuild", "BPQ32", MB_OK); - return 0; - } - - if (sizeof(struct DEST_LIST) != DEST_LIST_LEN) - { - // Catastrophic - Refuse to load - - MessageBox(NULL,"NODES Table .c and .asm mismatch - fix and rebuild", "BPQ32", MB_OK); - return 0; - } - - GetSemaphore(&Semaphore, 4); - - BPQHOSTVECPTR = &BPQHOSTVECTOR[0]; - - LoadToolHelperRoutines(); - - Our_PID = GetCurrentProcessId(); - - QueryPerformanceFrequency(&lpFrequency); - - ticksPerMillisec = (int)lpFrequency.QuadPart / 1000; - - lastRunTime.QuadPart = lpFrequency.QuadPart; - - GetProcess(Our_PID, pgm); - - if (_stricmp(pgm, "regsvr32.exe") == 0 || _stricmp(pgm, "bpqcontrol.exe") == 0) - { - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 1; - } - - if (_stricmp(pgm,"BPQ32.exe") == 0) - BPQ32_EXE = TRUE; - - if (_stricmp(pgm,"BPQMailChat.exe") == 0) - IncludesMail = TRUE; - - if (_stricmp(pgm,"BPQMail.exe") == 0) - IncludesMail = TRUE; - - if (_stricmp(pgm,"BPQChat.exe") == 0) - IncludesChat = TRUE; - - if (FirstEntry) // If loaded by BPQ32.exe, dont close it at end - { - FirstEntry = 0; - if (BPQ32_EXE) - CloseLast = FALSE; - } - else - { - if (BPQ32_EXE && AttachingProcess == 0) - { - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - MessageBox(NULL,"BPQ32.exe is already running\r\n\r\nIt should only be run once", "BPQ32", MB_OK); - return 0; - } - } - - if (_stricmp(pgm,"BPQTelnetServer.exe") == 0) - { - MessageBox(NULL,"BPQTelnetServer is no longer supported\r\n\r\nUse the TelnetServer in BPQ32.dll", "BPQ32", MB_OK); - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 0; - } - - if (_stricmp(pgm,"BPQUIUtil.exe") == 0) - { - MessageBox(NULL,"BPQUIUtil is now part of BPQ32.dll\r\nBPQUIUtil.exe cannot be run\r\n", "BPQ32", MB_OK); - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 0; - } - - if (_stricmp(pgm,"BPQMailChat.exe") == 0) - { - MessageBox(NULL,"BPQMailChat is obsolete. Run BPQMail.exe and/or BPQChat.exe instead", "BPQ32", MB_OK); - AttachedProcesses++; // We will get a detach - FreeSemaphore(&Semaphore); - return 0; - } - AuthorisedProgram = TRUE; - - if (InitDone == 0) - { -// #pragma warning(push) -// #pragma warning(disable : 4996) - -// if (_winver < 0x0600) -// #pragma warning(pop) -// { -// // Below Vista -// -// REGTREE = HKEY_LOCAL_MACHINE; -// strcpy(REGTREETEXT, "HKEY_LOCAL_MACHINE"); -// } - - hInstance=hInst; - - Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"BPQLOCKMUTEX"); - - if (Mutex != NULL) - { - OutputDebugString("Another BPQ32.dll is loaded\n"); - i=MessageBox(NULL,"BPQ32 DLL already loaded from another directory\nIf you REALLY want this, hit OK, else hit Cancel","BPQ32",MB_OKCANCEL); - FreeSemaphore(&Semaphore); - - if (i != IDOK) return (0); - - CloseHandle(Mutex); - } - - if (!BPQ32_EXE) - { - if (CheckifBPQ32isLoaded() == FALSE) // Start BPQ32.exe if needed - { - // Wasn't Loaded, so we have started it, and should let it init system - - goto SkipInit; - } - } - - GetVersionInfo("bpq32.dll"); - - sprintf (SIGNONMSG, "G8BPQ AX25 Packet Switch System Version %s %s\r\n%s\r\n", - TextVerstring, Datestring, VerCopyright); - - SESSHDDRLEN = sprintf(SESSIONHDDR, "G8BPQ Network System %s for Win32 (", TextVerstring); - - SetupConsoleWindow(); - SetupBPQDirectory(); - - if (!ProcessConfig()) - { - StartMinimized = FALSE; - MinimizetoTray = FALSE; - ShowWindow(FrameWnd, SW_MAXIMIZE); - ShowWindow(hConsWnd, SW_MAXIMIZE); - ShowWindow(StatusWnd, SW_HIDE); - - SendMessage(hConsWnd, WM_PAINT, 0, 0); - SetForegroundWindow(hConsWnd); - - InitDone = (void *)-1; - FreeSemaphore(&Semaphore); - - MessageBox(NULL,"Configuration File Error\r\nProgram will close in 15 seconds","BPQ32",MB_ICONSTOP); - - return (0); - } - - Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring); - Consoleprintf(VerCopyright); - - if (Start() !=0) - { - Sleep(3000); - FreeSemaphore(&Semaphore); - return (0); - } - else - { - SetApplPorts(); - - GetUIConfig(); - - InitDone = &InitDone; - BPQMsg = RegisterWindowMessage(BPQWinMsg); -// TimerHandle=SetTimer(NULL,0,100,lpTimerFunc); -// TimerInst=GetCurrentProcessId(); - -/* Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"BPQLOCKMUTEX"); - - if (Mutex != NULL) - { - OutputDebugString("Another BPQ32.dll is loaded\n"); - MessageBox(NULL,"BPQ32 DLL already loaded from another directory","BPQ32",MB_ICONSTOP); - FreeSemaphore(&Semaphore); - return (0); - } - -*/ - Mutex=CreateMutex(NULL,TRUE,"BPQLOCKMUTEX"); - -// CreatePipe(&H1,&H2,NULL,1000); - -// GetLastError(); - -// NPHandle=CreateNamedPipe("\\\\.\\pipe\\BPQ32pipe", -// PIPE_ACCESS_DUPLEX,0,64,4096,4096,1000,NULL); - -// GetLastError(); - -/* - // - // Read SYSOP password - // - - if (PWTEXT[0] == 0) - { - handle = OpenConfigFile("PASSWORD.BPQ"); - - if (handle == INVALID_HANDLE_VALUE) - { - WritetoConsole("Can't open PASSWORD.BPQ\n"); - PWLen=0; - PWTEXT[0]=0; - } - else - { - ReadFile(handle,PWTEXT,78,&n,NULL); - CloseHandle(handle); - } - } -*/ - for (i=0;PWTEXT[i] > 0x20;i++); //Scan for cr or null - PWLen=i; - - } - } - else - { - if (InitDone != &InitDone) - { - MessageBox(NULL,"BPQ32 DLL already loaded at another address","BPQ32",MB_ICONSTOP); - FreeSemaphore(&Semaphore); - return (0); - } - } - - // Run timer monitor thread in all processes - it is possible for the TImer thread not to be the first thread -SkipInit: - - _beginthread(MonitorTimerThread,0,0); - - FreeSemaphore(&Semaphore); - - AttachedPIDList[AttachedProcesses++] = GetCurrentProcessId(); - - if (_stricmp(pgm,"bpq32.exe") == 0 && AttachingProcess == 1) AttachingProcess = 0; - - GetProcess(GetCurrentProcessId(),pgm); - n=sprintf(buf,"BPQ32 DLL Attach complete - Program %s - %d Process(es) Attached\n",pgm,AttachedProcesses); - OutputDebugString(buf); - - // Set up local variables - - MCOM=1; - MTX=1; - MMASK=0xffffffff; - -// if (StartMinimized) -// if (MinimizetoTray) -// ShowWindow(FrameWnd, SW_HIDE); -// else -// ShowWindow(FrameWnd, SW_SHOWMINIMIZED); -// else -// ShowWindow(FrameWnd, SW_RESTORE); - - return 1; - - case DLL_THREAD_ATTACH: - - return 1; - - case DLL_THREAD_DETACH: - - return 1; - - case DLL_PROCESS_DETACH: - - if (_stricmp(pgm,"BPQMailChat.exe") == 0) - IncludesMail = FALSE; - - if (_stricmp(pgm,"BPQChat.exe") == 0) - IncludesChat = FALSE; - - ProcessID=GetCurrentProcessId(); - - Debugprintf("BPQ32 Process %d Detaching", ProcessID); - - // Release any streams that the app has failed to release - - for (i=1;i<65;i++) - { - if (BPQHOSTVECTOR[i-1].STREAMOWNER == ProcessID) - { - // If connected, disconnect - - SessionControl(i, 2, 0); - DeallocateStream(i); - } - } - - // Remove any Tray Icon Entries - - for( i = 0; i < 100; ++i ) - { - if (PIDArray[i] == ProcessID) - { - char Log[80]; - hWndArray[i] = 0; - sprintf(Log,"BPQ32 Removing Tray Item %s\n", PopupText[i]); - OutputDebugString(Log); - DeleteMenu(trayMenu,TRAYBASEID+i,MF_BYCOMMAND); - } - } - - if (Mutex) CloseHandle(Mutex); - - // Remove our entry from PID List - - for (i=0; i< AttachedProcesses; i++) - if (AttachedPIDList[i] == ProcessID) - break; - - for (; i< AttachedProcesses; i++) - { - AttachedPIDList[i]=AttachedPIDList[i+1]; - } - - AttachedProcesses--; - - if (TimerInst == ProcessID) - { - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - - OutputDebugString("BPQ32 Process with Timer closing\n"); - - // Call Port Close Routines - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR && PORTVEC->DLLhandle == NULL) // Don't call if real .dll - it's not there! - { - SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); // Close External Ports - } - } - - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - - IPClose(); - PMClose(); - APRSClose(); - Rig_Close(); - CloseTNCEmulator(); - if (AGWActive) - AGWAPITerminate(); - - upnpClose(); - - WSACleanup(); - WSAGetLastError(); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - if (hConsWnd) DestroyWindow(hConsWnd); - - KillTimer(NULL,TimerHandle); - TimerHandle=0; - TimerInst=0xffffffff; - - if (AttachedProcesses && Closing == FALSE && AttachingProcess == 0) // Other processes - { - OutputDebugString("BPQ32 Reloading BPQ32.exe\n"); - StartBPQ32(); - } - } - else - { - // Not Timer Process - - if (AttachedProcesses == 1 && CloseLast) // Only bpq32.exe left - { - Debugprintf("Only BPQ32.exe running - close it"); - CloseAllNeeded = TRUE; - } - } - - if (AttachedProcesses < 2) - { - if (AUTOSAVE == 1) - SaveNodes(); - if (AUTOSAVEMH) - SaveMH(); - - if (needAIS) - SaveAIS(); - } - if (AttachedProcesses == 0) - { - Closing = TRUE; - KillTimer(NULL,TimerHandle); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - // Unload External Drivers - - { - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10 && PORTVEC->DLLhandle) - FreeLibrary(PORTVEC->DLLhandle); - - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - } - } - - GetProcess(GetCurrentProcessId(),pgm); - n=sprintf(buf,"BPQ32 DLL Detach complete - Program %s - %d Process(es) Attached\n",pgm,AttachedProcesses); - OutputDebugString(buf); - - return 1; - } - return 1; -} - -DllExport int APIENTRY CloseBPQ32() -{ - // Unload External Drivers - - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - int i; - int ProcessID = GetCurrentProcessId(); - - if (Semaphore.Flag == 1 && ProcessID == Semaphore.SemProcessID) - { - OutputDebugString("BPQ32 Process holding Semaphore called CloseBPQ32 - attempting recovery\r\n"); - Debugprintf("Last Sem Call %d %x %x %x %x %x %x", SemHeldByAPI, - Sem_eax, Sem_ebx, Sem_ecx, Sem_edx, Sem_esi, Sem_edi); - - Semaphore.Flag = 0; - SemHeldByAPI = 0; - } - - if (TimerInst == ProcessID) - { - OutputDebugString("BPQ32 Process with Timer called CloseBPQ32\n"); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); - } - } - PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL); - - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - KillTimer(NULL,TimerHandle); - TimerHandle=0; - TimerInst=0xffffffff; - - IPClose(); - PMClose(); - APRSClose(); - Rig_Close(); - if (AGWActive) - AGWAPITerminate(); - - upnpClose(); - - CloseTNCEmulator(); - WSACleanup(); - - if (hConsWnd) DestroyWindow(hConsWnd); - - Debugprintf("AttachedProcesses %d ", AttachedProcesses); - - if (AttachedProcesses > 1 && Closing == FALSE && AttachingProcess == 0) // Other processes - { - OutputDebugString("BPQ32 Reloading BPQ32.exe\n"); - StartBPQ32(); - } - } - - return 0; -} - -BOOL CopyReg(HKEY hKeyIn, HKEY hKeyOut); - -VOID SetupBPQDirectory() -{ - HKEY hKey = 0; - HKEY hKeyIn = 0; - HKEY hKeyOut = 0; - int disp; - int retCode,Type,Vallen=MAX_PATH,i; - char msg[512]; - char ValfromReg[MAX_PATH] = ""; - char DLLName[256]="Not Known"; - char LogDir[256]; - char Time[64]; - -/* -•NT4 was/is '4' -•Win 95 is 4.00.950 -•Win 98 is 4.10.1998 -•Win 98 SE is 4.10.2222 -•Win ME is 4.90.3000 -•2000 is NT 5.0.2195 -•XP is actually 5.1 -•Vista is 6.0 -•Win7 is 6.1 - - i = _osver; / Build - i = _winmajor; - i = _winminor; -*/ -/* -#pragma warning(push) -#pragma warning(disable : 4996) - -if (_winver < 0x0600) -#pragma warning(pop) - { - // Below Vista - - REGTREE = HKEY_LOCAL_MACHINE; - strcpy(REGTREETEXT, "HKEY_LOCAL_MACHINE"); - ValfromReg[0] = 0; - } - else -*/ - { - if (_stricmp(pgm, "regsvr32.exe") == 0) - { - Debugprintf("BPQ32 loaded by regsvr32.exe - Registry not copied"); - } - else - { - // If necessary, move reg from HKEY_LOCAL_MACHINE to HKEY_CURRENT_USER - - retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_READ, - &hKeyIn); - - retCode = RegCreateKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\G8BPQ\\BPQ32", 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKeyOut, &disp); - - // See if Version Key exists in HKEY_CURRENT_USER - if it does, we have already done the copy - - Vallen = MAX_PATH; - retCode = RegQueryValueEx(hKeyOut, "Version" ,0 , &Type,(UCHAR *)&msg, &Vallen); - - if (retCode != ERROR_SUCCESS) - if (hKeyIn) - CopyReg(hKeyIn, hKeyOut); - - RegCloseKey(hKeyIn); - RegCloseKey(hKeyOut); - } - } - - GetModuleFileName(hInstance,DLLName,256); - - BPQDirectory[0]=0; - - retCode = RegOpenKeyEx (REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (retCode == ERROR_SUCCESS) - { - // Try "BPQ Directory" - - Vallen = MAX_PATH; - retCode = RegQueryValueEx(hKey,"BPQ Directory",0, - &Type,(UCHAR *)&ValfromReg,&Vallen); - - if (retCode == ERROR_SUCCESS) - { - if (strlen(ValfromReg) == 2 && ValfromReg[0] == '"' && ValfromReg[1] == '"') - ValfromReg[0]=0; - } - - if (ValfromReg[0] == 0) - { - // BPQ Directory absent or = "" - try "Config File Location" - - Vallen = MAX_PATH; - - retCode = RegQueryValueEx(hKey,"Config File Location",0, - &Type,(UCHAR *)&ValfromReg,&Vallen); - - if (retCode == ERROR_SUCCESS) - { - if (strlen(ValfromReg) == 2 && ValfromReg[0] == '"' && ValfromReg[1] == '"') - ValfromReg[0]=0; - } - } - - if (ValfromReg[0] == 0) GetCurrentDirectory(MAX_PATH, ValfromReg); - - // Get StartMinimized and MinimizetoTray flags - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Start Minimized", 0, &Type, (UCHAR *)&StartMinimized, &Vallen); - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Minimize to Tray", 0, &Type, (UCHAR *)&MinimizetoTray, &Vallen); - - ExpandEnvironmentStrings(ValfromReg, BPQDirectory, MAX_PATH); - - // Also get "BPQ Program Directory" - - ValfromReg[0] = 0; - Vallen = MAX_PATH; - - retCode = RegQueryValueEx(hKey, "BPQ Program Directory",0 , &Type, (UCHAR *)&ValfromReg, &Vallen); - - if (retCode == ERROR_SUCCESS) - ExpandEnvironmentStrings(ValfromReg, BPQProgramDirectory, MAX_PATH); - - // And Log Directory - - ValfromReg[0] = 0; - Vallen = MAX_PATH; - - retCode = RegQueryValueEx(hKey, "Log Directory",0 , &Type, (UCHAR *)&ValfromReg, &Vallen); - - if (retCode == ERROR_SUCCESS) - ExpandEnvironmentStrings(ValfromReg, LogDirectory, MAX_PATH); - - RegCloseKey(hKey); - } - - if (LogDirectory[0] == 0) - strcpy(LogDirectory, BPQDirectory); - - if (BPQProgramDirectory[0] == 0) - strcpy(BPQProgramDirectory, BPQDirectory); - - sprintf(msg,"BPQ32 Ver %s Loaded from: %s by %s\n", VersionString, DLLName, pgm); - WritetoConsole(msg); - OutputDebugString(msg); - FormatTime3(Time, time(NULL)); - sprintf(msg,"Loaded %s\n", Time); - WritetoConsole(msg); - OutputDebugString(msg); - -#pragma warning(push) -#pragma warning(disable : 4996) - -#if _MSC_VER >= 1400 - -#define _winmajor 6 -#define _winminor 0 - -#endif - - i=sprintf(msg,"Windows Ver %d.%d, Using Registry Key %s\n" ,_winmajor, _winminor, REGTREETEXT); - -#pragma warning(pop) - - WritetoConsole(msg); - OutputDebugString(msg); - - i=sprintf(msg,"BPQ32 Using config from: %s\n\n",BPQDirectory); - WritetoConsole(&msg[6]); - msg[i-1]=0; - OutputDebugString(msg); - - // Don't write the Version Key if loaded by regsvr32.exe (Installer is running with Admin rights, - // so will write the wrong tree on ) - - if (_stricmp(pgm, "regsvr32.exe") == 0) - { - Debugprintf("BPQ32 loaded by regsvr32.exe - Version String not written"); - } - else - { - retCode = RegCreateKeyEx(REGTREE, "SOFTWARE\\G8BPQ\\BPQ32", 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - sprintf(msg,"%d,%d,%d,%d", Ver[0], Ver[1], Ver[2], Ver[3]); - retCode = RegSetValueEx(hKey, "Version",0, REG_SZ,(BYTE *)msg, strlen(msg) + 1); - - RegCloseKey(hKey); - } - - // Make sure Logs Directory exists - - sprintf(LogDir, "%s/Logs", LogDirectory); - - CreateDirectory(LogDir, NULL); - - return; -} - -HANDLE OpenConfigFile(char *fn) -{ - HANDLE handle; - UCHAR Value[MAX_PATH]; - FILETIME LastWriteTime; - SYSTEMTIME Time; - char Msg[256]; - - - // If no directory, use current - if (BPQDirectory[0] == 0) - { - strcpy(Value,fn); - } - else - { - strcpy(Value,BPQDirectory); - strcat(Value,"\\"); - strcat(Value,fn); - } - - handle = CreateFile(Value, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - GetFileTime(handle, NULL, NULL, &LastWriteTime); - FileTimeToSystemTime(&LastWriteTime, &Time); - - sprintf(Msg,"BPQ32 Config File %s Created %.2d:%.2d %d/%.2d/%.2d\n", Value, - Time.wHour, Time.wMinute, Time.wYear, Time.wMonth, Time.wDay); - - OutputDebugString(Msg); - - return(handle); -} - -#ifdef _WIN64 -int BPQHOSTAPI() -{ - return 0; -} -#endif - - -DllExport int APIENTRY GETBPQAPI() -{ - return (int)BPQHOSTAPI; -} - -//DllExport UINT APIENTRY GETMONDECODE() -//{ -// return (UINT)MONDECODE; -//} - - -DllExport INT APIENTRY BPQAPI(int Fn, char * params) -{ - -/* -; -; BPQ HOST MODE SUPPORT CODE -; -; 22/11/95 -; -; MOVED FROM TNCODE.ASM COS CONITIONALS WERE GETTING TOO COMPLICATED -; (OS2 VERSION HAD UPSET KANT VERISON -; -; -*/ - - -/* - - BPQHOSTPORT: -; -; SPECIAL INTERFACE, MAINLY FOR EXTERNAL HOST MODE SUPPORT PROGS -; -; COMMANDS SUPPORTED ARE -; -; AH = 0 Get node/switch version number and description. On return -; AH='B',AL='P',BH='Q',BL=' ' -; DH = major version number and DL = minor version number. -; -; -; AH = 1 Set application mask to value in DL (or even DX if 16 -; applications are ever to be supported). -; -; Set application flag(s) to value in CL (or CX). -; whether user gets connected/disconnected messages issued -; by the node etc. -; -; -; AH = 2 Send frame in ES:SI (length CX) -; -; -; AH = 3 Receive frame into buffer at ES:DI, length of frame returned -; in CX. BX returns the number of outstanding frames still to -; be received (ie. after this one) or zero if no more frames -; (ie. this is last one). -; -; -; -; AH = 4 Get stream status. Returns: -; -; CX = 0 if stream disconnected or CX = 1 if stream connected -; DX = 0 if no change of state since last read, or DX = 1 if -; the connected/disconnected state has changed since -; last read (ie. delta-stream status). -; -; -; -; AH = 6 Session control. -; -; CX = 0 Conneect - _APPLMASK in DL -; CX = 1 connect -; CX = 2 disconnect -; CX = 3 return user to node -; -; -; AH = 7 Get buffer counts for stream. Returns: -; -; AX = number of status change messages to be received -; BX = number of frames queued for receive -; CX = number of un-acked frames to be sent -; DX = number of buffers left in node -; SI = number of trace frames queued for receive -; -;AH = 8 Port control/information. Called with a stream number -; in AL returns: -; -; AL = Radio port on which channel is connected (or zero) -; AH = SESSION TYPE BITS -; BX = L2 paclen for the radio port -; CX = L2 maxframe for the radio port -; DX = L4 window size (if L4 circuit, or zero) -; ES:DI = CALLSIGN - -;AH = 9 Fetch node/application callsign & alias. AL = application -; number: -; -; 0 = node -; 1 = BBS -; 2 = HOST -; 3 = SYSOP etc. etc. -; -; Returns string with alias & callsign or application name in -; user's buffer pointed to by ES:SI length CX. For example: -; -; "WORCS:G8TIC" or "TICPMS:G8TIC-10". -; -; -; AH = 10 Unproto transmit frame. Data pointed to by ES:SI, of -; length CX, is transmitted as a HDLC frame on the radio -; port (not stream) in AL. -; -; -; AH = 11 Get Trace (RAW Data) Frame into ES:DI, -; Length to CX, Timestamp to AX -; -; -; AH = 12 Update Switch. At the moment only Beacon Text may be updated -; DX = Function -; 1=update BT. ES:SI, Len CX = Text -; 2=kick off nodes broadcast -; -; AH = 13 Allocate/deallocate stream -; If AL=0, return first free stream -; If AL>0, CL=1, Allocate stream. If aleady allocated, -; return CX nonzero, else allocate, and return CX=0 -; If AL>0, CL=2, Release stream -; -; -; AH = 14 Internal Interface for IP Router -; -; Send frame - to NETROM L3 if DL=0 -; to L2 Session if DL<>0 -; -; -; AH = 15 Get interval timer - - -*/ - - - switch(Fn) - { - - case CHECKLOADED: - - params[0]=MAJORVERSION; - params[1]=MINORVERSION; - params[2]=QCOUNT; - - return (1); - } - return 0; -} - -DllExport int APIENTRY InitSwitch() -{ - return (0); -} - -/*DllExport int APIENTRY SwitchTimer() -{ - GetSemaphore((&Semaphore); - - TIMERINTERRUPT(); - - FreeSemaphore(&Semaphore); - - return (0); -} -*/ -DllExport int APIENTRY GetFreeBuffs() -{ -// Returns number of free buffers -// (BPQHOST function 7 (part)). - return (QCOUNT); -} - -DllExport UCHAR * APIENTRY GetNodeCall() -{ - return (&MYNODECALL); -} - - -DllExport UCHAR * APIENTRY GetNodeAlias() -{ - return (&MYALIASTEXT[0]); -} - -DllExport UCHAR * APIENTRY GetBBSCall() -{ - return (UCHAR *)(&APPLCALLTABLE[0].APPLCALL_TEXT); -} - - -DllExport UCHAR * APIENTRY GetBBSAlias() -{ - return (UCHAR *)(&APPLCALLTABLE[0].APPLALIAS_TEXT); -} - -DllExport VOID APIENTRY GetApplCallVB(int Appl, char * ApplCall) -{ - if (Appl < 1 || Appl > NumberofAppls ) return; - - strncpy(ApplCall,(char *)&APPLCALLTABLE[Appl-1].APPLCALL_TEXT, 10); -} - -BOOL UpdateNodesForApp(int Appl); - -DllExport BOOL APIENTRY SetApplCall(int Appl, char * NewCall) -{ - char Call[10]=" "; - int i; - - if (Appl < 1 || Appl > NumberofAppls ) return FALSE; - - i=strlen(NewCall); - - if (i > 10) i=10; - - strncpy(Call,NewCall,i); - - strncpy((char *)&APPLCALLTABLE[Appl-1].APPLCALL_TEXT,Call,10); - - if (!ConvToAX25(Call,APPLCALLTABLE[Appl-1].APPLCALL)) return FALSE; - - UpdateNodesForApp(Appl); - - return TRUE; - -} - -DllExport BOOL APIENTRY SetApplAlias(int Appl, char * NewCall) -{ - char Call[10]=" "; - int i; - - if (Appl < 1 || Appl > NumberofAppls ) return FALSE; - - i=strlen(NewCall); - - if (i > 10) i=10; - - strncpy(Call,NewCall,i); - - strncpy((char *)&APPLCALLTABLE[Appl-1].APPLALIAS_TEXT,Call,10); - - if (!ConvToAX25(Call,APPLCALLTABLE[Appl-1].APPLALIAS)) return FALSE; - - UpdateNodesForApp(Appl); - - return TRUE; - -} - - - -DllExport BOOL APIENTRY SetApplQual(int Appl, int NewQual) -{ - if (Appl < 1 || Appl > NumberofAppls ) return FALSE; - - APPLCALLTABLE[Appl-1].APPLQUAL=NewQual; - - UpdateNodesForApp(Appl); - - return TRUE; - -} - - -BOOL UpdateNodesForApp(int Appl) -{ - int App=Appl-1; - int DestLen = sizeof (struct DEST_LIST); - int n = MAXDESTS; - - struct DEST_LIST * DEST = APPLCALLTABLE[App].NODEPOINTER; - APPLCALLS * APPL=&APPLCALLTABLE[App]; - - if (DEST == NULL) - { - // No dest at the moment. If we have valid call and Qual, create an entry - - if (APPLCALLTABLE[App].APPLQUAL == 0) return FALSE; - - if (APPLCALLTABLE[App].APPLCALL[0] < 41) return FALSE; - - - GetSemaphore(&Semaphore, 5); - - DEST = DESTS; - - while (n--) - { - if (DEST->DEST_CALL[0] == 0) // Spare - break; - } - - if (n == 0) - { - // no dests - - FreeSemaphore(&Semaphore); - return FALSE; - } - - NUMBEROFNODES++; - APPL->NODEPOINTER = DEST; - - memmove (DEST->DEST_CALL,APPL->APPLCALL,13); - - DEST->DEST_STATE=0x80; // SPECIAL ENTRY - - DEST->NRROUTE[0].ROUT_QUALITY = (BYTE)APPL->APPLQUAL; - DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; - - FreeSemaphore(&Semaphore); - - return TRUE; - } - - // We have a destination. If Quality is zero, remove it, else update it - - if (APPLCALLTABLE[App].APPLQUAL == 0) - { - GetSemaphore(&Semaphore, 6); - - REMOVENODE(DEST); // Clear buffers, Remove from Sorted Nodes chain, and zap entry - - APPL->NODEPOINTER=NULL; - - FreeSemaphore(&Semaphore); - return FALSE; - - } - - if (APPLCALLTABLE[App].APPLCALL[0] < 41) return FALSE; - - GetSemaphore(&Semaphore, 7); - - memmove (DEST->DEST_CALL,APPL->APPLCALL,13); - - DEST->DEST_STATE=0x80; // SPECIAL ENTRY - - DEST->NRROUTE[0].ROUT_QUALITY = (BYTE)APPL->APPLQUAL; - DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; - - FreeSemaphore(&Semaphore); - return TRUE; - -} - - -DllExport UCHAR * APIENTRY GetSignOnMsg() -{ - return (&SIGNONMSG[0]); -} - - -DllExport HKEY APIENTRY GetRegistryKey() -{ - return REGTREE; -} - -DllExport char * APIENTRY GetRegistryKeyText() -{ - return REGTREETEXT;; -} - -DllExport UCHAR * APIENTRY GetBPQDirectory() -{ - while (BPQDirectory[0] == 0) - { - Debugprintf("BPQ Directory not set up - waiting"); - Sleep(1000); - } - return (&BPQDirectory[0]); -} - -DllExport UCHAR * APIENTRY GetProgramDirectory() -{ - return (&BPQProgramDirectory[0]); -} - -DllExport UCHAR * APIENTRY GetLogDirectory() -{ - return (&LogDirectory[0]); -} - -// Version for Visual Basic - -DllExport char * APIENTRY CopyBPQDirectory(char * dir) -{ - return (strcpy(dir,BPQDirectory)); -} - -DllExport int APIENTRY GetMsgPerl(int stream, char * msg) -{ - int len,count; - - GetMsg(stream, msg, &len, &count ); - - return len; -} - -int Rig_Command(int Session, char * Command); - -BOOL Rig_CommandInt(int Session, char * Command) -{ - return Rig_Command(Session, Command); -} - -DllExport int APIENTRY BPQSetHandle(int Stream, HWND hWnd) -{ - BPQHOSTVECTOR[Stream-1].HOSTHANDLE=hWnd; - return (0); -} - -#define L4USER 0 - -BPQVECSTRUC * PORTVEC ; - -VOID * InitializeExtDriver(PEXTPORTDATA PORTVEC) -{ - HINSTANCE ExtDriver=0; - char msg[128]; - int err=0; - HKEY hKey=0; - UCHAR Value[MAX_PATH]; - - // If no directory, use current - - if (BPQDirectory[0] == 0) - { - strcpy(Value,PORTVEC->PORT_DLL_NAME); - } - else - { - strcpy(Value,BPQDirectory); - strcat(Value,"\\"); - strcat(Value,PORTVEC->PORT_DLL_NAME); - } - - // Several Drivers are now built into bpq32.dll - - _strupr(Value); - - if (strstr(Value, "BPQVKISS")) - return VCOMExtInit; - - if (strstr(Value, "BPQAXIP")) - return AXIPExtInit; - - if (strstr(Value, "BPQETHER")) - return ETHERExtInit; - - if (strstr(Value, "BPQTOAGW")) - return AGWExtInit; - - if (strstr(Value, "AEAPACTOR")) - return AEAExtInit; - - if (strstr(Value, "HALDRIVER")) - return HALExtInit; - - if (strstr(Value, "KAMPACTOR")) - return KAMExtInit; - - if (strstr(Value, "SCSPACTOR")) - return SCSExtInit; - - if (strstr(Value, "WINMOR")) - return WinmorExtInit; - - if (strstr(Value, "V4")) - return V4ExtInit; - - if (strstr(Value, "TELNET")) - return TelnetExtInit; - -// if (strstr(Value, "SOUNDMODEM")) -// return SoundModemExtInit; - - if (strstr(Value, "SCSTRACKER")) - return TrackerExtInit; - - if (strstr(Value, "TRKMULTI")) - return TrackerMExtInit; - - if (strstr(Value, "UZ7HO")) - return UZ7HOExtInit; - - if (strstr(Value, "MULTIPSK")) - return MPSKExtInit; - - if (strstr(Value, "FLDIGI")) - return FLDigiExtInit; - - if (strstr(Value, "UIARQ")) - return UIARQExtInit; - -// if (strstr(Value, "BAYCOM")) -// return (UINT) BaycomExtInit; - - if (strstr(Value, "VARA")) - return VARAExtInit; - - if (strstr(Value, "ARDOP")) - return ARDOPExtInit; - - if (strstr(Value, "SERIAL")) - return SerialExtInit; - - if (strstr(Value, "KISSHF")) - return KISSHFExtInit; - - if (strstr(Value, "WINRPR")) - return WinRPRExtInit; - - if (strstr(Value, "HSMODEM")) - return HSMODEMExtInit; - - if (strstr(Value, "FREEDATA")) - return FreeDataExtInit; - - ExtDriver = LoadLibrary(Value); - - if (ExtDriver == NULL) - { - err=GetLastError(); - - sprintf(msg,"Error loading Driver %s - Error code %d", - PORTVEC->PORT_DLL_NAME,err); - - MessageBox(NULL,msg,"BPQ32",MB_ICONSTOP); - - return(0); - } - - PORTVEC->DLLhandle=ExtDriver; - - return (GetProcAddress(ExtDriver,"_ExtInit@4")); - -} - -/* -_DATABASE LABEL BYTE - -FILLER DB 14 DUP (0) ; PROTECTION AGENST BUFFER PROBLEMS! - DB MAJORVERSION,MINORVERSION -_NEIGHBOURS DD 0 - DW TYPE ROUTE -_MAXNEIGHBOURS DW 20 ; MAX ADJACENT NODES - -_DESTS DD 0 ; NODE LIST - DW TYPE DEST_LIST -MAXDESTS DW 100 ; MAX NODES IN SYSTEM -*/ - - -DllExport int APIENTRY GetAttachedProcesses() -{ - return (AttachedProcesses); -} - -DllExport int * APIENTRY GetAttachedProcessList() -{ - return (&AttachedPIDList[0]); -} - -DllExport int * APIENTRY SaveNodesSupport() -{ - return (&DATABASESTART); -} - -// -// Internal BPQNODES support -// - -#define UCHAR unsigned char - -/* -ROUTE ADD G1HTL-1 2 200 0 0 0 -ROUTE ADD G4IRX-3 2 200 0 0 0 -NODE ADD MAPPLY:G1HTL-1 G1HTL-1 2 200 G4IRX-3 2 98 -NODE ADD NOT:GB7NOT G1HTL-1 2 199 G4IRX-3 2 98 - -*/ - -struct DEST_LIST * Dests; -struct ROUTE * Routes; - -int MaxNodes; -int MaxRoutes; -int NodeLen; -int RouteLen; - -int count; -int cursor; - -int len,i; - -ULONG cnt; -char Normcall[10]; -char Portcall[10]; -char Alias[7]; - -char line[100]; - -HANDLE handle; - -int APIENTRY Restart() -{ - int i, Count = AttachedProcesses; - HANDLE hProc; - DWORD PID; - - for (i = 0; i < Count; i++) - { - PID = AttachedPIDList[i]; - - // Kill Timer Owner last - - if (TimerInst != PID) - { - hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID); - - if (hProc) - { - TerminateProcess(hProc, 0); - CloseHandle(hProc); - } - } - } - - hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, TimerInst); - - if (hProc) - { - TerminateProcess(hProc, 0); - CloseHandle(hProc); - } - - - return 0; -} - -int APIENTRY Reboot() -{ - // Run shutdown -r -f - - STARTUPINFO SInfo; - PROCESS_INFORMATION PInfo; - char Cmd[] = "shutdown -r -f"; - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - return CreateProcess(NULL, Cmd, NULL, NULL, FALSE,0 ,NULL ,NULL, &SInfo, &PInfo); -} -/* -int APIENTRY Reconfig() -{ - if (!ProcessConfig()) - { - return (0); - } - SaveNodes(); - WritetoConsole("Nodes Saved\n"); - ReconfigFlag=TRUE; - WritetoConsole("Reconfig requested ... Waiting for Timer Poll\n"); - return 1; -} -*/ -// Code to support minimizing all BPQ Apps to a single Tray ICON - -// As we can't minimize the console window to the tray, I'll use an ordinary -// window instead. This also gives me somewhere to post the messages to - - -char AppName[] = "BPQ32"; -char Title[80] = "BPQ32.dll Console"; - -int NewLine(); - -char FrameClassName[] = TEXT("MdiFrame"); - -HWND ClientWnd; //This stores the MDI client area window handle - -LOGFONT LFTTYFONT ; - -HFONT hFont ; - -HMENU hPopMenu, hWndMenu; -HMENU hMainFrameMenu = NULL; -HMENU hBaseMenu = NULL; -HMENU hConsMenu = NULL; -HMENU hTermMenu = NULL; -HMENU hMonMenu = NULL; -HMENU hTermActMenu, hTermCfgMenu, hTermEdtMenu, hTermHlpMenu; -HMENU hMonActMenu, hMonCfgMenu, hMonEdtMenu, hMonHlpMenu; - - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - -DllExport int APIENTRY DeleteTrayMenuItem(HWND hWnd); - -#define BPQMonitorAvail 1 -#define BPQDataAvail 2 -#define BPQStateChange 4 - -VOID GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value); -SOCKET OpenWL2KHTTPSock(); -SendHTTPRequest(SOCKET sock, char * Request, char * Params, int Len, char * Return); - -BOOL GetWL2KSYSOPInfo(char * Call, char * _REPLYBUFFER); -BOOL UpdateWL2KSYSOPInfo(char * Call, char * SQL); - - -static INT_PTR CALLBACK ConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_INITDIALOG: - { - char _REPLYBUFFER[1000] = ""; - char Value[1000]; - - if (GetWL2KSYSOPInfo(WL2KCall, _REPLYBUFFER)) - { -// if (strstr(_REPLYBUFFER, "\"ErrorMessage\":") == 0) - - GetJSONValue(_REPLYBUFFER, "\"SysopName\":", Value); - SetDlgItemText(hDlg, NAME, Value); - - GetJSONValue(_REPLYBUFFER, "\"GridSquare\":", Value); - SetDlgItemText(hDlg, IDC_Locator, Value); - - GetJSONValue(_REPLYBUFFER, "\"StreetAddress1\":", Value); - SetDlgItemText(hDlg, ADDR1, Value); - - GetJSONValue(_REPLYBUFFER, "\"StreetAddress2\":", Value); - SetDlgItemText(hDlg, ADDR2, Value); - - GetJSONValue(_REPLYBUFFER, "\"City\":", Value); - SetDlgItemText(hDlg, CITY, Value); - - GetJSONValue(_REPLYBUFFER, "\"State\":", Value); - SetDlgItemText(hDlg, STATE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Country\":", Value); - SetDlgItemText(hDlg, COUNTRY, Value); - - GetJSONValue(_REPLYBUFFER, "\"PostalCode\":", Value); - SetDlgItemText(hDlg, POSTCODE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Email\":", Value); - SetDlgItemText(hDlg, EMAIL, Value); - - GetJSONValue(_REPLYBUFFER, "\"Website\":", Value); - SetDlgItemText(hDlg, WEBSITE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Phones\":", Value); - SetDlgItemText(hDlg, PHONE, Value); - - GetJSONValue(_REPLYBUFFER, "\"Comments\":", Value); - SetDlgItemText(hDlg, ADDITIONALDATA, Value); - - } - - return (INT_PTR)TRUE; - } - case WM_COMMAND: - - switch(LOWORD(wParam)) - { - - case ID_SAVE: - { - char Name[100]; - char PasswordText[100]; - char LocatorText[100]; - char Addr1[100]; - char Addr2[100]; - char City[100]; - char State[100]; - char Country[100]; - char PostCode[100]; - char Email[100]; - char Website[100]; - char Phone[100]; - char Data[100]; - - SOCKET sock; - - int Len; - char Message[2048]; - char Reply[2048] = ""; - - - GetDlgItemText(hDlg, NAME, Name, 99); - GetDlgItemText(hDlg, IDC_Password, PasswordText, 99); - GetDlgItemText(hDlg, IDC_Locator, LocatorText, 99); - GetDlgItemText(hDlg, ADDR1, Addr1, 99); - GetDlgItemText(hDlg, ADDR2, Addr2, 99); - GetDlgItemText(hDlg, CITY, City, 99); - GetDlgItemText(hDlg, STATE, State, 99); - GetDlgItemText(hDlg, COUNTRY, Country, 99); - GetDlgItemText(hDlg, POSTCODE, PostCode, 99); - GetDlgItemText(hDlg, EMAIL, Email, 99); - GetDlgItemText(hDlg, WEBSITE, Website, 99); - GetDlgItemText(hDlg, PHONE, Phone, 99); - GetDlgItemText(hDlg, ADDITIONALDATA, Data, 99); - - -//{"Callsign":"String","GridSquare":"String","SysopName":"String", -//"StreetAddress1":"String","StreetAddress2":"String","City":"String", -//"State":"String","Country":"String","PostalCode":"String","Email":"String", -//"Phones":"String","Website":"String","Comments":"String"} - - Len = sprintf(Message, - "\"Callsign\":\"%s\"," - "\"Password\":\"%s\"," - "\"GridSquare\":\"%s\"," - "\"SysopName\":\"%s\"," - "\"StreetAddress1\":\"%s\"," - "\"StreetAddress2\":\"%s\"," - "\"City\":\"%s\"," - "\"State\":\"%s\"," - "\"Country\":\"%s\"," - "\"PostalCode\":\"%s\"," - "\"Email\":\"%s\"," - "\"Phones\":\"%s\"," - "\"Website\":\"%s\"," - "\"Comments\":\"%s\"", - - WL2KCall, PasswordText, LocatorText, Name, Addr1, Addr2, City, State, Country, PostCode, Email, Phone, Website, Data); - - Debugprintf("Sending %s", Message); - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - char * ptr; - - SendHTTPRequest(sock, - "/sysop/add", Message, Len, Reply); - - ptr = strstr(Reply, "\"ErrorCode\":"); - - if (ptr) - { - ptr = strstr(ptr, "Message"); - if (ptr) - { - ptr += 10; - strlop(ptr, '"'); - MessageBox(NULL ,ptr, "Error", MB_OK); - } - } - else - MessageBox(NULL, "Sysop Record Updated", "BPQ32", MB_OK); - - } - closesocket(sock); - } - - case ID_CANCEL: - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - break; - } - } - return (INT_PTR)FALSE; -} - - - -LRESULT CALLBACK UIWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -VOID WINAPI OnTabbedDialogInit(HWND hDlg); - -LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - POINT pos; - BOOL ret; - - CLIENTCREATESTRUCT MDIClientCreateStruct; // Structure to be used for MDI client area - //HWND m_hwndSystemInformation = 0; - - if (message == BPQMsg) - { - if (lParam & BPQDataAvail) - DoReceivedData(wParam); - - if (lParam & BPQMonitorAvail) - DoMonData(wParam); - - if (lParam & BPQStateChange) - DoStateChange(wParam); - - return (0); - } - - switch (message) - { - case MY_TRAY_ICON_MESSAGE: - - switch(lParam) - { - case WM_RBUTTONUP: - case WM_LBUTTONUP: - - GetCursorPos(&pos); - - // SetForegroundWindow(FrameWnd); - - TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, FrameWnd, 0); - return 0; - } - - break; - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - case WM_SIZING: - case WM_SIZE: - - SendMessage(ClientWnd, WM_MDIICONARRANGE, 0 ,0); - break; - - case WM_NCCREATE: - - ret = DefFrameProc(hWnd, ClientWnd, message, wParam, lParam); - return TRUE; - - case WM_CREATE: - - // On creation of main frame, create the MDI client area - - MDIClientCreateStruct.hWindowMenu = NULL; - MDIClientCreateStruct.idFirstChild = IDM_FIRSTCHILD; - - ClientWnd = CreateWindow(TEXT("MDICLIENT"), // predefined value for MDI client area - NULL, // no caption required - WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, - 0, // No need to give any x/y or height/width since this client - // will just be used to get client windows created, effectively - // in the main window we will be seeing the mainframe window client area itself. - 0, - 0, - 0, - hWnd, - NULL, - hInstance, - (void *) &MDIClientCreateStruct); - - - return 0; - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - if (wmId >= TRAYBASEID && wmId < (TRAYBASEID + 100)) - { - handle=hWndArray[wmId-TRAYBASEID]; - - if (handle == FrameWnd) - ShowWindow(handle, SW_NORMAL); - - if (handle == FrameWnd && FrameMaximized == TRUE) - PostMessage(handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); - else - PostMessage(handle, WM_SYSCOMMAND, SC_RESTORE, 0); - - SetForegroundWindow(handle); - return 0; - } - - switch(wmId) - { - struct ConsoleInfo * Cinfo = NULL; - - case ID_NEWWINDOW: - Cinfo = CreateChildWindow(0, FALSE); - if (Cinfo) - SendMessage(ClientWnd, WM_MDIACTIVATE, (WPARAM)Cinfo->hConsole, 0); - break; - - case ID_WINDOWS_CASCADE: - SendMessage(ClientWnd, WM_MDICASCADE, 0, 0); - return 0; - - case ID_WINDOWS_TILE: - SendMessage(ClientWnd, WM_MDITILE , MDITILE_HORIZONTAL, 0); - return 0; - - case BPQCLOSEALL: - CloseAllPrograms(); - // SendMessage(ClientWnd, WM_MDIICONARRANGE, 0 ,0); - - return 0; - - case BPQUICONFIG: - { - int err, i=0; - char Title[80]; - WNDCLASS wc; - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = UIWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - - wc.lpszMenuName = NULL; - wc.lpszClassName = UIClassName; - - RegisterClass(&wc); - - UIhWnd = CreateDialog(hInstance, UIClassName, 0, NULL); - - if (!UIhWnd) - { - err=GetLastError(); - return FALSE; - } - - wsprintf(Title,"BPQ32 Beacon Configuration"); - MySetWindowText(UIhWnd, Title); - ShowWindow(UIhWnd, SW_NORMAL); - - OnTabbedDialogInit(UIhWnd); // Set up pages - - // UpdateWindow(UIhWnd); - return 0; - } - - - case IDD_WL2KSYSOP: - - if (WL2KCall[0] == 0) - { - MessageBox(NULL,"WL2K Reporting is not configured","BPQ32", MB_OK); - break; - } - - DialogBox(hInstance, MAKEINTRESOURCE(IDD_WL2KSYSOP), hWnd, ConfigWndProc); - break; - - - // Handle MDI Window commands - - default: - { - if(wmId >= IDM_FIRSTCHILD) - { - DefFrameProc(hWnd, ClientWnd, message, wParam, lParam); - } - else - { - HWND hChild = (HWND)SendMessage(ClientWnd, WM_MDIGETACTIVE,0,0); - - if(hChild) - SendMessage(hChild, WM_COMMAND, wParam, lParam); - } - } - } - - break; - - case WM_INITMENUPOPUP: - { - HWND hChild = (HWND)SendMessage(ClientWnd, WM_MDIGETACTIVE,0,0); - - if(hChild) - SendMessage(hChild, WM_INITMENUPOPUP, wParam, lParam); - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_MAXIMIZE: - - FrameMaximized = TRUE; - break; - - case SC_RESTORE: - - FrameMaximized = FALSE; - break; - - case SC_MINIMIZE: - - if (MinimizetoTray) - { - ShowWindow(hWnd, SW_HIDE); - return TRUE; - } - } - - return (DefFrameProc(hWnd, ClientWnd, message, wParam, lParam)); - - case WM_CLOSE: - - PostQuitMessage(0); - - if (MinimizetoTray) - DeleteTrayMenuItem(hWnd); - - break; - - default: - return (DefFrameProc(hWnd, ClientWnd, message, wParam, lParam)); - - } - return (DefFrameProc(hWnd, ClientWnd, message, wParam, lParam)); -} - -int OffsetH, OffsetW; - -int SetupConsoleWindow() -{ - WNDCLASS wc; - int i; - int retCode, Type, Vallen; - HKEY hKey=0; - char Size[80]; - WNDCLASSEX wndclassMainFrame; - RECT CRect; - - retCode = RegOpenKeyEx (REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"FrameWindowSize",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size,"%d,%d,%d,%d",&FRect.left,&FRect.right,&FRect.top,&FRect.bottom); - - if (FRect.top < - 500 || FRect.left < - 500) - { - FRect.left = 0; - FRect.top = 0; - FRect.right = 600; - FRect.bottom = 400; - } - - - Vallen=80; - retCode = RegQueryValueEx(hKey,"WindowSize",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size,"%d,%d,%d,%d,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom, &ConsoleMinimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - Vallen=80; - - retCode = RegQueryValueEx(hKey,"StatusWindowSize",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size, "%d,%d,%d,%d,%d", &StatusRect.left, &StatusRect.right, - &StatusRect.top, &StatusRect.bottom, &StatusMinimized); - - if (StatusRect.top < - 500 || StatusRect.left < - 500) - { - StatusRect.left = 0; - StatusRect.top = 0; - StatusRect.right = 850; - StatusRect.bottom = 500; - } - - - // Get StartMinimized and MinimizetoTray flags - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Start Minimized", 0, &Type, (UCHAR *)&StartMinimized, &Vallen); - - Vallen = 4; - retCode = RegQueryValueEx(hKey, "Minimize to Tray", 0, &Type, (UCHAR *)&MinimizetoTray, &Vallen); - } - - wndclassMainFrame.cbSize = sizeof(WNDCLASSEX); - wndclassMainFrame.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wndclassMainFrame.lpfnWndProc = FrameWndProc; - wndclassMainFrame.cbClsExtra = 0; - wndclassMainFrame.cbWndExtra = 0; - wndclassMainFrame.hInstance = hInstance; - wndclassMainFrame.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON)); - wndclassMainFrame.hCursor = LoadCursor(NULL, IDC_ARROW); - wndclassMainFrame.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH); - wndclassMainFrame.lpszMenuName = NULL; - wndclassMainFrame.lpszClassName = FrameClassName; - wndclassMainFrame.hIconSm = NULL; - - if(!RegisterClassEx(&wndclassMainFrame)) - { - return 0; - } - - pindex = 0; - PartLine = FALSE; - - bgBrush = CreateSolidBrush(BGCOLOUR); - -// hMainFrameMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MAINFRAME_MENU)); - - hBaseMenu = LoadMenu(hInstance, MAKEINTRESOURCE(CONS_MENU)); - hConsMenu = GetSubMenu(hBaseMenu, 1); - hWndMenu = GetSubMenu(hBaseMenu, 0); - - hTermMenu = LoadMenu(hInstance, MAKEINTRESOURCE(TERM_MENU)); - hTermActMenu = GetSubMenu(hTermMenu, 1); - hTermCfgMenu = GetSubMenu(hTermMenu, 2); - hTermEdtMenu = GetSubMenu(hTermMenu, 3); - hTermHlpMenu = GetSubMenu(hTermMenu, 4); - - hMonMenu = LoadMenu(hInstance, MAKEINTRESOURCE(MON_MENU)); - hMonCfgMenu = GetSubMenu(hMonMenu, 1); - hMonEdtMenu = GetSubMenu(hMonMenu, 2); - hMonHlpMenu = GetSubMenu(hMonMenu, 3); - - hMainFrameMenu = CreateMenu(); - AppendMenu(hMainFrameMenu, MF_STRING + MF_POPUP, (UINT)hWndMenu, "Window"); - - //Create the main MDI frame window - - ClientWnd = NULL; - - FrameWnd = CreateWindow(FrameClassName, - "BPQ32 Console", - WS_OVERLAPPEDWINDOW |WS_CLIPCHILDREN, - FRect.left, - FRect.top, - FRect.right - FRect.left, - FRect.bottom - FRect.top, - NULL, // handle to parent window - hMainFrameMenu, // handle to menu - hInstance, // handle to the instance of module - NULL); // Long pointer to a value to be passed to the window through the - // CREATESTRUCT structure passed in the lParam parameter the WM_CREATE message - - - // Get Client Params - - if (FrameWnd == 0) - { - Debugprintf("SetupConsoleWindow Create Frame failed %d", GetLastError()); - return 0; - } - - ShowWindow(FrameWnd, SW_RESTORE); - - - GetWindowRect(FrameWnd, &FRect); - OffsetH = FRect.bottom - FRect.top; - OffsetW = FRect.right - FRect.left; - GetClientRect(FrameWnd, &CRect); - OffsetH -= CRect.bottom; - OffsetW -= CRect.right; - OffsetH -= 4; - - // Create Console Window - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = 0; - wc.lpszClassName = ClassName; - - i=RegisterClass(&wc); - - sprintf (Title, "BPQ32.dll Console Version %s", VersionString); - - hConsWnd = CreateMDIWindow(ClassName, "Console", 0, - 0,0,0,0, ClientWnd, hInstance, 1234); - - i = GetLastError(); - - if (!hConsWnd) { - return (FALSE); - } - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)StatusWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(BPQICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wc.lpszMenuName = 0; - wc.lpszClassName = "Status"; - - i=RegisterClass(&wc); - - if (StatusRect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - StatusRect.top; - StatusRect.top += Error; - StatusRect.bottom += Error; - } - - StatusWnd = CreateMDIWindow("Status", "Stream Status", 0, - StatusRect.left, StatusRect.top, StatusRect.right - StatusRect.left, - StatusRect.bottom - StatusRect.top, ClientWnd, hInstance, 1234); - - SetTimer(StatusWnd, 1, 1000, NULL); - - hPopMenu = GetSubMenu(hBaseMenu, 1) ; - - if (MinimizetoTray) - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_UNCHECKED); - - if (StartMinimized) - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_UNCHECKED); - - DrawMenuBar(hConsWnd); - - // setup default font information - - LFTTYFONT.lfHeight = 12; - LFTTYFONT.lfWidth = 8 ; - LFTTYFONT.lfEscapement = 0 ; - LFTTYFONT.lfOrientation = 0 ; - LFTTYFONT.lfWeight = 0 ; - LFTTYFONT.lfItalic = 0 ; - LFTTYFONT.lfUnderline = 0 ; - LFTTYFONT.lfStrikeOut = 0 ; - LFTTYFONT.lfCharSet = 0; - LFTTYFONT.lfOutPrecision = OUT_DEFAULT_PRECIS ; - LFTTYFONT.lfClipPrecision = CLIP_DEFAULT_PRECIS ; - LFTTYFONT.lfQuality = DEFAULT_QUALITY ; - LFTTYFONT.lfPitchAndFamily = FIXED_PITCH; - lstrcpy(LFTTYFONT.lfFaceName, "FIXEDSYS" ) ; - - hFont = CreateFontIndirect(&LFTTYFONT) ; - - SetWindowText(hConsWnd,Title); - - if (Rect.right < 100 || Rect.bottom < 100) - { - GetWindowRect(hConsWnd, &Rect); - } - - if (Rect.top < OffsetH) // Make sure not off top of MDI frame - { - int Error = OffsetH - Rect.top; - Rect.top += Error; - Rect.bottom += Error; - } - - - MoveWindow(hConsWnd, Rect.left - (OffsetW /2), Rect.top - OffsetH, Rect.right-Rect.left, Rect.bottom-Rect.top, TRUE); - - MoveWindow(StatusWnd, StatusRect.left - (OffsetW /2), StatusRect.top - OffsetH, - StatusRect.right-StatusRect.left, StatusRect.bottom-StatusRect.top, TRUE); - - hWndCons = CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "", - WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | LBS_NOSEL | WS_VSCROLL | WS_HSCROLL, - Rect.left, Rect.top, Rect.right - Rect.left, Rect.bottom - Rect.top, - hConsWnd, NULL, hInstance, NULL); - -// SendMessage(hWndCons, WM_SETFONT, hFont, 0); - - SendMessage(hWndCons, LB_SETHORIZONTALEXTENT , 1000, 0); - - if (ConsoleMinimized) - ShowWindow(hConsWnd, SW_SHOWMINIMIZED); - else - ShowWindow(hConsWnd, SW_RESTORE); - - if (StatusMinimized) - ShowWindow(StatusWnd, SW_SHOWMINIMIZED); - else - ShowWindow(StatusWnd, SW_RESTORE); - - ShowWindow(FrameWnd, SW_RESTORE); - - - LoadLibrary("riched20.dll"); - - if (StartMinimized) - if (MinimizetoTray) - ShowWindow(FrameWnd, SW_HIDE); - else - ShowWindow(FrameWnd, SW_SHOWMINIMIZED); - else - ShowWindow(FrameWnd, SW_RESTORE); - - CreateMonitorWindow(Size); - - return 0; -} - -DllExport int APIENTRY SetupTrayIcon() -{ - if (MinimizetoTray == 0) - return 0; - - trayMenu = CreatePopupMenu(); - - for( i = 0; i < 100; ++i ) - { - if (strcmp(PopupText[i],"BPQ32 Console") == 0) - { - hWndArray[i] = FrameWnd; - goto doneit; - } - } - - for( i = 0; i < 100; ++i ) - { - if (hWndArray[i] == 0) - { - hWndArray[i] = FrameWnd; - strcpy(PopupText[i],"BPQ32 Console"); - break; - } - } -doneit: - - for( i = 0; i < 100; ++i ) - { - if (hWndArray[i] != 0) - AppendMenu(trayMenu,MF_STRING,TRAYBASEID+i,PopupText[i]); - } - - // Set up Tray ICON - - ZeroMemory(&niData,sizeof(NOTIFYICONDATA)); - - niData.cbSize = sizeof(NOTIFYICONDATA); - - // the ID number can be any UINT you choose and will - // be used to identify your icon in later calls to - // Shell_NotifyIcon - - niData.uID = TRAY_ICON_ID; - - // state which structure members are valid - // here you can also choose the style of tooltip - // window if any - specifying a balloon window: - // NIF_INFO is a little more complicated - - strcpy(niData.szTip,"BPQ32 Windows"); - - niData.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP; - - // load the icon note: you should destroy the icon - // after the call to Shell_NotifyIcon - - niData.hIcon = - - //LoadIcon(NULL, IDI_APPLICATION); - - (HICON)LoadImage( hInstance, - MAKEINTRESOURCE(BPQICON), - IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), - LR_DEFAULTCOLOR); - - - // set the window you want to receive event messages - - niData.hWnd = FrameWnd; - - // set the message to send - // note: the message value should be in the - // range of WM_APP through 0xBFFF - - niData.uCallbackMessage = MY_TRAY_ICON_MESSAGE; - - // Call Shell_NotifyIcon. NIM_ADD adds a new tray icon - - if (Shell_NotifyIcon(NIM_ADD,&niData)) - Debugprintf("BPQ32 Create Tray Icon Ok"); -// else -// Debugprintf("BPQ32 Create Tray Icon failed %d", GetLastError()); - - return 0; -} - -VOID SaveConfig() -{ - HKEY hKey=0; - int retCode, disp; - - retCode = RegCreateKeyEx(REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, // Reserved - 0, // Class - 0, // Options - KEY_ALL_ACCESS, - NULL, // Security Attrs - &hKey, - &disp); - - if (retCode == ERROR_SUCCESS) - { - retCode = RegSetValueEx(hKey, "Start Minimized", 0, REG_DWORD, (UCHAR *)&StartMinimized, 4); - retCode = RegSetValueEx(hKey, "Minimize to Tray", 0, REG_DWORD, (UCHAR *)&MinimizetoTray, 4); - } -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - POINT pos; - HWND handle; - RECT cRect; - - switch (message) - { - case WM_MDIACTIVATE: - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - // GetSubMenu function should retrieve a handle to the drop-down menu or submenu. - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)hConsMenu, "Actions"); - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - DrawMenuBar(FrameWnd); - - return TRUE; //DefMDIChildProc(hWnd, message, wParam, lParam); - - case MY_TRAY_ICON_MESSAGE: - - switch(lParam) - { - case WM_RBUTTONUP: - case WM_LBUTTONUP: - - GetCursorPos(&pos); - - SetForegroundWindow(hWnd); - - TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, hWnd, 0); - return 0; - } - - break; - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - if (wmId == IDC_ENIGATE) - { - int retCode, disp; - HKEY hKey=0; - - IGateEnabled = IsDlgButtonChecked(hWnd, IDC_ENIGATE); - - if (IGateEnabled) - ISDelayTimer = 60; - - retCode = RegCreateKeyEx(REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, // Reserved - 0, // Class - 0, // Options - KEY_ALL_ACCESS, - NULL, // Security Attrs - &hKey, - &disp); - - if (retCode == ERROR_SUCCESS) - { - retCode = RegSetValueEx(hKey,"IGateEnabled", 0 , REG_DWORD,(BYTE *)&IGateEnabled, 4); - RegCloseKey(hKey); - } - - return 0; - } - - if (wmId == BPQSAVENODES) - { - SaveNodes(); - WritetoConsole("Nodes Saved\n"); - return 0; - } - if (wmId == BPQCLEARRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - - ClearNodes(); - WritetoConsole("Nodes file Cleared\n"); - ReconfigFlag=TRUE; - WritetoConsole("Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - if (wmId == BPQRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - SaveNodes(); - WritetoConsole("Nodes Saved\n"); - ReconfigFlag=TRUE; - WritetoConsole("Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - - if (wmId == SCANRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - - RigReconfigFlag=TRUE; - WritetoConsole("Rigcontrol Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - - if (wmId == APRSRECONFIG) - { - if (!ProcessConfig()) - { - MessageBox(NULL,"Configuration File check falled - will continue with old config","BPQ32",MB_OK); - return (0); - } - - APRSReconfigFlag=TRUE; - WritetoConsole("APRS Reconfig requested ... Waiting for Timer Poll\n"); - return 0; - } - if (wmId == BPQDUMP) - { - DumpSystem(); - return 0; - } - - if (wmId == BPQCLOSEALL) - { - CloseAllPrograms(); - return 0; - } - - if (wmId == BPQUICONFIG) - { - int err, i=0; - char Title[80]; - WNDCLASS wc; - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = UIWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - - wc.lpszMenuName = NULL; - wc.lpszClassName = UIClassName; - - RegisterClass(&wc); - - UIhWnd = CreateDialog(hInstance, UIClassName,0,NULL); - - if (!UIhWnd) - { - err=GetLastError(); - return FALSE; - } - - wsprintf(Title,"BPQ32 Beacon Utility Version"); - MySetWindowText(UIhWnd, Title); - return 0; - } - - if (wmId == BPQSAVEREG) - { - CreateRegBackup(); - return 0; - } - - if (wmId == BPQMINTOTRAY) - { - MinimizetoTray = !MinimizetoTray; - - if (MinimizetoTray) - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQMINTOTRAY, MF_UNCHECKED); - - SaveConfig(); - return 0; - } - - if (wmId == BPQSTARTMIN) - { - StartMinimized = !StartMinimized; - - if (StartMinimized) - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_CHECKED); - else - CheckMenuItem(hPopMenu, BPQSTARTMIN, MF_UNCHECKED); - - SaveConfig(); - return 0; - } - - if (wmId >= TRAYBASEID && wmId < (TRAYBASEID + 100)) - { - handle=hWndArray[wmId-TRAYBASEID]; - - if (handle == FrameWnd && FrameMaximized == TRUE) - PostMessage(handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); - else - PostMessage(handle, WM_SYSCOMMAND, SC_RESTORE, 0); - - SetForegroundWindow(handle); - return 0; - } - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_MINIMIZE: - - ConsoleMinimized = TRUE; - break; - - case SC_RESTORE: - - ConsoleMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - - case WM_SIZE: - - GetClientRect(hWnd, &cRect); - - MoveWindow(hWndBG, 0, 0, cRect.right, 26, TRUE); - - if (APRSActive) - MoveWindow(hWndCons, 2, 26, cRect.right-4, cRect.bottom - 32, TRUE); - else - MoveWindow(hWndCons, 2, 2, cRect.right-4, cRect.bottom - 4, TRUE); - -// InvalidateRect(hWnd, NULL, TRUE); - break; - -/* - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - - hOldFont = SelectObject( hdc, hFont) ; - - for (i=0; i 300) - len = 300; - - memcpy(&buffptr[2], buff, len + 1); - - C_Q_ADD(&WritetoConsoleQ, buffptr); - - return 0; -} - -int WritetoConsoleSupport(char * buff) -{ - - int len=strlen(buff); - char Temp[2000]= ""; - char * ptr; - - if (PartLine) - { - SendMessage(hWndCons, LB_GETTEXT, pindex, (LPARAM)(LPCTSTR) Temp); - SendMessage(hWndCons, LB_DELETESTRING, pindex, 0); - PartLine = FALSE; - } - - if ((strlen(Temp) + strlen(buff)) > 1990) - Temp[0] = 0; // Should never have anything this long - - strcat(Temp, buff); - - ptr = strchr(Temp, '\n'); - - if (ptr) - *ptr = 0; - else - PartLine = TRUE; - - pindex=SendMessage(hWndCons, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR) Temp); - return 0; - } - -DllExport VOID APIENTRY BPQOutputDebugString(char * String) -{ - OutputDebugString(String); - return; - } - -HANDLE handle; -char fn[]="BPQDUMP"; -ULONG cnt; -char * stack; -//char screen[1920]; -//COORD ReadCoord; - -#define DATABYTES 400000 - -extern UCHAR DATAAREA[]; - -DllExport int APIENTRY DumpSystem() -{ - char fn[200]; - char Msg[250]; - - sprintf(fn,"%s\\BPQDUMP",BPQDirectory); - - handle = CreateFile(fn, - GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - -#ifndef _WIN64 - - _asm { - - mov stack,esp - } - - WriteFile(handle,stack,128,&cnt,NULL); -#endif - -// WriteFile(handle,Screen,MAXLINELEN*MAXSCREENLEN,&cnt,NULL); - - WriteFile(handle,DATAAREA, DATABYTES,&cnt,NULL); - - CloseHandle(handle); - - sprintf(Msg, "Dump to %s Completed\n", fn); - WritetoConsole(Msg); - - FindLostBuffers(); - - return (0); -} - -BOOLEAN CheckifBPQ32isLoaded() -{ - HANDLE Mutex; - - // See if BPQ32 is running - if we create it in the NTVDM address space by - // loading bpq32.dll it will not work. - - Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"BPQLOCKMUTEX"); - - if (Mutex == NULL) - { - if (AttachingProcess == 0) // Already starting BPQ32 - { - OutputDebugString("BPQ32 No other bpq32 programs running - Loading BPQ32.exe\n"); - StartBPQ32(); - } - return FALSE; - } - - CloseHandle(Mutex); - - return TRUE; -} - -BOOLEAN StartBPQ32() -{ - UCHAR Value[100]; - - char bpq[]="BPQ32.exe"; - char *fn=(char *)&bpq; - HKEY hKey=0; - int ret,Type,Vallen=99; - - char Errbuff[100]; - char buff[20]; - - STARTUPINFO StartupInfo; // pointer to STARTUPINFO - PROCESS_INFORMATION ProcessInformation; // pointer to PROCESS_INFORMATION - - AttachingProcess = 1; - -// Get address of BPQ Directory - - Value[0]=0; - - ret = RegOpenKeyEx (REGTREE, - "SOFTWARE\\G8BPQ\\BPQ32", - 0, - KEY_QUERY_VALUE, - &hKey); - - if (ret == ERROR_SUCCESS) - { - ret = RegQueryValueEx(hKey, "BPQ Program Directory", 0, &Type,(UCHAR *)&Value, &Vallen); - - if (ret == ERROR_SUCCESS) - { - if (strlen(Value) == 2 && Value[0] == '"' && Value[1] == '"') - Value[0]=0; - } - - - if (Value[0] == 0) - { - - // BPQ Directory absent or = "" - "try Config File Location" - - ret = RegQueryValueEx(hKey,"BPQ Directory",0, - &Type,(UCHAR *)&Value,&Vallen); - - if (ret == ERROR_SUCCESS) - { - if (strlen(Value) == 2 && Value[0] == '"' && Value[1] == '"') - Value[0]=0; - } - - } - RegCloseKey(hKey); - } - - if (Value[0] == 0) - { - strcpy(Value,fn); - } - else - { - strcat(Value,"\\"); - strcat(Value,fn); - } - - StartupInfo.cb=sizeof(StartupInfo); - StartupInfo.lpReserved=NULL; - StartupInfo.lpDesktop=NULL; - StartupInfo.lpTitle=NULL; - StartupInfo.dwFlags=0; - StartupInfo.cbReserved2=0; - StartupInfo.lpReserved2=NULL; - - if (!CreateProcess(Value,NULL,NULL,NULL,FALSE, - CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, - NULL,NULL,&StartupInfo,&ProcessInformation)) - { - ret=GetLastError(); - - _itoa(ret,buff,10); - - strcpy(Errbuff, "BPQ32 Load "); - strcat(Errbuff,Value); - strcat(Errbuff," failed "); - strcat(Errbuff,buff); - OutputDebugString(Errbuff); - AttachingProcess = 0; - return FALSE; - } - - return TRUE; -} - - -DllExport BPQVECSTRUC * APIENTRY GetIPVectorAddr() -{ - return &IPHOSTVECTOR; -} - -DllExport UINT APIENTRY GETSENDNETFRAMEADDR() -{ - return (UINT)&SENDNETFRAME; -} - -DllExport VOID APIENTRY RelBuff(VOID * Msg) -{ - UINT * pointer, * BUFF = Msg; - - if (Semaphore.Flag == 0) - Debugprintf("ReleaseBuffer called without semaphore"); - - pointer = FREE_Q; - - *BUFF =(UINT)pointer; - - FREE_Q = BUFF; - - QCOUNT++; - - return; -} - -extern int MINBUFFCOUNT; - -DllExport VOID * APIENTRY GetBuff() -{ - UINT * Temp = Q_REM(&FREE_Q); - - if (Semaphore.Flag == 0) - Debugprintf("GetBuff called without semaphore"); - - if (Temp) - { - QCOUNT--; - - if (QCOUNT < MINBUFFCOUNT) - MINBUFFCOUNT = QCOUNT; - } - - return Temp; -} - - -VOID __cdecl Debugprintf(const char * format, ...) -{ - char Mess[10000]; - va_list(arglist); - - va_start(arglist, format); - vsprintf(Mess, format, arglist); - strcat(Mess, "\r\n"); - OutputDebugString(Mess); - - return; -} - -unsigned short int compute_crc(unsigned char *buf, int txlen); - -extern SOCKADDR_IN reportdest; - -extern SOCKET ReportSocket; - -extern SOCKADDR_IN Chatreportdest; - -DllExport VOID APIENTRY SendChatReport(SOCKET ChatReportSocket, char * buff, int txlen) -{ - unsigned short int crc = compute_crc(buff, txlen); - - crc ^= 0xffff; - - buff[txlen++] = (crc&0xff); - buff[txlen++] = (crc>>8); - - sendto(ChatReportSocket, buff, txlen, 0, (LPSOCKADDR)&Chatreportdest, sizeof(Chatreportdest)); -} - -VOID CreateRegBackup() -{ - char Backup1[MAX_PATH]; - char Backup2[MAX_PATH]; - char RegFileName[MAX_PATH]; - char Msg[80]; - HANDLE handle; - int len, written; - char RegLine[300]; - -// SHELLEXECUTEINFO sei; -// STARTUPINFO SInfo; -// PROCESS_INFORMATION PInfo; - - sprintf(RegFileName, "%s\\BPQ32.reg", BPQDirectory); - - // Keep 4 Generations - - strcpy(Backup2, RegFileName); - strcat(Backup2, ".bak.3"); - - strcpy(Backup1, RegFileName); - strcat(Backup1, ".bak.2"); - - DeleteFile(Backup2); // Remove old .bak.3 - MoveFile(Backup1, Backup2); // Move .bak.2 to .bak.3 - - strcpy(Backup2, RegFileName); - strcat(Backup2, ".bak.1"); - - MoveFile(Backup2, Backup1); // Move .bak.1 to .bak.2 - - strcpy(Backup1, RegFileName); - strcat(Backup1, ".bak"); - - MoveFile(Backup1, Backup2); //Move .bak to .bak.1 - - strcpy(Backup2, RegFileName); - strcat(Backup2, ".bak"); - - CopyFile(RegFileName, Backup2, FALSE); // Copy to .bak - - handle = CreateFile(RegFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if (handle == INVALID_HANDLE_VALUE) - { - sprintf(Msg, "Failed to open Registry Save File\n"); - WritetoConsole(Msg); - return; - } - - len = sprintf(RegLine, "Windows Registry Editor Version 5.00\r\n\r\n"); - WriteFile(handle, RegLine, len, &written, NULL); - - if (SaveReg("Software\\G8BPQ\\BPQ32", handle)) - WritetoConsole("Registry Save complete\n"); - else - WritetoConsole("Registry Save failed\n"); - - CloseHandle(handle); - return ; -/* - - if (REGTREE == HKEY_LOCAL_MACHINE) // < Vista - { - sprintf(cmd, - "regedit /E \"%s\\BPQ32.reg\" %s\\Software\\G8BPQ\\BPQ32", BPQDirectory, REGTREETEXT); - - ZeroMemory(&SInfo, sizeof(SInfo)); - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0 ,NULL, NULL, &SInfo, &PInfo) == 0) - { - sprintf(Msg, "Error: CreateProcess for regedit failed 0%d\n", GetLastError() ); - WritetoConsole(Msg); - return; - } - } - else - { - - sprintf(cmd, - "/E \"%s\\BPQ32.reg\" %s\\Software\\G8BPQ\\BPQ32", BPQDirectory, REGTREETEXT); - - ZeroMemory(&sei, sizeof(sei)); - - sei.cbSize = sizeof(SHELLEXECUTEINFOW); - sei.hwnd = hWnd; - sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI; - sei.lpVerb = "runas"; - sei.lpFile = "regedit.exe"; - sei.lpParameters = cmd; - sei.nShow = SW_SHOWNORMAL; - - if (!ShellExecuteEx(&sei)) - { - sprintf(Msg, "Error: ShellExecuteEx for regedit failed %d\n", GetLastError() ); - WritetoConsole(Msg); - return; - } - } - - sprintf(Msg, "Registry Save Initiated\n", fn); - WritetoConsole(Msg); - - return ; -*/ -} - -BOOL CALLBACK EnumForCloseProc(HWND hwnd, LPARAM lParam) -{ - struct TNCINFO * TNC = (struct TNCINFO *)lParam; - UINT ProcessId; - - GetWindowThreadProcessId(hwnd, &ProcessId); - - for (i=0; i< AttachedProcesses; i++) - { - if (AttachedPIDList[i] == ProcessId) - { - Debugprintf("BPQ32 Close All Closing PID %d", ProcessId); - PostMessage(hwnd, WM_CLOSE, 1, 1); - // AttachedPIDList[i] = 0; // So we don't do it again - break; - } - } - - return (TRUE); -} -DllExport BOOL APIENTRY RestoreFrameWindow() -{ - return ShowWindow(FrameWnd, SW_RESTORE); -} - -DllExport VOID APIENTRY CreateNewTrayIcon() -{ - Shell_NotifyIcon(NIM_DELETE,&niData); - trayMenu = NULL; -} - -DllExport VOID APIENTRY CloseAllPrograms() -{ -// HANDLE hProc; - - // Close all attached BPQ32 programs - - Closing = TRUE; - - ShowWindow(FrameWnd, SW_RESTORE); - - GetWindowRect(FrameWnd, &FRect); - - SaveBPQ32Windows(); - CloseHostSessions(); - - if (AttachedProcesses == 1) - CloseBPQ32(); - - Debugprintf("BPQ32 Close All Processes %d PIDS %d %d %d %d", AttachedProcesses, AttachedPIDList[0], - AttachedPIDList[1], AttachedPIDList[2], AttachedPIDList[3]); - - if (MinimizetoTray) - Shell_NotifyIcon(NIM_DELETE,&niData); - - EnumWindows(EnumForCloseProc, (LPARAM)NULL); -} - -#define MAX_KEY_LENGTH 255 -#define MAX_VALUE_NAME 16383 -#define MAX_VALUE_DATA 65536 - -BOOL CopyReg(HKEY hKeyIn, HKEY hKeyOut) -{ - TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name - DWORD cbName; // size of name string - TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name - DWORD cchClassName = MAX_PATH; // size of class string - DWORD cSubKeys=0; // number of subkeys - DWORD cbMaxSubKey; // longest subkey size - DWORD cchMaxClass; // longest class string - DWORD cValues; // number of values for key - DWORD cchMaxValue; // longest value name - DWORD cbMaxValueData; // longest value data - DWORD cbSecurityDescriptor; // size of security descriptor - FILETIME ftLastWriteTime; // last write time - - DWORD i, retCode; - - TCHAR achValue[MAX_VALUE_NAME]; - DWORD cchValue = MAX_VALUE_NAME; - - // Get the class name and the value count. - retCode = RegQueryInfoKey( - hKeyIn, // key handle - achClass, // buffer for class name - &cchClassName, // size of class string - NULL, // reserved - &cSubKeys, // number of subkeys - &cbMaxSubKey, // longest subkey size - &cchMaxClass, // longest class string - &cValues, // number of values for this key - &cchMaxValue, // longest value name - &cbMaxValueData, // longest value data - &cbSecurityDescriptor, // security descriptor - &ftLastWriteTime); // last write time - - // Enumerate the subkeys, until RegEnumKeyEx fails. - - if (cSubKeys) - { - Debugprintf( "\nNumber of subkeys: %d\n", cSubKeys); - - for (i=0; i 76) - { - len = sprintf(RegLine, "%s\\\r\n", RegLine); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - - len = sprintf(RegLine, "%s%02x,", RegLine, Value[k]); - } - RegLine[--len] = 0x0d; - RegLine[++len] = 0x0a; - len++; - - break; - - case REG_DWORD: //( 4 ) // 32-bit number -// case REG_DWORD_LITTLE_ENDIAN: //( 4 ) // 32-bit number (same as REG_DWORD) - - memcpy(&Intval, Value, 4); - len = sprintf(RegLine, "\"%s\"=dword:%08x\r\n", achValue, Intval); - break; - - case REG_DWORD_BIG_ENDIAN: //( 5 ) // 32-bit number - break; - case REG_LINK: //( 6 ) // Symbolic Link (unicode) - break; - case REG_MULTI_SZ: //( 7 ) // Multiple Unicode strings - - len = sprintf(RegLine, "\"%s\"=hex(7):%02x,00,", achValue, Value[0]); - for (k = 1; k < ValLen; k++) - { - if (len > 76) - { - len = sprintf(RegLine, "%s\\\r\n", RegLine); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - len = 2; - } - len = sprintf(RegLine, "%s%02x,", RegLine, Value[k]); - if (len > 76) - { - len = sprintf(RegLine, "%s\\\r\n", RegLine); - WriteFile(hFile, RegLine, len, &written, NULL); - strcpy(RegLine, " "); - } - len = sprintf(RegLine, "%s00,", RegLine); - } - - RegLine[--len] = 0x0d; - RegLine[++len] = 0x0a; - len++; - break; - - case REG_RESOURCE_LIST: //( 8 ) // Resource list in the resource map - break; - case REG_FULL_RESOURCE_DESCRIPTOR: //( 9 ) // Resource list in the hardware description - break; - case REG_RESOURCE_REQUIREMENTS_LIST://( 10 ) - break; - case REG_QWORD: //( 11 ) // 64-bit number -// case REG_QWORD_LITTLE_ENDIAN: //( 11 ) // 64-bit number (same as REG_QWORD) - break; - - } - - WriteFile(hFile, RegLine, len, &written, NULL); - } - } - } - - WriteFile(hFile, "\r\n", 2, &written, NULL); - - // Enumerate the subkeys, until RegEnumKeyEx fails. - - if (cSubKeys) - { - for (i=0; i> 1; - } - - Flags=GetApplFlags(i); - - if (OneBits > 1) - sprintf(&NewScreen[(i+1)*54],"%2d%s%3d %3d %3d %03x %3x %10s%-20s", - i, flag, RXCount(i), TXCount(i), MONCount(i), Mask, Flags, callsign, - BPQHOSTVECTOR[i-1].PgmName); - else - sprintf(&NewScreen[(i+1)*54],"%2d%s%3d %3d %3d %3d %3x %10s%-20s", - i, flag, RXCount(i), TXCount(i), MONCount(i), AppNumber, Flags, callsign, - BPQHOSTVECTOR[i-1].PgmName); - - } - } - - #include "StdExcept.c" - - if (Semaphore.Flag && Semaphore.SemProcessID == GetCurrentProcessId()) - FreeSemaphore(&Semaphore); - - } - - if (memcmp(Screen, NewScreen, 33 * 108) == 0) // No Change - return 0; - - memcpy(Screen, NewScreen, 33 * 108); - InvalidateRect(StatusWnd,NULL,FALSE); - - return(0); -} - -LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - PAINTSTRUCT ps; - HDC hdc; - HFONT hOldFont ; - HGLOBAL hMem; - MINMAXINFO * mmi; - int i; - - switch (message) - { - case WM_TIMER: - - if (Semaphore.Flag == 0) - DoStatus(); - break; - - case WM_MDIACTIVATE: - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)hConsMenu, "Actions"); - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - } - else - { - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - DrawMenuBar(FrameWnd); - - return TRUE; //DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_GETMINMAXINFO: - - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = 850; - mmi->ptMaxSize.y = 500; - mmi->ptMaxTrackSize.x = 850; - mmi->ptMaxTrackSize.y = 500; - - - case WM_COMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - //Parse the menu selections: - - switch (wmId) - { - -/* - case BPQSTREAMS: - - CheckMenuItem(hMenu,BPQSTREAMS,MF_CHECKED); - CheckMenuItem(hMenu,BPQIPSTATUS,MF_UNCHECKED); - - StreamDisplay = TRUE; - - break; - - case BPQIPSTATUS: - - CheckMenuItem(hMenu,BPQSTREAMS,MF_UNCHECKED); - CheckMenuItem(hMenu,BPQIPSTATUS,MF_CHECKED); - - StreamDisplay = FALSE; - memset(Screen, ' ', 4000); - - - break; - -*/ - - case BPQCOPY: - - // - // Copy buffer to clipboard - // - hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 33*110); - - if (hMem != 0) - { - if (OpenClipboard(hWnd)) - { -// CopyScreentoBuffer(GlobalLock(hMem)); - GlobalUnlock(hMem); - EmptyClipboard(); - SetClipboardData(CF_TEXT,hMem); - CloseClipboard(); - } - else - { - GlobalFree(hMem); - } - - } - - break; - - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_MAXIMIZE: - - break; - - case SC_MINIMIZE: - - StatusMinimized = TRUE; - break; - - case SC_RESTORE: - - StatusMinimized = FALSE; - SendMessage(ClientWnd, WM_MDIRESTORE, (WPARAM)hWnd, 0); - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_PAINT: - - hdc = BeginPaint (hWnd, &ps); - - hOldFont = SelectObject( hdc, hFont) ; - - for (i=0; i<33; i++) - { - TextOut(hdc,0,i*14,&Screen[i*108],108); - } - - SelectObject( hdc, hOldFont ) ; - EndPaint (hWnd, &ps); - - break; - - case WM_DESTROY: - -// PostQuitMessage(0); - - break; - - - default: - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - } - return (0); -} - -VOID SaveMDIWindowPos(HWND hWnd, char * RegKey, char * Value, BOOL Minimized) -{ - HKEY hKey=0; - char Size[80]; - char Key[80]; - int retCode, disp; - RECT Rect; - - if (IsWindow(hWnd) == FALSE) - return; - - ShowWindow(hWnd, SW_RESTORE); - - if (GetWindowRect(hWnd, &Rect) == FALSE) - return; - - // Make relative to Frame - - Rect.top -= FRect.top ; - Rect.left -= FRect.left; - Rect.bottom -= FRect.top; - Rect.right -= FRect.left; - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\%s", RegKey); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, - KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - sprintf(Size,"%d,%d,%d,%d,%d", Rect.left, Rect.right, Rect.top ,Rect.bottom, Minimized); - retCode = RegSetValueEx(hKey, Value, 0, REG_SZ,(BYTE *)&Size, strlen(Size)); - RegCloseKey(hKey); - } -} - -extern int GPSPort; -extern char LAT[]; // in standard APRS Format -extern char LON[]; // in standard APRS Format - -VOID SaveBPQ32Windows() -{ - HKEY hKey=0; - char Size[80]; - int retCode, disp; - PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE; - int i; - - retCode = RegCreateKeyEx(REGTREE, "SOFTWARE\\G8BPQ\\BPQ32", 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - sprintf(Size,"%d,%d,%d,%d", FRect.left, FRect.right, FRect.top, FRect.bottom); - retCode = RegSetValueEx(hKey, "FrameWindowSize", 0, REG_SZ, (BYTE *)&Size, strlen(Size)); - - // Save GPS Position - - if (GPSPort) - { - sprintf(Size, "%s, %s", LAT, LON); - retCode = RegSetValueEx(hKey, "GPS", 0, REG_SZ,(BYTE *)&Size, strlen(Size)); - } - - RegCloseKey(hKey); - } - - SaveMDIWindowPos(StatusWnd, "", "StatusWindowSize", StatusMinimized); - SaveMDIWindowPos(hConsWnd, "", "WindowSize", ConsoleMinimized); - - for (i=0;iPORTCONTROL.PORTTYPE == 0x10) // External - { - if (PORTVEC->PORT_EXT_ADDR) - { - SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER); - } - } - PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; - } - - SaveWindowPos(40); // Rigcontrol - - - if (hIPResWnd) - SaveMDIWindowPos(hIPResWnd, "", "IPResSize", IPMinimized); - - SaveHostSessions(); -} - -DllExport BOOL APIENTRY CheckIfOwner() -{ - // - // Returns TRUE if current process is root process - // that loaded the DLL - // - - if (TimerInst == GetCurrentProcessId()) - - return (TRUE); - else - return (FALSE); -} - -VOID GetParam(char * input, char * key, char * value) -{ - char * ptr = strstr(input, key); - char Param[2048]; - char * ptr1, * ptr2; - char c; - - if (ptr) - { - ptr2 = strchr(ptr, '&'); - if (ptr2) *ptr2 = 0; - strcpy(Param, ptr + strlen(key)); - if (ptr2) *ptr2 = '&'; // Restore string - - // Undo any % transparency - - ptr1 = Param; - ptr2 = Param; - - c = *(ptr1++); - - while (c) - { - if (c == '%') - { - int n; - int m = *(ptr1++) - '0'; - if (m > 9) m = m - 7; - n = *(ptr1++) - '0'; - if (n > 9) n = n - 7; - - *(ptr2++) = m * 16 + n; - } - else if (c == '+') - *(ptr2++) = ' '; - else - *(ptr2++) = c; - - c = *(ptr1++); - } - - *(ptr2++) = 0; - - strcpy(value, Param); - } -} - -int GetListeningPortsPID(int Port) -{ - MIB_TCPTABLE_OWNER_PID * TcpTable = NULL; - PMIB_TCPROW_OWNER_PID Row; - int dwSize = 0; - DWORD n; - - // Get PID of process for this TCP Port - - // Get Length of table - - GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0); - - TcpTable = malloc(dwSize); - - if (TcpTable == NULL) - return 0; - - GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0); - - for (n = 0; n < TcpTable->dwNumEntries; n++) - { - Row = &TcpTable->table[n]; - - if (Row->dwLocalPort == Port && Row->dwState == MIB_TCP_STATE_LISTEN) - { - return Row->dwOwningPid; - break; - } - } - return 0; // Not found -} - -DllExport char * APIENTRY GetLOC() -{ - return LOC; -} - -// UZ7HO Dll PTT interface - -// 1 ext_PTT_info -// 2 ext_PTT_settings -// 3 ext_PTT_OFF -// 4 ext_PTT_ON -// 5 ext_PTT_close -// 6 ext_PTT_open - -extern struct RIGINFO * DLLRIG; // Rig record for dll PTT interface (currently only for UZ7HO); - -VOID Rig_PTT(struct TNCINFO * TNC, BOOL PTTState); -VOID Rig_PTTEx(struct RIGINFO * RIG, BOOL PTTState, struct TNCINFO * TNC); - -int WINAPI ext_PTT_info() -{ - return 0; -} - -int WINAPI ext_PTT_settings() -{ - return 0; -} - -int WINAPI ext_PTT_OFF(int Port) -{ - if (DLLRIG) - Rig_PTTEx(DLLRIG, 0, 0); - - return 0; -} - -int WINAPI ext_PTT_ON(int Port) -{ - if (DLLRIG) - Rig_PTTEx(DLLRIG, 1, 0); - - return 0; -} -int WINAPI ext_PTT_close() -{ - if (DLLRIG) - Rig_PTTEx(DLLRIG, 0, 0); - - return 0; -} - -DllExport INT WINAPI ext_PTT_open() -{ - return 1; -} - -char * stristr (char *ch1, char *ch2) -{ - char *chN1, *chN2; - char *chNdx; - char *chRet = NULL; - - chN1 = _strdup(ch1); - chN2 = _strdup(ch2); - - if (chN1 && chN2) - { - chNdx = chN1; - while (*chNdx) - { - *chNdx = (char) tolower(*chNdx); - chNdx ++; - } - chNdx = chN2; - - while (*chNdx) - { - *chNdx = (char) tolower(*chNdx); - chNdx ++; - } - - chNdx = strstr(chN1, chN2); - - if (chNdx) - chRet = ch1 + (chNdx - chN1); - } - - free (chN1); - free (chN2); - return chRet; -} - - - diff --git a/CommonCode-HPLaptop.c b/CommonCode-HPLaptop.c deleted file mode 100644 index 2abf722..0000000 --- a/CommonCode-HPLaptop.c +++ /dev/null @@ -1,4742 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - - - -// General C Routines common to bpq32 and linbpq. Mainly moved from BPQ32.c - -#pragma data_seg("_BPQDATA") - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include -#include - -#pragma data_seg("_BPQDATA") - -#include "CHeaders.h" -#include "tncinfo.h" -#include "configstructs.h" - -extern struct CONFIGTABLE xxcfg; - -#define LIBCONFIG_STATIC -#include "libconfig.h" - -#ifndef LINBPQ - -//#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. - -#include "commctrl.h" -#include "Commdlg.h" - -#endif - -struct TNCINFO * TNCInfo[41]; // Records are Malloc'd - -extern int ReportTimer; - -Dll VOID APIENTRY Send_AX(UCHAR * Block, DWORD Len, UCHAR Port); -TRANSPORTENTRY * SetupSessionFromHost(PBPQVECSTRUC HOST, UINT ApplMask); -int Check_Timer(); -VOID SENDUIMESSAGE(struct DATAMESSAGE * Msg); -DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); -VOID APIENTRY md5 (char *arg, unsigned char * checksum); -VOID COMSetDTR(HANDLE fd); -VOID COMClearDTR(HANDLE fd); -VOID COMSetRTS(HANDLE fd); -VOID COMClearRTS(HANDLE fd); - -VOID WriteMiniDump(); -void printStack(void); -char * FormatMH(PMHSTRUC MH, char Format); -void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode); -extern BOOL LogAllConnects; - -extern VOID * ENDBUFFERPOOL; - -// Read/Write length field in a buffer header - -// Needed for Big/LittleEndian and ARM5 (unaligned operation problem) portability - - -VOID PutLengthinBuffer(PDATAMESSAGE buff, USHORT datalen) -{ - if (datalen <= sizeof(void *) + 4) - datalen = sizeof(void *) + 4; // Protect - - memcpy(&buff->LENGTH, &datalen, 2); -} - -int GetLengthfromBuffer(PDATAMESSAGE buff) -{ - USHORT Length; - - memcpy(&Length, &buff->LENGTH, 2); - return Length; -} - -BOOL CheckQHeadder(UINT * Q) -{ -#ifdef WIN32 - UINT Test; - - __try - { - Test = *Q; - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - Debugprintf("Invalid Q Header %p", Q); - printStack(); - return FALSE; - } -#endif - return TRUE; -} - -// Get buffer from Queue - - -VOID * _Q_REM(VOID **PQ, char * File, int Line) -{ - void ** Q; - void ** first; - VOID * next; - PMESSAGE Test; - - // PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (Semaphore.Flag == 0) - Debugprintf("Q_REM called without semaphore from %s Line %d", File, Line); - - if (CheckQHeadder((UINT *) Q) == 0) - return(0); - - first = Q[0]; - - if (first == 0) - return (0); // Empty - - next = first[0]; // Address of next buffer - - Q[0] = next; - - // Make sure guard zone is zeros - - Test = (PMESSAGE)first; - - if (Test->GuardZone != 0) - { - Debugprintf("Q_REM %p GUARD ZONE CORRUPT %x Called from %s Line %d", first, Test->GuardZone, File, Line); - printStack(); - } - - return first; -} - -// Non=pool version (for IPGateway) - -VOID * _Q_REM_NP(VOID *PQ, char * File, int Line) -{ - void ** Q; - void ** first; - void * next; - - // PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (CheckQHeadder((UINT *)Q) == 0) - return(0); - - first = Q[0]; - - if (first == 0) return (0); // Empty - - next = first[0]; // Address of next buffer - - Q[0] = next; - - return first; -} - -// Return Buffer to Free Queue - -extern VOID * BUFFERPOOL; -extern void ** Bufferlist[1000]; -void printStack(void); - -void _CheckGuardZone(char * File, int Line) -{ - int n = 0, i, offset = 0; - PMESSAGE Test; - UINT CodeDump[8]; - unsigned char * ptr; - - n = NUMBEROFBUFFERS; - - while (n--) - { - Test = (PMESSAGE)Bufferlist[n]; - - if (Test && Test->GuardZone) - { - Debugprintf("CheckGuardZone %p GUARD ZONE CORRUPT %d Called from %s Line %d", Test, Test->Process, File, Line); - - offset = 0; - ptr = (unsigned char *)Test; - - while (offset < 400) - { - memcpy(CodeDump, &ptr[offset], 32); - - for (i = 0; i < 8; i++) - CodeDump[i] = htonl(CodeDump[i]); - - Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", - &ptr[offset], CodeDump[0], CodeDump[1], CodeDump[2], CodeDump[3], CodeDump[4], CodeDump[5], CodeDump[6], CodeDump[7]); - - offset += 32; - } - WriteMiniDump(); -#ifdef MDIKERNEL - CloseAllNeeded = 1; -#endif - } - - } -} - -UINT _ReleaseBuffer(VOID *pBUFF, char * File, int Line) -{ - void ** pointer, ** BUFF = pBUFF; - int n = 0; - void ** debug; - PMESSAGE Test; - UINT CodeDump[16]; - int i; - unsigned int rev; - - if (Semaphore.Flag == 0) - Debugprintf("ReleaseBuffer called without semaphore from %s Line %d", File, Line); - - // Make sure address is within pool - - if ((uintptr_t)BUFF < (uintptr_t)BUFFERPOOL || (uintptr_t)BUFF > (uintptr_t)ENDBUFFERPOOL) - { - // Not pointing to a buffer . debug points to the buffer that this is chained from - - // Dump first chunk and source tag - - memcpy(CodeDump, BUFF, 64); - - Debugprintf("Releasebuffer Buffer not in pool from %s Line %d, ptr %p prev %d", File, Line, BUFF, 0); - - for (i = 0; i < 16; i++) - { - rev = (CodeDump[i] & 0xff) << 24; - rev |= (CodeDump[i] & 0xff00) << 8; - rev |= (CodeDump[i] & 0xff0000) >> 8; - rev |= (CodeDump[i] & 0xff000000) >> 24; - - CodeDump[i] = rev; - } - - Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", - Bufferlist[n], CodeDump[0], CodeDump[1], CodeDump[2], CodeDump[3], CodeDump[4], CodeDump[5], CodeDump[6], CodeDump[7]); - - Debugprintf(" %08x %08x %08x %08x %08x %08x %08x %08x", - CodeDump[8], CodeDump[9], CodeDump[10], CodeDump[11], CodeDump[12], CodeDump[13], CodeDump[14], CodeDump[15]); - - - return 0; - } - - Test = (PMESSAGE)pBUFF; - - if (Test->GuardZone != 0) - { - Debugprintf("_ReleaseBuffer %p GUARD ZONE CORRUPT %x Called from %s Line %d", pBUFF, Test->GuardZone, File, Line); - } - - while (n <= NUMBEROFBUFFERS) - { - if (BUFF == Bufferlist[n++]) - goto BOK1; - } - - Debugprintf("ReleaseBuffer %X not in Pool called from %s Line %d", BUFF, File, Line); - printStack(); - - return 0; - -BOK1: - - n = 0; - - // validate free Queue - - pointer = FREE_Q; - debug = &FREE_Q; - - while (pointer) - { - // Validate pointer to make sure it is in pool - it may be a duff address if Q is corrupt - - Test = (PMESSAGE)pointer; - - if (Test->GuardZone || (uintptr_t)pointer < (uintptr_t)BUFFERPOOL || (uintptr_t)pointer > (uintptr_t)ENDBUFFERPOOL) - { - // Not pointing to a buffer . debug points to the buffer that this is chained from - - // Dump first chunk and source tag - - memcpy(CodeDump, debug, 64); - - Debugprintf("Releasebuffer Pool Corruption n = %d, ptr %p prev %p", n, pointer, debug); - - for (i = 0; i < 16; i++) - { - rev = (CodeDump[i] & 0xff) << 24; - rev |= (CodeDump[i] & 0xff00) << 8; - rev |= (CodeDump[i] & 0xff0000) >> 8; - rev |= (CodeDump[i] & 0xff000000) >> 24; - - CodeDump[i] = rev; - } - - Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", - Bufferlist[n], CodeDump[0], CodeDump[1], CodeDump[2], CodeDump[3], CodeDump[4], CodeDump[5], CodeDump[6], CodeDump[7]); - - Debugprintf(" %08x %08x %08x %08x %08x %08x %08x %08x", - CodeDump[8], CodeDump[9], CodeDump[10], CodeDump[11], CodeDump[12], CodeDump[13], CodeDump[14], CodeDump[15]); - - if (debug[400]) - Debugprintf(" %s", &debug[400]); - - } - - // See if already on free Queue - - if (pointer == BUFF) - { - Debugprintf("Trying to free buffer %p when already on FREE_Q called from %s Line %d", BUFF, File, Line); -// WriteMiniDump(); - return 0; - } - -// if (pointer[0] && pointer == pointer[0]) -// { -// Debugprintf("Buffer chained to itself"); -// return 0; -// } - - debug = pointer; - pointer = pointer[0]; - n++; - - if (n > 1000) - { - Debugprintf("Loop searching free chain - pointer = %p %p", debug, pointer); - return 0; - } - } - - pointer = FREE_Q; - - *BUFF = pointer; - - FREE_Q = BUFF; - - QCOUNT++; - - return 0; -} - -int _C_Q_ADD(VOID *PQ, VOID *PBUFF, char * File, int Line) -{ - void ** Q; - void ** BUFF = PBUFF; - void ** next; - PMESSAGE Test; - - - int n = 0; - -// PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (Semaphore.Flag == 0) - Debugprintf("C_Q_ADD called without semaphore from %s Line %d", File, Line); - - if (CheckQHeadder((UINT *)Q) == 0) // Make sure Q header is readable - return(0); - - // Make sure guard zone is zeros - - Test = (PMESSAGE)PBUFF; - - if (Test->GuardZone != 0) - { - Debugprintf("C_Q_ADD %p GUARD ZONE CORRUPT %x Called from %s Line %d", PBUFF, Test->GuardZone, File, Line); - } - - Test = (PMESSAGE)Q; - - - - // Make sure address is within pool - - while (n <= NUMBEROFBUFFERS) - { - if (BUFF == Bufferlist[n++]) - goto BOK2; - } - - Debugprintf("C_Q_ADD %X not in Pool called from %s Line %d", BUFF, File, Line); - printStack(); - - return 0; - -BOK2: - - BUFF[0] = 0; // Clear chain in new buffer - - if (Q[0] == 0) // Empty - { - Q[0]=BUFF; // New one on front - return(0); - } - - next = Q[0]; - - while (next[0] != 0) - { - next = next[0]; // Chain to end of queue - } - next[0] = BUFF; // New one on end - - return(0); -} - -// Non-pool version - -int C_Q_ADD_NP(VOID *PQ, VOID *PBUFF) -{ - void ** Q; - void ** BUFF = PBUFF; - void ** next; - int n = 0; - -// PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (CheckQHeadder((UINT *)Q) == 0) // Make sure Q header is readable - return(0); - - BUFF[0]=0; // Clear chain in new buffer - - if (Q[0] == 0) // Empty - { - Q[0]=BUFF; // New one on front -// memcpy(PQ, &BUFF, 4); - return 0; - } - next = Q[0]; - - while (next[0] != 0) - next=next[0]; // Chain to end of queue - - next[0] = BUFF; // New one on end - - return(0); -} - - -int C_Q_COUNT(VOID *PQ) -{ - void ** Q; - int count = 0; - -// PQ may not be word aligned, so copy as bytes (for ARM5) - - Q = PQ; - - if (CheckQHeadder((UINT *)Q) == 0) // Make sure Q header is readable - return(0); - - // SEE HOW MANY BUFFERS ATTACHED TO Q HEADER - - while (*Q) - { - count++; - if ((count + QCOUNT) > MAXBUFFS) - { - Debugprintf("C_Q_COUNT Detected corrupt Q %p len %d", PQ, count); - return count; - } - Q = *Q; - } - - return count; -} - -VOID * _GetBuff(char * File, int Line) -{ - UINT * Temp; - MESSAGE * Msg; - char * fptr = 0; - unsigned char * byteaddr; - - Temp = Q_REM(&FREE_Q); - -// FindLostBuffers(); - - if (Semaphore.Flag == 0) - Debugprintf("GetBuff called without semaphore from %s Line %d", File, Line); - - if (Temp) - { - QCOUNT--; - - if (QCOUNT < MINBUFFCOUNT) - MINBUFFCOUNT = QCOUNT; - - Msg = (MESSAGE *)Temp; - fptr = File + (int)strlen(File); - while (*fptr != '\\' && *fptr != '/') - fptr--; - fptr++; - - // Buffer Length is BUFFLEN, but buffers are allocated 512 - // So add file info in gap between - - byteaddr = (unsigned char *)Msg; - - - memset(&byteaddr[0], 0, 64); // simplify debugging lost buffers - memset(&byteaddr[400], 0, 64); // simplify debugging lost buffers - sprintf(&byteaddr[400], "%s %d", fptr, Line); - - Msg->Process = (short)GetCurrentProcessId(); - Msg->Linkptr = NULL; - } - else - Debugprintf("Warning - Getbuff returned NULL"); - - return Temp; -} - -void * zalloc(int len) -{ - // malloc and clear - - void * ptr; - - ptr=malloc(len); - - if (ptr) - memset(ptr, 0, len); - - return ptr; -} - -char * strlop(char * buf, char delim) -{ - // Terminate buf at delim, and return rest of string - - char * ptr; - - if (buf == NULL) return NULL; // Protect - - ptr = strchr(buf, delim); - - if (ptr == NULL) return NULL; - - *(ptr)++=0; - - return ptr; -} - -VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer) -{ - UCHAR Type = L4->L4CIRCUITTYPE; - struct PORTCONTROL * PORT; - struct _LINKTABLE * LINK; - BPQVECSTRUC * VEC; - struct DEST_LIST * DEST; - - char Normcall[20] = ""; // Could be alias:call - char Normcall2[11] = ""; - char Alias[11] = ""; - - Buffer[0] = 0; - - switch (Type) - { - case PACTOR+UPLINK: - - PORT = L4->L4TARGET.PORT; - - ConvFromAX25(L4->L4USER, Normcall); - strlop(Normcall, ' '); - - if (PORT) - sprintf(Buffer, "%s %d/%d(%s)", "TNC Uplink Port", PORT->PORTNUMBER, L4->KAMSESSION, Normcall); - - return; - - - case PACTOR+DOWNLINK: - - PORT = L4->L4TARGET.PORT; - - if (PORT) - sprintf(Buffer, "%s %d/%d", "Attached to Port", PORT->PORTNUMBER, L4->KAMSESSION); - return; - - - case L2LINK+UPLINK: - - LINK = L4->L4TARGET.LINK; - - ConvFromAX25(L4->L4USER, Normcall); - strlop(Normcall, ' '); - - if (LINK &&LINK->LINKPORT) - sprintf(Buffer, "%s %d(%s)", "Uplink", LINK->LINKPORT->PORTNUMBER, Normcall); - - return; - - case L2LINK+DOWNLINK: - - LINK = L4->L4TARGET.LINK; - - if (LINK == NULL) - return; - - ConvFromAX25(LINK->OURCALL, Normcall); - strlop(Normcall, ' '); - - ConvFromAX25(LINK->LINKCALL, Normcall2); - strlop(Normcall2, ' '); - - sprintf(Buffer, "%s %d(%s %s)", "Downlink", LINK->LINKPORT->PORTNUMBER, Normcall, Normcall2); - return; - - case BPQHOST + UPLINK: - case BPQHOST + DOWNLINK: - - // if the call has a Level 4 address display ALIAS:CALL, else just Call - - if (FindDestination(L4->L4USER, &DEST)) - Normcall[DecodeNodeName(DEST->DEST_CALL, Normcall)] = 0; // null terminate - else - Normcall[ConvFromAX25(L4->L4USER, Normcall)] = 0; - - VEC = L4->L4TARGET.HOST; - sprintf(Buffer, "%s%02d(%s)", "Host", (int)(VEC - BPQHOSTVECTOR) + 1, Normcall); - return; - - case SESSION + DOWNLINK: - case SESSION + UPLINK: - - ConvFromAX25(L4->L4USER, Normcall); - strlop(Normcall, ' '); - - DEST = L4->L4TARGET.DEST; - - if (DEST == NULL) - return; - - ConvFromAX25(DEST->DEST_CALL, Normcall2); - strlop(Normcall2, ' '); - - memcpy(Alias, DEST->DEST_ALIAS, 6); - strlop(Alias, ' '); - - sprintf(Buffer, "Circuit(%s:%s %s)", Alias, Normcall2, Normcall); - - return; - } -} - -VOID CheckForDetach(struct TNCINFO * TNC, int Stream, struct STREAMINFO * STREAM, - VOID TidyCloseProc(), VOID ForcedCloseProc(), VOID CloseComplete()) -{ - void ** buffptr; - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] == 0) - { - // Node has disconnected - clear any connection - - if (STREAM->Disconnecting) - { - // Already detected the detach, and have started to close - - STREAM->DisconnectingTimeout--; - - if (STREAM->DisconnectingTimeout) - return; // Give it a bit longer - - // Close has timed out - force a disc, and clear - - ForcedCloseProc(TNC, Stream); // Send Tidy Disconnect - - goto NotConnected; - } - - // New Disconnect - - Debugprintf("New Disconnect Port %d Q %x", TNC->Port, STREAM->BPQtoPACTOR_Q); - - if (STREAM->Connected || STREAM->Connecting) - { - char logmsg[120]; - time_t Duration; - - // Need to do a tidy close - - STREAM->Connecting = FALSE; - STREAM->Disconnecting = TRUE; - STREAM->DisconnectingTimeout = 300; // 30 Secs - - if (Stream == 0) - SetWindowText(TNC->xIDC_TNCSTATE, "Disconnecting"); - - // Create a traffic record - - if (STREAM->Connected && STREAM->ConnectTime) - { - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; // Or will get divide by zero error - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - - STREAM->ConnectTime = 0; - } - - if (STREAM->BPQtoPACTOR_Q) // Still data to send? - return; // Will close when all acked - -// if (STREAM->FramesOutstanding && TNC->Hardware == H_UZ7HO) -// return; // Will close when all acked - - TidyCloseProc(TNC, Stream); // Send Tidy Disconnect - - return; - } - - // Not connected -NotConnected: - - STREAM->Disconnecting = FALSE; - STREAM->Attached = FALSE; - STREAM->Connecting = FALSE; - STREAM->Connected = FALSE; - - if (Stream == 0) - SetWindowText(TNC->xIDC_TNCSTATE, "Free"); - - STREAM->FramesQueued = 0; - STREAM->FramesOutstanding = 0; - - CloseComplete(TNC, Stream); - - while(STREAM->BPQtoPACTOR_Q) - { - buffptr=Q_REM(&STREAM->BPQtoPACTOR_Q); - ReleaseBuffer(buffptr); - } - - while(STREAM->PACTORtoBPQ_Q) - { - buffptr=Q_REM(&STREAM->PACTORtoBPQ_Q); - ReleaseBuffer(buffptr); - } - } -} - -char * CheckAppl(struct TNCINFO * TNC, char * Appl) -{ - APPLCALLS * APPL; - BPQVECSTRUC * PORTVEC; - int Allocated = 0, Available = 0; - int App, Stream; - struct TNCINFO * APPLTNC; - -// Debugprintf("Checking if %s is running", Appl); - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - - if (_memicmp(APPL->APPLCMD, Appl, 12) == 0) - { - int _APPLMASK = 1 << App; - - // If App has an alias, assume it is running , unless a CMS alias - then check CMS - - if (APPL->APPLHASALIAS) - { - if (_memicmp(APPL->APPLCMD, "RELAY ", 6) == 0) - return APPL->APPLCALL_TEXT; // Assume people using RELAY know what they are doing - - if (APPL->APPLPORT && (_memicmp(APPL->APPLCMD, "RMS ", 4) == 0)) - { - APPLTNC = TNCInfo[APPL->APPLPORT]; - { - if (APPLTNC) - { - if (APPLTNC->TCPInfo && !APPLTNC->TCPInfo->CMSOK && !APPLTNC->TCPInfo->FallbacktoRelay) - return NULL; - } - } - } - return APPL->APPLCALL_TEXT; - } - - // See if App is running - - PORTVEC = &BPQHOSTVECTOR[0]; - - for (Stream = 0; Stream < 64; Stream++) - { - if (PORTVEC->HOSTAPPLMASK & _APPLMASK) - { - Allocated++; - - if (PORTVEC->HOSTSESSION == 0 && (PORTVEC->HOSTFLAGS & 3) == 0) - { - // Free and no outstanding report - - return APPL->APPLCALL_TEXT; // Running - } - } - PORTVEC++; - } - } - } - - return NULL; // Not Running -} - -VOID SetApplPorts() -{ - // If any appl has an alias, get port number - - struct APPLCONFIG * App; - APPLCALLS * APPL; - - char C[80]; - char Port[80]; - char Call[80]; - - int i, n; - - App = &xxcfg.C_APPL[0]; - - for (i=0; i < NumberofAppls; i++) - { - APPL=&APPLCALLTABLE[i]; - - if (APPL->APPLHASALIAS) - { - n = sscanf(App->CommandAlias, "%s %s %s", &C[0], &Port[0], &Call[0]); - if (n == 3) - APPL->APPLPORT = atoi(Port); - } - App++; - } -} - - -extern struct TNCINFO * TNCInfo[41]; // Records are Malloc'd - - -char Modenames[19][10] = {"WINMOR", "SCS", "KAM", "AEA", "HAL", "TELNET", "TRK", - "V4", "UZ7HO", "MPSK", "FLDIGI", "UIARQ", "ARDOP", "VARA", - "SERIAL", "KISSHF", "WINRPR", "HSMODEM", "FREEDATA"}; - -BOOL ProcessIncommingConnect(struct TNCINFO * TNC, char * Call, int Stream, BOOL SENDCTEXT) -{ - return ProcessIncommingConnectEx(TNC, Call, Stream, SENDCTEXT, FALSE); -} - -BOOL ProcessIncommingConnectEx(struct TNCINFO * TNC, char * Call, int Stream, BOOL SENDCTEXT, BOOL AllowTR) -{ - TRANSPORTENTRY * Session; - int Index = 0; - PMSGWITHLEN buffptr; - int Totallen = 0; - UCHAR * ptr; - struct PORTCONTROL * PORT; - - PORT = &TNC->PortRecord->PORTCONTROL; - - // Stop Scanner - - if (Stream == 0 || TNC->Hardware == H_UZ7HO) - { - char Msg[80]; - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command(-1, Msg); - - UpdateMH(TNC, Call, '+', 'I'); - } - - Session = L4TABLE; - - // Find a free Circuit Entry - - while (Index < MAXCIRCUITS) - { - if (Session->L4USER[0] == 0) - break; - - Session++; - Index++; - } - - if (Index == MAXCIRCUITS) - return FALSE; // Tables Full - - memset(Session, 0, sizeof(TRANSPORTENTRY)); - - memcpy(TNC->Streams[Stream].RemoteCall, Call, 9); // Save Text Callsign - - if (AllowTR) - ConvToAX25Ex(Call, Session->L4USER); // Allow -T and -R SSID's for MPS - else - ConvToAX25(Call, Session->L4USER); - ConvToAX25(MYNODECALL, Session->L4MYCALL); - Session->CIRCUITINDEX = Index; - Session->CIRCUITID = NEXTID; - NEXTID++; - if (NEXTID == 0) NEXTID++; // Keep non-zero - - TNC->PortRecord->ATTACHEDSESSIONS[Stream] = Session; - TNC->Streams[Stream].Attached = TRUE; - - Session->L4TARGET.EXTPORT = TNC->PortRecord; - - Session->L4CIRCUITTYPE = UPLINK+PACTOR; - Session->L4WINDOW = L4DEFAULTWINDOW; - Session->L4STATE = 5; - Session->SESSIONT1 = L4T1; - Session->SESSPACLEN = TNC->PortRecord->PORTCONTROL.PORTPACLEN; - Session->KAMSESSION = Stream; - - TNC->Streams[Stream].Connected = TRUE; // Subsequent data to data channel - - if (LogAllConnects) - { - if (TNC->TargetCall[0]) - WriteConnectLog(Call, TNC->TargetCall, Modenames[TNC->Hardware - 1]); - else - WriteConnectLog(Call, MYNODECALL, Modenames[TNC->Hardware - 1]); - } - - if (SENDCTEXT == 0) - return TRUE; - - // if Port CTEXT defined, use it - - if (PORT->CTEXT) - { - Totallen = strlen(PORT->CTEXT); - ptr = PORT->CTEXT; - } - else if (HFCTEXTLEN > 0) - { - Totallen = HFCTEXTLEN; - ptr = HFCTEXT; - } - else - return TRUE; - - while (Totallen > 0) - { - int sendLen = TNC->PortRecord->ATTACHEDSESSIONS[Stream]->SESSPACLEN; - - if (sendLen == 0) - sendLen = 80; - - if (Totallen < sendLen) - sendLen = Totallen; - - buffptr = (PMSGWITHLEN)GetBuff(); - if (buffptr == 0) return TRUE; // No buffers - - buffptr->Len = sendLen; - memcpy(&buffptr->Data[0], ptr, sendLen); - C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); - Totallen -= sendLen; - ptr += sendLen; - } - return TRUE; -} - -char * Config; -static char * ptr1, * ptr2; - -BOOL ReadConfigFile(int Port, int ProcLine()) -{ - char buf[256],errbuf[256]; - - if (TNCInfo[Port]) // If restarting, free old config - free(TNCInfo[Port]); - - TNCInfo[Port] = NULL; - - Config = PortConfig[Port]; - - if (Config) - { - // Using config from bpq32.cfg - - if (strlen(Config) == 0) - { - // Empty Config File - OK for most types - - struct TNCINFO * TNC = TNCInfo[Port] = zalloc(sizeof(struct TNCINFO)); - - TNC->InitScript = malloc(2); - TNC->InitScript[0] = 0; - - return TRUE; - } - - ptr1 = Config; - - ptr2 = strchr(ptr1, 13); - while(ptr2) - { - memcpy(buf, ptr1, ptr2 - ptr1 + 1); - buf[ptr2 - ptr1 + 1] = 0; - ptr1 = ptr2 + 2; - ptr2 = strchr(ptr1, 13); - - strcpy(errbuf,buf); // save in case of error - - if (!ProcLine(buf, Port)) - { - WritetoConsoleLocal("\n"); - WritetoConsoleLocal("Bad config record "); - WritetoConsoleLocal(errbuf); - } - } - } - else - { - sprintf(buf," ** Error - No Configuration info in bpq32.cfg"); - WritetoConsoleLocal(buf); - } - - return (TRUE); -} -int GetLine(char * buf) -{ -loop: - - if (ptr2 == NULL) - return 0; - - memcpy(buf, ptr1, ptr2 - ptr1 + 2); - buf[ptr2 - ptr1 + 2] = 0; - ptr1 = ptr2 + 2; - ptr2 = strchr(ptr1, 13); - - if (buf[0] < 0x20) goto loop; - if (buf[0] == '#') goto loop; - if (buf[0] == ';') goto loop; - - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - buf[strlen(buf)] = 13; - - return 1; -} -VOID DigiToMultiplePorts(struct PORTCONTROL * PORTVEC, PMESSAGE Msg) -{ - USHORT Mask=PORTVEC->DIGIMASK; - int i; - - for (i=1; i<=NUMBEROFPORTS; i++) - { - if (Mask & 1) - { - // Block includes the Msg Header (7/11 bytes), Len Does not! - - Msg->PORT = i; - Send_AX((UCHAR *)&Msg, Msg->LENGTH - MSGHDDRLEN, i); - Mask>>=1; - } - } -} - -int CompareAlias(struct DEST_LIST ** a, struct DEST_LIST ** b) -{ - return memcmp(a[0]->DEST_ALIAS, b[0]->DEST_ALIAS, 6); - /* strcmp functions works exactly as expected from comparison function */ -} - - -int CompareNode(struct DEST_LIST ** a, struct DEST_LIST ** b) -{ - return memcmp(a[0]->DEST_CALL, b[0]->DEST_CALL, 7); -} - -DllExport int APIENTRY CountFramesQueuedOnStream(int Stream) -{ - BPQVECSTRUC * PORTVEC = &BPQHOSTVECTOR[Stream-1]; // API counts from 1 - TRANSPORTENTRY * L4 = PORTVEC->HOSTSESSION; - - int Count = 0; - - if (L4) - { - if (L4->L4CROSSLINK) // CONNECTED? - Count = CountFramesQueuedOnSession(L4->L4CROSSLINK); - else - Count = CountFramesQueuedOnSession(L4); - } - return Count; -} - -DllExport int APIENTRY ChangeSessionCallsign(int Stream, unsigned char * AXCall) -{ - // Equivalent to "*** linked to" command - - memcpy(BPQHOSTVECTOR[Stream-1].HOSTSESSION->L4USER, AXCall, 7); - return (0); -} - -DllExport int APIENTRY ChangeSessionPaclen(int Stream, int Paclen) -{ - BPQHOSTVECTOR[Stream-1].HOSTSESSION->SESSPACLEN = Paclen; - return (0); -} - -DllExport int APIENTRY ChangeSessionIdletime(int Stream, int idletime) -{ - if (BPQHOSTVECTOR[Stream-1].HOSTSESSION) - BPQHOSTVECTOR[Stream-1].HOSTSESSION->L4LIMIT = idletime; - return (0); -} - -DllExport int APIENTRY Get_APPLMASK(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTAPPLMASK; -} -DllExport int APIENTRY GetStreamPID(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].STREAMOWNER; -} - -DllExport int APIENTRY GetApplFlags(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTAPPLFLAGS; -} - -DllExport int APIENTRY GetApplNum(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTAPPLNUM; -} - -DllExport int APIENTRY GetApplMask(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTAPPLMASK; -} - -DllExport BOOL APIENTRY GetAllocationState(int Stream) -{ - return BPQHOSTVECTOR[Stream-1].HOSTFLAGS & 0x80; -} - -VOID Send_AX_Datagram(PDIGIMESSAGE Block, DWORD Len, UCHAR Port); - -extern int InitDone; -extern int SemHeldByAPI; -extern char pgm[256]; // Uninitialised so per process -extern int BPQHOSTAPI(); - - -VOID POSTSTATECHANGE(BPQVECSTRUC * SESS) -{ - // Post a message if requested -#ifndef LINBPQ - if (SESS->HOSTHANDLE) - PostMessage(SESS->HOSTHANDLE, BPQMsg, SESS->HOSTSTREAM, 4); -#endif - return; -} - - -DllExport int APIENTRY SessionControl(int stream, int command, int Mask) -{ - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return (0); - - SESS = &BPQHOSTVECTOR[stream]; - - // Send Session Control command (BPQHOST function 6) - //; CL=0 CONNECT USING APPL MASK IN DL - //; CL=1, CONNECT. CL=2 - DISCONNECT. CL=3 RETURN TO NODE - - if (command > 1) - { - // Disconnect - - if (SESS->HOSTSESSION == 0) - { - SESS->HOSTFLAGS |= 1; // State Change - POSTSTATECHANGE(SESS); - return 0; // NOT CONNECTED - } - - if (command == 3) - SESS->HOSTFLAGS |= 0x20; // Set Stay - - SESS->HOSTFLAGS |= 0x40; // SET 'DISC REQ' FLAG - - return 0; - } - - // 0 or 1 - connect - - if (SESS->HOSTSESSION) // ALREADY CONNECTED - { - SESS->HOSTFLAGS |= 1; // State Change - POSTSTATECHANGE(SESS); - return 0; - } - - // SET UP A SESSION FOR THE CONSOLE - - SESS->HOSTFLAGS |= 0x80; // SET ALLOCATED BIT - - if (command == 1) // Zero is mask supplied by caller - Mask = SESS->HOSTAPPLMASK; // SO WE GET CORRECT CALLSIGN - - L4 = SetupSessionFromHost(SESS, Mask); - - if (L4 == 0) // tables Full - { - SESS->HOSTFLAGS |= 3; // State Change - POSTSTATECHANGE(SESS); - return 0; - } - - SESS->HOSTSESSION = L4; - L4->L4CIRCUITTYPE = BPQHOST | UPLINK; - L4->Secure_Session = AuthorisedProgram; // Secure Host Session - - SESS->HOSTFLAGS |= 1; // State Change - POSTSTATECHANGE(SESS); - return 0; // ALREADY CONNECTED -} - -int FindFreeStreamEx(int GetSem); - -int FindFreeStreamNoSem() -{ - return FindFreeStreamEx(0); -} - -DllExport int APIENTRY FindFreeStream() -{ - return FindFreeStreamEx(1); -} - -int FindFreeStreamEx(int GetSem) -{ - int stream, n; - BPQVECSTRUC * PORTVEC; - -// Returns number of first unused BPQHOST stream. If none available, -// returns 255. See API function 13. - - // if init has not yet been run, wait. - - while (InitDone == 0) - { - Debugprintf("Waiting for init to complete"); - Sleep(1000); - } - - if (InitDone == -1) // Init failed - exit(0); - - if (GetSem) - GetSemaphore(&Semaphore, 9); - - stream = 0; - n = 64; - - while (n--) - { - PORTVEC = &BPQHOSTVECTOR[stream++]; - if ((PORTVEC->HOSTFLAGS & 0x80) == 0) - { - PORTVEC->STREAMOWNER=GetCurrentProcessId(); - PORTVEC->HOSTFLAGS = 128; // SET ALLOCATED BIT, clear others - memcpy(&PORTVEC->PgmName[0], pgm, 31); - if (GetSem) - FreeSemaphore(&Semaphore); - return stream; - } - } - - if (GetSem) - FreeSemaphore(&Semaphore); - - return 255; -} - -DllExport int APIENTRY AllocateStream(int stream) -{ -// Allocate stream. If stream is already allocated, return nonzero. -// Otherwise allocate stream, and return zero. - - BPQVECSTRUC * PORTVEC = &BPQHOSTVECTOR[stream -1]; // API counts from 1 - - if ((PORTVEC->HOSTFLAGS & 0x80) == 0) - { - PORTVEC->STREAMOWNER=GetCurrentProcessId(); - PORTVEC->HOSTFLAGS = 128; // SET ALLOCATED BIT, clear others - memcpy(&PORTVEC->PgmName[0], pgm, 31); - FreeSemaphore(&Semaphore); - return 0; - } - - return 1; // Already allocated -} - - -DllExport int APIENTRY DeallocateStream(int stream) -{ - BPQVECSTRUC * PORTVEC; - UINT * monbuff; - BOOL GotSem = Semaphore.Flag; - -// Release stream. - - stream--; - - if (stream < 0 || stream > 63) - return (0); - - PORTVEC=&BPQHOSTVECTOR[stream]; - - PORTVEC->STREAMOWNER=0; - PORTVEC->PgmName[0] = 0; - PORTVEC->HOSTAPPLFLAGS=0; - PORTVEC->HOSTAPPLMASK=0; - PORTVEC->HOSTHANDLE=0; - - // Clear Trace Queue - - if (PORTVEC->HOSTSESSION) - SessionControl(stream + 1, 2, 0); - - if (GotSem == 0) - GetSemaphore(&Semaphore, 0); - - while (PORTVEC->HOSTTRACEQ) - { - monbuff = Q_REM((void *)&PORTVEC->HOSTTRACEQ); - ReleaseBuffer(monbuff); - } - - if (GotSem == 0) - FreeSemaphore(&Semaphore); - - PORTVEC->HOSTFLAGS &= 0x60; // Clear Allocated. Must leave any DISC Pending bits - - return(0); -} -DllExport int APIENTRY SessionState(int stream, int * state, int * change) -{ - // Get current Session State. Any state changed is ACK'ed - // automatically. See BPQHOST functions 4 and 5. - - BPQVECSTRUC * HOST = &BPQHOSTVECTOR[stream -1]; // API counts from 1 - - Check_Timer(); // In case Appl doesnt call it often ehough - - GetSemaphore(&Semaphore, 20); - - // CX = 0 if stream disconnected or CX = 1 if stream connected - // DX = 0 if no change of state since last read, or DX = 1 if - // the connected/disconnected state has changed since - // last read (ie. delta-stream status). - - // HOSTFLAGS = Bit 80 = Allocated - // Bit 40 = Disc Request - // Bit 20 = Stay Flag - // Bit 02 and 01 State Change Bits - - if ((HOST->HOSTFLAGS & 3) == 0) - // No Chaange - *change = 0; - else - *change = 1; - - if (HOST->HOSTSESSION) // LOCAL SESSION - // Connected - *state = 1; - else - *state = 0; - - HOST->HOSTFLAGS &= 0xFC; // Clear Change Bitd - - FreeSemaphore(&Semaphore); - return 0; -} - -DllExport int APIENTRY SessionStateNoAck(int stream, int * state) -{ - // Get current Session State. Dont ACK any change - // See BPQHOST function 4 - - BPQVECSTRUC * HOST = &BPQHOSTVECTOR[stream -1]; // API counts from 1 - - Check_Timer(); // In case Appl doesnt call it often ehough - - if (HOST->HOSTSESSION) // LOCAL SESSION - // Connected - *state = 1; - else - *state = 0; - - return 0; -} - -DllExport int APIENTRY SendMsg(int stream, char * msg, int len) -{ - // Send message to stream (BPQHOST Function 2) - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - TRANSPORTENTRY * Partner; - PDATAMESSAGE MSG; - - Check_Timer(); - - if (len > 256) - return 0; // IGNORE - - if (stream == 0) - { - // Send UNPROTO - SEND FRAME TO ALL RADIO PORTS - - // COPY DATA TO A BUFFER IN OUR SEGMENTS - SIMPLFIES THINGS LATER - - if (QCOUNT < 50) - return 0; // Dont want to run out - - GetSemaphore(&Semaphore, 10); - - if ((MSG = GetBuff()) == 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - MSG->PID = 0xF0; // Normal Data PID - - memcpy(&MSG->L2DATA[0], msg, len); - MSG->LENGTH = (len + MSGHDDRLEN + 1); - - SENDUIMESSAGE(MSG); - ReleaseBuffer(MSG); - FreeSemaphore(&Semaphore); - return 0; - } - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - if (L4 == 0) - return 0; - - GetSemaphore(&Semaphore, 22); - - SESS->HOSTFLAGS |= 0x80; // SET ALLOCATED BIT - - if (QCOUNT < 40) // PLENTY FREE? - { - FreeSemaphore(&Semaphore); - return 1; - } - - // Dont allow massive queues to form - - if (QCOUNT < 100) - { - int n = CountFramesQueuedOnStream(stream + 1); - - if (n > 100) - { - Debugprintf("Stream %d QCOUNT %d Q Len %d - discarding", stream, QCOUNT, n); - FreeSemaphore(&Semaphore); - return 1; - } - } - - if ((MSG = GetBuff()) == 0) - { - FreeSemaphore(&Semaphore); - return 1; - } - - MSG->PID = 0xF0; // Normal Data PID - - memcpy(&MSG->L2DATA[0], msg, len); - MSG->LENGTH = len + MSGHDDRLEN + 1; - - // IF CONNECTED, PASS MESSAGE TO TARGET CIRCUIT - FLOW CONTROL AND - // DELAYED DISC ONLY WORK ON ONE SIDE - - Partner = L4->L4CROSSLINK; - - L4->L4KILLTIMER = 0; // RESET SESSION TIMEOUT - - if (Partner && Partner->L4STATE > 4) // Partner and link up - { - // Connected - - Partner->L4KILLTIMER = 0; // RESET SESSION TIMEOUT - C_Q_ADD(&Partner->L4TX_Q, MSG); - PostDataAvailable(Partner); - } - else - C_Q_ADD(&L4->L4RX_Q, MSG); - - FreeSemaphore(&Semaphore); - return 0; -} -DllExport int APIENTRY SendRaw(int port, char * msg, int len) -{ - struct PORTCONTROL * PORT; - MESSAGE * MSG; - - Check_Timer(); - - // Send Raw (KISS mode) frame to port (BPQHOST function 10) - - if (len > (MAXDATA - (MSGHDDRLEN + 8))) - return 0; - - if (QCOUNT < 50) - return 1; - - // GET A BUFFER - - PORT = GetPortTableEntryFromSlot(port); - - if (PORT == 0) - return 0; - - GetSemaphore(&Semaphore, 24); - - MSG = GetBuff(); - - if (MSG == 0) - { - FreeSemaphore(&Semaphore); - return 1; - } - - memcpy(MSG->DEST, msg, len); - - MSG->LENGTH = len + MSGHDDRLEN; - - if (PORT->PROTOCOL == 10) // PACTOR/WINMOR Style - { - // Pactor Style. Probably will only be used for Tracker uneless we do APRS over V4 or WINMOR - - EXTPORTDATA * EXTPORT = (EXTPORTDATA *) PORT; - - C_Q_ADD(&EXTPORT->UI_Q, MSG); - - FreeSemaphore(&Semaphore); - return 0; - } - - MSG->PORT = PORT->PORTNUMBER; - - PUT_ON_PORT_Q(PORT, MSG); - - FreeSemaphore(&Semaphore); - return 0; -} - -DllExport time_t APIENTRY GetRaw(int stream, char * msg, int * len, int * count) -{ - time_t Stamp; - BPQVECSTRUC * SESS; - PMESSAGE MSG; - int Msglen; - - Check_Timer(); - - *len = 0; - *count = 0; - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - - GetSemaphore(&Semaphore, 26); - - if (SESS->HOSTTRACEQ == 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - MSG = Q_REM((void *)&SESS->HOSTTRACEQ); - - Msglen = MSG->LENGTH; - - if (Msglen < 0 || Msglen > 350) - { - FreeSemaphore(&Semaphore); - return 0; - } - - Stamp = MSG->Timestamp; - - memcpy(msg, MSG, Msglen); - - *len = Msglen; - - ReleaseBuffer(MSG); - - *count = C_Q_COUNT(&SESS->HOSTTRACEQ); - FreeSemaphore(&Semaphore); - - return Stamp; -} - -DllExport int APIENTRY GetMsg(int stream, char * msg, int * len, int * count ) -{ -// Get message from stream. Returns length, and count of frames -// still waiting to be collected. (BPQHOST function 3) -// AH = 3 Receive frame into buffer at ES:DI, length of frame returned -// in CX. BX returns the number of outstanding frames still to -// be received (ie. after this one) or zero if no more frames -// (ie. this is last one). -// - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - PDATAMESSAGE MSG; - int Msglen; - - Check_Timer(); - - *len = 0; - *count = 0; - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - GetSemaphore(&Semaphore, 25); - - if (L4 == 0 || L4->L4TX_Q == 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - L4->L4KILLTIMER = 0; // RESET SESSION TIMEOUT - - if(L4->L4CROSSLINK) - L4->L4CROSSLINK->L4KILLTIMER = 0; - - MSG = Q_REM((void *)&L4->L4TX_Q); - - Msglen = MSG->LENGTH - (MSGHDDRLEN + 1); // Dont want PID - - if (Msglen < 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - if (Msglen > 256) - Msglen = 256; - - memcpy(msg, &MSG->L2DATA[0], Msglen); - - *len = Msglen; - - ReleaseBuffer(MSG); - - *count = C_Q_COUNT(&L4->L4TX_Q); - FreeSemaphore(&Semaphore); - - return 0; -} - - -DllExport int APIENTRY RXCount(int stream) -{ -// Returns count of packets waiting on stream -// (BPQHOST function 7 (part)). - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - if (L4 == 0) - return 0; // NOT CONNECTED - - return C_Q_COUNT(&L4->L4TX_Q); -} - -DllExport int APIENTRY TXCount(int stream) -{ -// Returns number of packets on TX queue for stream -// (BPQHOST function 7 (part)). - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - if (L4 == 0) - return 0; // NOT CONNECTED - - L4 = L4->L4CROSSLINK; - - if (L4 == 0) - return 0; // NOTHING ro Q on - - return (CountFramesQueuedOnSession(L4)); -} - -DllExport int APIENTRY MONCount(int stream) -{ -// Returns number of monitor frames available -// (BPQHOST function 7 (part)). - - BPQVECSTRUC * SESS; - - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - - return C_Q_COUNT(&SESS->HOSTTRACEQ); -} - - -DllExport int APIENTRY GetCallsign(int stream, char * callsign) -{ - // Returns call connected on stream (BPQHOST function 8 (part)). - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - TRANSPORTENTRY * Partner; - UCHAR Call[11] = "SWITCH "; - UCHAR * AXCall = NULL; - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - GetSemaphore(&Semaphore, 26); - - if (L4 == 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - Partner = L4->L4CROSSLINK; - - if (Partner) - { - // CONNECTED OUT - GET TARGET SESSION - - if (Partner->L4CIRCUITTYPE & BPQHOST) - { - AXCall = &Partner->L4USER[0]; - } - else if (Partner->L4CIRCUITTYPE & L2LINK) - { - struct _LINKTABLE * LINK = Partner->L4TARGET.LINK; - - if (LINK) - AXCall = LINK->LINKCALL; - - if (Partner->L4CIRCUITTYPE & UPLINK) - { - // IF UPLINK, SHOULD USE SESSION CALL, IN CASE *** LINKED HAS BEEN USED - - AXCall = &Partner->L4USER[0]; - } - } - else if (Partner->L4CIRCUITTYPE & PACTOR) - { - // PACTOR Type - Frames are queued on the Port Entry - - EXTPORTDATA * EXTPORT = Partner->L4TARGET.EXTPORT; - - if (EXTPORT) - AXCall = &EXTPORT->ATTACHEDSESSIONS[Partner->KAMSESSION]->L4USER[0]; - - } - else - { - // MUST BE NODE SESSION - - // ANOTHER NODE - - // IF THE HOST IS THE UPLINKING STATION, WE NEED THE TARGET CALL - - if (L4->L4CIRCUITTYPE & UPLINK) - { - struct DEST_LIST *DEST = Partner->L4TARGET.DEST; - - if (DEST) - AXCall = &DEST->DEST_CALL[0]; - } - else - AXCall = Partner->L4USER; - } - if (AXCall) - ConvFromAX25(AXCall, Call); - } - - memcpy(callsign, Call, 10); - - FreeSemaphore(&Semaphore); - return 0; -} - -DllExport int APIENTRY GetConnectionInfo(int stream, char * callsign, - int * port, int * sesstype, int * paclen, - int * maxframe, int * l4window) -{ - // Return the Secure Session Flag rather than not connected - - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4; - TRANSPORTENTRY * Partner; - UCHAR Call[11] = "SWITCH "; - UCHAR * AXCall; - Check_Timer(); - - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return 0; - - SESS = &BPQHOSTVECTOR[stream]; - L4 = SESS->HOSTSESSION; - - GetSemaphore(&Semaphore, 27); - - if (L4 == 0) - { - FreeSemaphore(&Semaphore); - return 0; - } - - Partner = L4->L4CROSSLINK; - - // Return the Secure Session Flag rather than not connected - - // AL = Radio port on which channel is connected (or zero) - // AH = SESSION TYPE BITS - // EBX = L2 paclen for the radio port - // ECX = L2 maxframe for the radio port - // EDX = L4 window size (if L4 circuit, or zero) or -1 if not connected - // ES:DI = CALLSIGN - - *port = 0; - *sesstype = 0; - *paclen = 0; - *maxframe = 0; - *l4window = 0; - if (L4->SESSPACLEN) - *paclen = L4->SESSPACLEN; - else - *paclen = 256; - - if (Partner) - { - // CONNECTED OUT - GET TARGET SESSION - - *l4window = Partner->L4WINDOW; - *sesstype = Partner->L4CIRCUITTYPE; - - if (Partner->L4CIRCUITTYPE & BPQHOST) - { - AXCall = &Partner->L4USER[0]; - } - else if (Partner->L4CIRCUITTYPE & L2LINK) - { - struct _LINKTABLE * LINK = Partner->L4TARGET.LINK; - - // EXTRACT PORT AND MAXFRAME - - *port = LINK->LINKPORT->PORTNUMBER; - *maxframe = LINK->LINKWINDOW; - *l4window = 0; - - AXCall = LINK->LINKCALL; - - if (Partner->L4CIRCUITTYPE & UPLINK) - { - // IF UPLINK, SHOULD USE SESSION CALL, IN CASE *** LINKED HAS BEEN USED - - AXCall = &Partner->L4USER[0]; - } - } - else if (Partner->L4CIRCUITTYPE & PACTOR) - { - // PACTOR Type - Frames are queued on the Port Entry - - EXTPORTDATA * EXTPORT = Partner->L4TARGET.EXTPORT; - - *port = EXTPORT->PORTCONTROL.PORTNUMBER; - AXCall = &EXTPORT->ATTACHEDSESSIONS[Partner->KAMSESSION]->L4USER[0]; - - } - else - { - // MUST BE NODE SESSION - - // ANOTHER NODE - - // IF THE HOST IS THE UPLINKING STATION, WE NEED THE TARGET CALL - - if (L4->L4CIRCUITTYPE & UPLINK) - { - struct DEST_LIST *DEST = Partner->L4TARGET.DEST; - - AXCall = &DEST->DEST_CALL[0]; - } - else - AXCall = Partner->L4USER; - } - ConvFromAX25(AXCall, Call); - } - - memcpy(callsign, Call, 10); - - FreeSemaphore(&Semaphore); - - if (Partner) - return Partner->Secure_Session; - - return 0; -} - - -DllExport int APIENTRY SetAppl(int stream, int flags, int mask) -{ -// Sets Application Flags and Mask for stream. (BPQHOST function 1) -// AH = 1 Set application mask to value in EDX (or even DX if 16 -// applications are ever to be supported). -// -// Set application flag(s) to value in CL (or CX). -// whether user gets connected/disconnected messages issued -// by the node etc. - - - BPQVECSTRUC * PORTVEC; - stream--; - - if (stream < 0 || stream > 63) - return (0); - - PORTVEC=&BPQHOSTVECTOR[stream]; - - PORTVEC->HOSTAPPLFLAGS = flags; - PORTVEC->HOSTAPPLMASK = mask; - - // If either is non-zero, set allocated and Process. This gets round problem with - // stations that don't call allocate stream - - if (flags || mask) - { - if ((PORTVEC->HOSTFLAGS & 128) == 0) // Not allocated - { - PORTVEC->STREAMOWNER=GetCurrentProcessId(); - memcpy(&PORTVEC->PgmName[0], pgm, 31); - PORTVEC->HOSTFLAGS = 128; // SET ALLOCATED BIT, clear others - } - } - - return (0); -} - -DllExport struct PORTCONTROL * APIENTRY GetPortTableEntry(int portslot) // Kept for Legacy apps -{ - struct PORTCONTROL * PORTVEC=PORTTABLE; - - if (portslot>NUMBEROFPORTS) - portslot=NUMBEROFPORTS; - - while (--portslot > 0) - PORTVEC=PORTVEC->PORTPOINTER; - - return PORTVEC; -} - -// Proc below renamed to avoid confusion with GetPortTableEntryFromPortNum - -DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot) -{ - struct PORTCONTROL * PORTVEC=PORTTABLE; - - if (portslot>NUMBEROFPORTS) - portslot=NUMBEROFPORTS; - - while (--portslot > 0) - PORTVEC=PORTVEC->PORTPOINTER; - - return PORTVEC; -} - -struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum) -{ - struct PORTCONTROL * PORTVEC=PORTTABLE; - - do - { - if (PORTVEC->PORTNUMBER == portnum) - return PORTVEC; - - PORTVEC=PORTVEC->PORTPOINTER; - } - while (PORTVEC); - - return NULL; -} - -DllExport UCHAR * APIENTRY GetPortDescription(int portslot, char * Desc) -{ - struct PORTCONTROL * PORTVEC=PORTTABLE; - - if (portslot>NUMBEROFPORTS) - portslot=NUMBEROFPORTS; - - while (--portslot > 0) - PORTVEC=PORTVEC->PORTPOINTER; - - memcpy(Desc, PORTVEC->PORTDESCRIPTION, 30); - Desc[30]=0; - - return 0; -} - -// Standard serial port handling routines, used by lots of modules. - -int OpenCOMMPort(struct TNCINFO * conn, char * Port, int Speed, BOOL Quiet) -{ - if (conn->WEB_COMMSSTATE == NULL) - conn->WEB_COMMSSTATE = zalloc(100); - - if (Port == NULL) - return (FALSE); - - conn->hDevice = OpenCOMPort(Port, Speed, TRUE, TRUE, Quiet, 0); - - if (conn->hDevice == 0) - { - sprintf(conn->WEB_COMMSSTATE,"%s Open failed - Error %d", Port, GetLastError()); - if (conn->xIDC_COMMSSTATE) - SetWindowText(conn->xIDC_COMMSSTATE, conn->WEB_COMMSSTATE); - - return (FALSE); - } - - sprintf(conn->WEB_COMMSSTATE,"%s Open", Port); - - if (conn->xIDC_COMMSSTATE) - SetWindowText(conn->xIDC_COMMSSTATE, conn->WEB_COMMSSTATE); - - return TRUE; -} - - - -#ifdef WIN32 - -HANDLE OpenCOMPort(char * pPort, int speed, BOOL SetDTR, BOOL SetRTS, BOOL Quiet, int Stopbits) -{ - char szPort[80]; - BOOL fRetVal ; - COMMTIMEOUTS CommTimeOuts ; - int Err; - char buf[100]; - HANDLE fd; - DCB dcb; - - // if Port Name starts COM, convert to \\.\COM or ports above 10 wont work - - if (_memicmp(pPort, "COM", 3) == 0) - { - char * pp = (char *)pPort; - int p = atoi(&pp[3]); - sprintf( szPort, "\\\\.\\COM%d", p); - } - else - strcpy(szPort, pPort); - - // open COMM device - - fd = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (fd == (HANDLE) -1) - { - if (Quiet == 0) - { - Debugprintf("%s could not be opened %d", pPort, GetLastError()); - } - return (FALSE); - } - - Err = GetFileType(fd); - - // setup device buffers - - SetupComm(fd, 4096, 4096 ) ; - - // purge any information in the buffer - - PurgeComm(fd, PURGE_TXABORT | PURGE_RXABORT | - PURGE_TXCLEAR | PURGE_RXCLEAR ) ; - - // set up for overlapped I/O - - CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ; - CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ; - CommTimeOuts.ReadTotalTimeoutConstant = 0 ; - CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ; -// CommTimeOuts.WriteTotalTimeoutConstant = 0 ; - CommTimeOuts.WriteTotalTimeoutConstant = 500 ; - SetCommTimeouts(fd, &CommTimeOuts ) ; - - dcb.DCBlength = sizeof( DCB ) ; - - GetCommState(fd, &dcb ) ; - - dcb.BaudRate = speed; - dcb.ByteSize = 8; - dcb.Parity = 0; - dcb.StopBits = TWOSTOPBITS; - dcb.StopBits = Stopbits; - - // setup hardware flow control - - dcb.fOutxDsrFlow = 0; - dcb.fDtrControl = DTR_CONTROL_DISABLE ; - - dcb.fOutxCtsFlow = 0; - dcb.fRtsControl = RTS_CONTROL_DISABLE ; - - // setup software flow control - - dcb.fInX = dcb.fOutX = 0; - dcb.XonChar = 0; - dcb.XoffChar = 0; - dcb.XonLim = 100 ; - dcb.XoffLim = 100 ; - - // other various settings - - dcb.fBinary = TRUE ; - dcb.fParity = FALSE; - - fRetVal = SetCommState(fd, &dcb); - - if (fRetVal) - { - if (SetDTR) - EscapeCommFunction(fd, SETDTR); - else - EscapeCommFunction(fd, CLRDTR); - - if (SetRTS) - EscapeCommFunction(fd, SETRTS); - else - EscapeCommFunction(fd, CLRRTS); - } - else - { - sprintf(buf,"%s Setup Failed %d ", pPort, GetLastError()); - - WritetoConsoleLocal(buf); - OutputDebugString(buf); - CloseHandle(fd); - return 0; - } - - return fd; - -} - -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error); - -int ReadCOMBlock(HANDLE fd, char * Block, int MaxLength) -{ - BOOL Error; - return ReadCOMBlockEx(fd, Block, MaxLength, &Error); -} - -// version to pass read error back to caller - -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error) -{ - BOOL fReadStat ; - COMSTAT ComStat ; - DWORD dwErrorFlags; - DWORD dwLength; - BOOL ret; - - if (fd == NULL) - return 0; - - // only try to read number of bytes in queue - - ret = ClearCommError(fd, &dwErrorFlags, &ComStat); - - if (ret == 0) - { - int Err = GetLastError(); - *Error = TRUE; - return 0; - } - - - dwLength = min((DWORD) MaxLength, ComStat.cbInQue); - - if (dwLength > 0) - { - fReadStat = ReadFile(fd, Block, dwLength, &dwLength, NULL) ; - - if (!fReadStat) - { - dwLength = 0 ; - ClearCommError(fd, &dwErrorFlags, &ComStat ) ; - } - } - - *Error = FALSE; - - return dwLength; -} - - -BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite) -{ - BOOL fWriteStat; - DWORD BytesWritten; - DWORD ErrorFlags; - COMSTAT ComStat; - - fWriteStat = WriteFile(fd, Block, BytesToWrite, - &BytesWritten, NULL ); - - if ((!fWriteStat) || (BytesToWrite != BytesWritten)) - { - int Err = GetLastError(); - ClearCommError(fd, &ErrorFlags, &ComStat); - return FALSE; - } - return TRUE; -} - -VOID CloseCOMPort(HANDLE fd) -{ - if (fd == NULL) - return; - - SetCommMask(fd, 0); - - // drop DTR - - COMClearDTR(fd); - - // purge any outstanding reads/writes and close device handle - - PurgeComm(fd, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ; - - CloseHandle(fd); - fd = NULL; -} - - -VOID COMSetDTR(HANDLE fd) -{ - EscapeCommFunction(fd, SETDTR); -} - -VOID COMClearDTR(HANDLE fd) -{ - EscapeCommFunction(fd, CLRDTR); -} - -VOID COMSetRTS(HANDLE fd) -{ - EscapeCommFunction(fd, SETRTS); -} - -VOID COMClearRTS(HANDLE fd) -{ - EscapeCommFunction(fd, CLRRTS); -} - - -#else - -static struct speed_struct -{ - int user_speed; - speed_t termios_speed; -} speed_table[] = { - {300, B300}, - {600, B600}, - {1200, B1200}, - {2400, B2400}, - {4800, B4800}, - {9600, B9600}, - {19200, B19200}, - {38400, B38400}, - {57600, B57600}, - {115200, B115200}, - {-1, B0} -}; - - -HANDLE OpenCOMPort(VOID * pPort, int speed, BOOL SetDTR, BOOL SetRTS, BOOL Quiet, int Stopbits) -{ - char Port[256]; - char buf[100]; - - // Linux Version. - - int fd; - int hwflag = 0; - u_long param=1; - struct termios term; - struct speed_struct *s; - - if ((UINT)pPort < 256) - sprintf(Port, "%s/com%d", BPQDirectory, (int)pPort); - else - strcpy(Port, pPort); - - if ((fd = open(Port, O_RDWR | O_NDELAY)) == -1) - { - if (Quiet == 0) - { - perror("Com Open Failed"); - sprintf(buf," %s could not be opened \n", Port); - WritetoConsoleLocal(buf); - Debugprintf(buf); - } - return 0; - } - - // Validate Speed Param - - for (s = speed_table; s->user_speed != -1; s++) - if (s->user_speed == speed) - break; - - if (s->user_speed == -1) - { - fprintf(stderr, "tty_speed: invalid speed %d\n", speed); - return FALSE; - } - - if (tcgetattr(fd, &term) == -1) - { - perror("tty_speed: tcgetattr"); - return FALSE; - } - - cfmakeraw(&term); - cfsetispeed(&term, s->termios_speed); - cfsetospeed(&term, s->termios_speed); - - if (tcsetattr(fd, TCSANOW, &term) == -1) - { - perror("tty_speed: tcsetattr"); - return FALSE; - } - - ioctl(fd, FIONBIO, ¶m); - - Debugprintf("LinBPQ Port %s fd %d", Port, fd); - - if (SetDTR) - { - COMSetDTR(fd); - } - else - { - COMClearDTR(fd); - } - - if (SetRTS) - { - COMSetRTS(fd); - } - else - { - COMClearRTS(fd); - } - return fd; -} - -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error); - -int ReadCOMBlock(HANDLE fd, char * Block, int MaxLength) -{ - BOOL Error; - return ReadCOMBlockEx(fd, Block, MaxLength, &Error); -} - -// version to pass read error back to caller - -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error) -{ - int Length; - - if (fd == 0) - { - *Error = 1; - return 0; - } - - errno = 22222; // to catch zero read (?? file closed ??) - - Length = read(fd, Block, MaxLength); - - *Error = 0; - - if (Length == 0 && errno == 22222) // seems to be result of unpluging USB - { -// printf("KISS read returned zero len and no errno\n"); - *Error = 1; - return 0; - } - - if (Length < 0) - { - if (errno != 11 && errno != 35) // Would Block - { - perror("read"); - printf("Handle %d Errno %d Len %d\n", fd, errno, Length); - *Error = errno; - } - return 0; - } - - return Length; -} - -BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite) -{ - // Some systems seem to have a very small max write size - - int ToSend = BytesToWrite; - int Sent = 0, ret; - - while (ToSend) - { - ret = write(fd, &Block[Sent], ToSend); - - if (ret >= ToSend) - return TRUE; - - if (ret == -1) - { - if (errno != 11 && errno != 35) // Would Block - return FALSE; - - usleep(10000); - ret = 0; - } - - Sent += ret; - ToSend -= ret; - } - return TRUE; -} - -VOID CloseCOMPort(HANDLE fd) -{ - if (fd == 0) - return; - - close(fd); - fd = 0; -} - -VOID COMSetDTR(HANDLE fd) -{ - int status; - - ioctl(fd, TIOCMGET, &status); - status |= TIOCM_DTR; - ioctl(fd, TIOCMSET, &status); -} - -VOID COMClearDTR(HANDLE fd) -{ - int status; - - ioctl(fd, TIOCMGET, &status); - status &= ~TIOCM_DTR; - ioctl(fd, TIOCMSET, &status); -} - -VOID COMSetRTS(HANDLE fd) -{ - int status; - - ioctl(fd, TIOCMGET, &status); - status |= TIOCM_RTS; - ioctl(fd, TIOCMSET, &status); -} - -VOID COMClearRTS(HANDLE fd) -{ - int status; - - ioctl(fd, TIOCMGET, &status); - status &= ~TIOCM_RTS; - ioctl(fd, TIOCMSET, &status); -} - -#endif - - -int MaxNodes; -int MaxRoutes; -int NodeLen; -int RouteLen; -struct DEST_LIST * Dests; -struct ROUTE * Routes; - -FILE *file; - -int DoRoutes() -{ - char digis[30] = ""; - int count, len; - char Normcall[10], Portcall[10]; - char line[80]; - - for (count=0; countNEIGHBOUR_CALL[0] != 0) - { - len=ConvFromAX25(Routes->NEIGHBOUR_CALL,Normcall); - Normcall[len]=0; - - if (Routes->NEIGHBOUR_DIGI1[0] != 0) - { - memcpy(digis," VIA ",5); - - len=ConvFromAX25(Routes->NEIGHBOUR_DIGI1,Portcall); - Portcall[len]=0; - strcpy(&digis[5],Portcall); - - if (Routes->NEIGHBOUR_DIGI2[0] != 0) - { - len=ConvFromAX25(Routes->NEIGHBOUR_DIGI2,Portcall); - Portcall[len]=0; - strcat(digis," "); - strcat(digis,Portcall); - } - } - else - digis[0] = 0; - - len=sprintf(line, - "ROUTE ADD %s %d %d %s %d %d %d %d %d\n", - Normcall, - Routes->NEIGHBOUR_PORT, - Routes->NEIGHBOUR_QUAL, digis, - Routes->NBOUR_MAXFRAME, - Routes->NBOUR_FRACK, - Routes->NBOUR_PACLEN, - Routes->INP3Node | (Routes->NoKeepAlive << 2), - Routes->OtherendsRouteQual); - - fputs(line, file); - } - - Routes+=1; - } - - return (0); -} - -int DoNodes() -{ - int count, len, cursor, i; - char Normcall[10], Portcall[10]; - char line[80]; - char Alias[7]; - - Dests-=1; - - for (count=0; countNRROUTE[0].ROUT_NEIGHBOUR == 0) - continue; - - { - len=ConvFromAX25(Dests->DEST_CALL,Normcall); - Normcall[len]=0; - - memcpy(Alias,Dests->DEST_ALIAS,6); - - Alias[6]=0; - - for (i=0;i<6;i++) - { - if (Alias[i] == ' ') - Alias[i] = 0; - } - - cursor=sprintf(line,"NODE ADD %s:%s ", Alias,Normcall); - - if (Dests->NRROUTE[0].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[0].ROUT_NEIGHBOUR->INP3Node == 0) - { - len=ConvFromAX25( - Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); - Portcall[len]=0; - - len=sprintf(&line[cursor],"%s %d %d ", - Portcall, - Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, - Dests->NRROUTE[0].ROUT_QUALITY); - - cursor+=len; - - if (Dests->NRROUTE[0].ROUT_OBSCOUNT > 127) - { - len=sprintf(&line[cursor],"! "); - cursor+=len; - } - } - - if (Dests->NRROUTE[1].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[1].ROUT_NEIGHBOUR->INP3Node == 0) - { - len=ConvFromAX25( - Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); - Portcall[len]=0; - - len=sprintf(&line[cursor],"%s %d %d ", - Portcall, - Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, - Dests->NRROUTE[1].ROUT_QUALITY); - - cursor+=len; - - if (Dests->NRROUTE[1].ROUT_OBSCOUNT > 127) - { - len=sprintf(&line[cursor],"! "); - cursor+=len; - } - } - - if (Dests->NRROUTE[2].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[2].ROUT_NEIGHBOUR->INP3Node == 0) - { - len=ConvFromAX25( - Dests->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); - Portcall[len]=0; - - len=sprintf(&line[cursor],"%s %d %d ", - Portcall, - Dests->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, - Dests->NRROUTE[2].ROUT_QUALITY); - - cursor+=len; - - if (Dests->NRROUTE[2].ROUT_OBSCOUNT > 127) - { - len=sprintf(&line[cursor],"! "); - cursor+=len; - } - } - - if (cursor > 30) - { - line[cursor++]='\n'; - line[cursor++]=0; - fputs(line, file); - } - } - } - return (0); -} - -void SaveMH() -{ - char FN[250]; - struct PORTCONTROL * PORT = PORTTABLE; - FILE *file; - - if (BPQDirectory[0] == 0) - { - strcpy(FN, "MHSave.txt"); - } - else - { - strcpy(FN,BPQDirectory); - strcat(FN,"/"); - strcat(FN,"MHSave.txt"); - } - - if ((file = fopen(FN, "w")) == NULL) - return; - - while (PORT) - { - int Port = 0; - char * ptr; - - MHSTRUC * MH = PORT->PORTMHEARD; - - int count = MHENTRIES; - int n; - char Normcall[20]; - char From[10]; - char DigiList[100]; - char * Output; - int len; - char Digi = 0; - - - // Note that the MHDIGIS field may contain rubbish. You have to check End of Address bit to find - // how many digis there are - - if (MH == NULL) - continue; - - fprintf(file, "Port:%d\n", PORT->PORTNUMBER); - - while (count--) - { - if (MH->MHCALL[0] == 0) - break; - - Digi = 0; - - len = ConvFromAX25(MH->MHCALL, Normcall); - Normcall[len] = 0; - - n = 8; // Max number of digi-peaters - - ptr = &MH->MHCALL[6]; // End of Address bit - - Output = &DigiList[0]; - - if ((*ptr & 1) == 0) - { - // at least one digi - - strcpy(Output, "via "); - Output += 4; - - while ((*ptr & 1) == 0) - { - // MORE TO COME - - From[ConvFromAX25(ptr + 1, From)] = 0; - Output += sprintf((char *)Output, "%s", From); - - ptr += 7; - n--; - - if (n == 0) - break; - - // See if digi actioned - put a * on last actioned - - if (*ptr & 0x80) - { - if (*ptr & 1) // if last address, must need * - { - *(Output++) = '*'; - Digi = '*'; - } - - else - if ((ptr[7] & 0x80) == 0) // Repeased by next? - { - *(Output++) = '*'; // No, so need * - Digi = '*'; - } - - - } - *(Output++) = ','; - } - *(--Output) = 0; // remove last comma - } - else - *(Output) = 0; - - // if we used a digi set * on call and display via string - - - if (Digi) - Normcall[len++] = Digi; - else - DigiList[0] = 0; // Dont show list if not used - - Normcall[len++] = 0; - - ptr = FormatMH(MH, 'U'); - - ptr[15] = 0; - - if (MH->MHDIGI) - fprintf(file, "%d %6d %-10s%c %s %s|%s|%s\n", (int)MH->MHTIME, MH->MHCOUNT, Normcall, MH->MHDIGI, ptr, DigiList, MH->MHLocator, MH->MHFreq); - else - fprintf(file, "%d %6d %-10s%c %s %s|%s|%s\n", (int)MH->MHTIME, MH->MHCOUNT, Normcall, ' ', ptr, DigiList, MH->MHLocator, MH->MHFreq); - - MH++; - } - PORT = PORT->PORTPOINTER; - } - - fclose(file); - - return; -} - - -int APIENTRY SaveNodes () -{ - char FN[250]; - - Routes = NEIGHBOURS; - RouteLen = ROUTE_LEN; - MaxRoutes = MAXNEIGHBOURS; - - Dests = DESTS; - NodeLen = DEST_LIST_LEN; - MaxNodes = MAXDESTS; - - // Set up pointer to BPQNODES file - - if (BPQDirectory[0] == 0) - { - strcpy(FN,"BPQNODES.dat"); - } - else - { - strcpy(FN,BPQDirectory); - strcat(FN,"/"); - strcat(FN,"BPQNODES.dat"); - } - - if ((file = fopen(FN, "w")) == NULL) - return FALSE; - - DoRoutes(); - DoNodes(); - - fclose(file); - - return (0); -} - -DllExport int APIENTRY ClearNodes () -{ - char FN[250]; - - // Set up pointer to BPQNODES file - - if (BPQDirectory[0] == 0) - { - strcpy(FN,"BPQNODES.dat"); - } - else - { - strcpy(FN,BPQDirectory); - strcat(FN,"/"); - strcat(FN,"BPQNODES.dat"); - } - - if ((file = fopen(FN, "w")) == NULL) - return FALSE; - - fclose(file); - - return (0); -} -char * FormatUptime(int Uptime) - { - struct tm * TM; - static char UPTime[50]; - time_t szClock = Uptime * 60; - - TM = gmtime(&szClock); - - sprintf(UPTime, "Uptime (Days Hours Mins) %.2d:%.2d:%.2d\r", - TM->tm_yday, TM->tm_hour, TM->tm_min); - - return UPTime; - } - -static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - - -char * FormatMH(PMHSTRUC MH, char Format) -{ - struct tm * TM; - static char MHTime[50]; - time_t szClock; - char LOC[7]; - - memcpy(LOC, MH->MHLocator, 6); - LOC[6] = 0; - - if (Format == 'U' || Format =='L') - szClock = MH->MHTIME; - else - szClock = time(NULL) - MH->MHTIME; - - if (Format == 'L') - TM = localtime(&szClock); - else - TM = gmtime(&szClock); - - if (Format == 'U' || Format =='L') - sprintf(MHTime, "%s %02d %.2d:%.2d:%.2d %s %s", - month[TM->tm_mon], TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec, MH->MHFreq, LOC); - else - sprintf(MHTime, "%.2d:%.2d:%.2d:%.2d %s %s", - TM->tm_yday, TM->tm_hour, TM->tm_min, TM->tm_sec, MH->MHFreq, LOC); - - return MHTime; - -} - - -Dll VOID APIENTRY CreateOneTimePassword(char * Password, char * KeyPhrase, int TimeOffset) -{ - // Create a time dependent One Time Password from the KeyPhrase - // TimeOffset is used when checking to allow for slight variation in clocks - - time_t NOW = time(NULL); - UCHAR Hash[16]; - char Key[1000]; - int i, chr; - - NOW = NOW/30 + TimeOffset; // Only Change every 30 secs - - sprintf(Key, "%s%x", KeyPhrase, (int)NOW); - - md5(Key, Hash); - - for (i=0; i<16; i++) - { - chr = (Hash[i] & 31); - if (chr > 9) chr += 7; - - Password[i] = chr + 48; - } - - Password[16] = 0; - return; -} - -Dll BOOL APIENTRY CheckOneTimePassword(char * Password, char * KeyPhrase) -{ - char CheckPassword[17]; - int Offsets[10] = {0, -1, 1, -2, 2, -3, 3, -4, 4}; - int i, Pass; - - if (strlen(Password) < 16) - Pass = atoi(Password); - - for (i = 0; i < 9; i++) - { - CreateOneTimePassword(CheckPassword, KeyPhrase, Offsets[i]); - - if (strlen(Password) < 16) - { - // Using a numeric extract - - long long Val; - - memcpy(&Val, CheckPassword, 8); - Val = Val %= 1000000; - - if (Pass == Val) - return TRUE; - } - else - if (memcmp(Password, CheckPassword, 16) == 0) - return TRUE; - } - - return FALSE; -} - - -DllExport BOOL ConvToAX25Ex(unsigned char * callsign, unsigned char * ax25call) -{ - // Allows SSID's of 'T and 'R' - - int i; - - memset(ax25call,0x40,6); // in case short - ax25call[6]=0x60; // default SSID - - for (i=0;i<7;i++) - { - if (callsign[i] == '-') - { - // - // process ssid and return - // - - if (callsign[i+1] == 'T') - { - ax25call[6]=0x42; - return TRUE; - } - - if (callsign[i+1] == 'R') - { - ax25call[6]=0x44; - return TRUE; - } - i = atoi(&callsign[i+1]); - - if (i < 16) - { - ax25call[6] |= i<<1; - return (TRUE); - } - return (FALSE); - } - - if (callsign[i] == 0 || callsign[i] == 13 || callsign[i] == ' ' || callsign[i] == ',') - { - // - // End of call - no ssid - // - return (TRUE); - } - - ax25call[i] = callsign[i] << 1; - } - - // - // Too many chars - // - - return (FALSE); -} - - -DllExport BOOL ConvToAX25(unsigned char * callsign, unsigned char * ax25call) -{ - int i; - - memset(ax25call,0x40,6); // in case short - ax25call[6]=0x60; // default SSID - - for (i=0;i<7;i++) - { - if (callsign[i] == '-') - { - // - // process ssid and return - // - i = atoi(&callsign[i+1]); - - if (i < 16) - { - ax25call[6] |= i<<1; - return (TRUE); - } - return (FALSE); - } - - if (callsign[i] == 0 || callsign[i] == 13 || callsign[i] == ' ' || callsign[i] == ',') - { - // - // End of call - no ssid - // - return (TRUE); - } - - ax25call[i] = callsign[i] << 1; - } - - // - // Too many chars - // - - return (FALSE); -} - - -DllExport int ConvFromAX25(unsigned char * incall,unsigned char * outcall) -{ - int in,out=0; - unsigned char chr; - - memset(outcall,0x20,10); - - for (in=0;in<6;in++) - { - chr=incall[in]; - if (chr == 0x40) - break; - chr >>= 1; - outcall[out++]=chr; - } - - chr=incall[6]; // ssid - - if (chr == 0x42) - { - outcall[out++]='-'; - outcall[out++]='T'; - return out; - } - - if (chr == 0x44) - { - outcall[out++]='-'; - outcall[out++]='R'; - return out; - } - - chr >>= 1; - chr &= 15; - - if (chr > 0) - { - outcall[out++]='-'; - if (chr > 9) - { - chr-=10; - outcall[out++]='1'; - } - chr+=48; - outcall[out++]=chr; - } - return (out); -} - -unsigned short int compute_crc(unsigned char *buf, int txlen); - -SOCKADDR_IN reportdest = {0}; - -SOCKET ReportSocket = 0; - -SOCKADDR_IN Chatreportdest = {0}; - -extern char LOCATOR[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char MAPCOMMENT[]; // Locator for Reporting - may be Maidenhead or LAT:LON -extern char LOC[7]; // Maidenhead Locator for Reporting -extern char ReportDest[7]; - - -VOID SendReportMsg(char * buff, int txlen) -{ - unsigned short int crc = compute_crc(buff, txlen); - - crc ^= 0xffff; - - buff[txlen++] = (crc&0xff); - buff[txlen++] = (crc>>8); - - sendto(ReportSocket, buff, txlen, 0, (LPSOCKADDR)&reportdest, sizeof(reportdest)); - -} -VOID SendLocation() -{ - MESSAGE AXMSG = {0}; - PMESSAGE AXPTR = &AXMSG; - char Msg[512]; - int Len; - - Len = sprintf(Msg, "%s %s
%s", LOCATOR, VersionString, MAPCOMMENT); - -#ifdef LINBPQ - Len = sprintf(Msg, "%s L%s
%s", LOCATOR, VersionString, MAPCOMMENT); -#endif -#ifdef MACBPQ - Len = sprintf(Msg, "%s M%s
%s", LOCATOR, VersionString, MAPCOMMENT); -#endif -#ifdef FREEBSD - Len = sprintf(Msg, "%s F%s
%s", LOCATOR, VersionString, MAPCOMMENT); -#endif - - if (Len > 256) - Len = 256; - - // Block includes the Msg Header (7 bytes), Len Does not! - - memcpy(AXPTR->DEST, ReportDest, 7); - memcpy(AXPTR->ORIGIN, MYCALL, 7); - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->L2DATA, Msg, Len); - - SendReportMsg((char *)&AXMSG.DEST, Len + 16); - - return; - -} - - - - -VOID SendMH(struct TNCINFO * TNC, char * call, char * freq, char * LOC, char * Mode) -{ - MESSAGE AXMSG; - PMESSAGE AXPTR = &AXMSG; - char Msg[100]; - int Len; - - if (ReportSocket == 0 || LOCATOR[0] == 0) - return; - - Len = sprintf(Msg, "MH %s,%s,%s,%s", call, freq, LOC, Mode); - - // Block includes the Msg Header (7 bytes), Len Does not! - - memcpy(AXPTR->DEST, ReportDest, 7); - if (TNC->PortRecord->PORTCONTROL.PORTCALL[0]) - memcpy(AXPTR->ORIGIN, TNC->PortRecord->PORTCONTROL.PORTCALL, 7); - else - memcpy(AXPTR->ORIGIN, MYCALL, 7); - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->L2DATA, Msg, Len); - - SendReportMsg((char *)&AXMSG.DEST, Len + 16) ; - - return; - -} - -time_t TimeLastNRRouteSent = 0; - -char NRRouteMessage[256]; -int NRRouteLen = 0; - - -VOID SendNETROMRoute(struct PORTCONTROL * PORT, unsigned char * axcall) -{ - // Called to update Link Map when a NODES Broadcast is received - // Batch to reduce Load - - MESSAGE AXMSG; - PMESSAGE AXPTR = &AXMSG; - char Msg[300]; - int Len; - char Call[10]; - char Report[16]; - time_t Now = time(NULL); - int NeedSend = FALSE; - - - if (ReportSocket == 0 || LOCATOR[0] == 0) - return; - - Call[ConvFromAX25(axcall, Call)] = 0; - - sprintf(Report, "%s,%d,", Call, PORT->PORTTYPE); - - if (Now - TimeLastNRRouteSent > 60) - NeedSend = TRUE; - - if (strstr(NRRouteMessage, Report) == 0) // reported recently - strcat(NRRouteMessage, Report); - - if (strlen(NRRouteMessage) > 230 || NeedSend) - { - Len = sprintf(Msg, "LINK %s", NRRouteMessage); - - // Block includes the Msg Header (7 bytes), Len Does not! - - memcpy(AXPTR->DEST, ReportDest, 7); - memcpy(AXPTR->ORIGIN, MYCALL, 7); - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->L2DATA, Msg, Len); - - SendReportMsg((char *)&AXMSG.DEST, Len + 16) ; - - TimeLastNRRouteSent = Now; - NRRouteMessage[0] = 0; - } - - return; - -} - -DllExport char * APIENTRY GetApplCall(int Appl) -{ - if (Appl < 1 || Appl > NumberofAppls ) return NULL; - - return (UCHAR *)(&APPLCALLTABLE[Appl-1].APPLCALL_TEXT); -} -DllExport char * APIENTRY GetApplAlias(int Appl) -{ - if (Appl < 1 || Appl > NumberofAppls ) return NULL; - - return (UCHAR *)(&APPLCALLTABLE[Appl-1].APPLALIAS_TEXT); -} - -DllExport int32_t APIENTRY GetApplQual(int Appl) -{ - if (Appl < 1 || Appl > NumberofAppls ) return 0; - - return (APPLCALLTABLE[Appl-1].APPLQUAL); -} - -char * GetApplCallFromName(char * App) -{ - int i; - char PaddedAppl[13] = " "; - - memcpy(PaddedAppl, App, (int)strlen(App)); - - for (i = 0; i < NumberofAppls; i++) - { - if (memcmp(&APPLCALLTABLE[i].APPLCMD, PaddedAppl, 12) == 0) - return &APPLCALLTABLE[i].APPLCALL_TEXT[0]; - } - return NULL; -} - - -DllExport char * APIENTRY GetApplName(int Appl) -{ - if (Appl < 1 || Appl > NumberofAppls ) return NULL; - - return (UCHAR *)(&APPLCALLTABLE[Appl-1].APPLCMD); -} - -DllExport int APIENTRY GetNumberofPorts() -{ - return (NUMBEROFPORTS); -} - -DllExport int APIENTRY GetPortNumber(int portslot) -{ - struct PORTCONTROL * PORTVEC=PORTTABLE; - - if (portslot>NUMBEROFPORTS) - portslot=NUMBEROFPORTS; - - while (--portslot > 0) - PORTVEC=PORTVEC->PORTPOINTER; - - return PORTVEC->PORTNUMBER; - -} - -DllExport char * APIENTRY GetVersionString() -{ -// return ((char *)&VersionStringWithBuild); - return ((char *)&VersionString); -} - -#ifdef MACBPQ - -//Fiddle till I find a better solution - -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060 -int __sync_lock_test_and_set(int * ptr, int val) -{ - *ptr = val; - return 0; -} -#endif // __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ -#endif // MACBPQ - - - -void GetSemaphore(struct SEM * Semaphore, int ID) -{ - // - // Wait for it to be free - // - - if (Semaphore->Flag != 0) - { - Semaphore->Clashes++; - } - -loop1: - - while (Semaphore->Flag != 0) - { - Sleep(10); - } - - // - // try to get semaphore - // - -#ifdef WIN32 - - { - if (InterlockedExchange(&Semaphore->Flag, 1) != 0) // Failed to get it - goto loop1; // try again;; - } - -#else - - if (__sync_lock_test_and_set(&Semaphore->Flag, 1) != 0) - - // Failed to get it - goto loop1; // try again; - -#endif - - //Ok. got it - - Semaphore->Gets++; - Semaphore->SemProcessID = GetCurrentProcessId(); - Semaphore->SemThreadID = GetCurrentThreadId(); - SemHeldByAPI = ID; - - return; -} - -void FreeSemaphore(struct SEM * Semaphore) -{ - if (Semaphore->Flag == 0) - Debugprintf("Free Semaphore Called when Sem not held"); - - Semaphore->Rels++; - Semaphore->Flag = 0; - - return; -} - -#ifdef WIN32 - -#include "DbgHelp.h" -/* -USHORT WINAPI RtlCaptureStackBackTrace( - __in ULONG FramesToSkip, - __in ULONG FramesToCapture, - __out PVOID *BackTrace, - __out_opt PULONG BackTraceHash -); -*/ -#endif - -void printStack(void) -{ -#ifdef WIN32 -#ifdef _DEBUG // So we can use on 98/2K - - unsigned int i; - void * stack[ 100 ]; - unsigned short frames; - SYMBOL_INFO * symbol; - HANDLE process; - - Debugprintf("Stack Backtrace"); - - process = GetCurrentProcess(); - - SymInitialize( process, NULL, TRUE ); - - frames = RtlCaptureStackBackTrace( 0, 60, stack, NULL ); - symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 ); - symbol->MaxNameLen = 255; - symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); - - for( i = 0; i < frames; i++ ) - { - SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); - - Debugprintf( "%i: %s - %p", frames - i - 1, symbol->Name, symbol->Address ); - } - - free(symbol); - -#endif -#endif -} - -pthread_t ResolveUpdateThreadId = 0; - -char NodeMapServer[80] = "update.g8bpq.net"; -char ChatMapServer[80] = "chatupdate.g8bpq.net"; - -VOID ResolveUpdateThread(void * Unused) -{ - struct hostent * HostEnt1; - struct hostent * HostEnt2; - - ResolveUpdateThreadId = GetCurrentThreadId(); - - while (TRUE) - { - if (pthread_equal(ResolveUpdateThreadId, GetCurrentThreadId()) == FALSE) - { - Debugprintf("Resolve Update thread %x redundant - closing", GetCurrentThreadId()); - return; - } - - // Resolve name to address - - Debugprintf("Resolving %s", NodeMapServer); - HostEnt1 = gethostbyname (NodeMapServer); -// HostEnt1 = gethostbyname ("192.168.1.64"); - - if (HostEnt1) - memcpy(&reportdest.sin_addr.s_addr,HostEnt1->h_addr,4); - - Debugprintf("Resolving %s", ChatMapServer); - HostEnt2 = gethostbyname (ChatMapServer); -// HostEnt2 = gethostbyname ("192.168.1.64"); - - if (HostEnt2) - memcpy(&Chatreportdest.sin_addr.s_addr,HostEnt2->h_addr,4); - - if (HostEnt1 && HostEnt2) - { - Sleep(1000 * 60 * 30); - continue; - } - - Debugprintf("Resolve Failed for update.g8bpq.net or chatmap.g8bpq.net"); - Sleep(1000 * 60 * 5); - } -} - - -VOID OpenReportingSockets() -{ - u_long param=1; - BOOL bcopt=TRUE; - - if (LOCATOR[0]) - { - // Enable Node Map Reports - - ReportTimer = 600; - - ReportSocket = socket(AF_INET,SOCK_DGRAM,0); - - if (ReportSocket == INVALID_SOCKET) - { - Debugprintf("Failed to create Reporting socket"); - ReportSocket = 0; - return; - } - - ioctlsocket (ReportSocket, FIONBIO, ¶m); - setsockopt (ReportSocket, SOL_SOCKET, SO_BROADCAST, (const char FAR *)&bcopt,4); - - reportdest.sin_family = AF_INET; - reportdest.sin_port = htons(81); - ConvToAX25("DUMMY-1", ReportDest); - } - - // Set up Chat Report even if no LOCATOR reportdest.sin_family = AF_INET; - // Socket must be opened in MailChat Process - - Chatreportdest.sin_family = AF_INET; - Chatreportdest.sin_port = htons(81); - - _beginthread(ResolveUpdateThread, 0, NULL); -} - -VOID WriteMiniDumpThread(); - -time_t lastMiniDump = 0; - -void WriteMiniDump() -{ -#ifdef WIN32 - - _beginthread(WriteMiniDumpThread, 0, 0); - Sleep(3000); -} - -VOID WriteMiniDumpThread() -{ - HANDLE hFile; - BOOL ret; - char FN[256]; - struct tm * TM; - time_t Now = time(NULL); - - if (lastMiniDump == Now) // Not more than one per second - { - Debugprintf("minidump suppressed"); - return; - } - - lastMiniDump = Now; - - TM = gmtime(&Now); - - sprintf(FN, "%s/Logs/MiniDump%d%02d%02d%02d%02d%02d.dmp", BPQDirectory, - TM->tm_year + 1900, TM->tm_mon +1, TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec); - - hFile = CreateFile(FN, GENERIC_READ | GENERIC_WRITE, - 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) - { - // Create the minidump - - ret = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), - hFile, MiniDumpNormal, 0, 0, 0 ); - - if(!ret) - Debugprintf("MiniDumpWriteDump failed. Error: %u", GetLastError()); - else - Debugprintf("Minidump %s created.", FN); - CloseHandle(hFile); - } -#endif -} - -// UI Util Code - -#pragma pack(1) - -typedef struct _MESSAGEX -{ -// BASIC LINK LEVEL MESSAGE BUFFER LAYOUT - - struct _MESSAGEX * CHAIN; - - UCHAR PORT; - USHORT LENGTH; - - UCHAR DEST[7]; - UCHAR ORIGIN[7]; - -// MAY BE UP TO 56 BYTES OF DIGIS - - UCHAR CTL; - UCHAR PID; - UCHAR DATA[256]; - UCHAR PADDING[56]; // In case he have Digis - -}MESSAGEX, *PMESSAGEX; - -#pragma pack() - - -int PortNum[33] = {0}; // Tab nunber to port - -char * UIUIDigi[33]= {0}; -char * UIUIDigiAX[33] = {0}; // ax.25 version of digistring -int UIUIDigiLen[33] = {0}; // Length of AX string - -char UIUIDEST[33][11] = {0}; // Dest for Beacons - -char UIAXDEST[33][7] = {0}; - - -UCHAR FN[33][256]; // Filename -int Interval[33]; // Beacon Interval (Mins) -int MinCounter[33]; // Interval Countdown - -BOOL SendFromFile[33]; -char Message[33][1000]; // Beacon Text - -VOID SendUIBeacon(int Port); - -BOOL RunUI = TRUE; - -VOID UIThread(void * Unused) -{ - int Port, MaxPorts = GetNumberofPorts(); - - Sleep(60000); - - while (RunUI) - { - int sleepInterval = 60000; - - for (Port = 1; Port <= MaxPorts; Port++) - { - if (MinCounter[Port]) - { - MinCounter[Port]--; - - if (MinCounter[Port] == 0) - { - MinCounter[Port] = Interval[Port]; - SendUIBeacon(Port); - - // pause beteen beacons but adjust sleep interval to suit - - Sleep(10000); - sleepInterval -= 10000; - } - } - } - - while (sleepInterval <= 0) // just in case we have a crazy config - sleepInterval += 60000; - - Sleep(sleepInterval); - } -} - -int UIRemoveLF(char * Message, int len) -{ - // Remove lf chars - - char * ptr1, * ptr2; - - ptr1 = ptr2 = Message; - - while (len-- > 0) - { - *ptr2 = *ptr1; - - if (*ptr1 == '\r') - if (*(ptr1+1) == '\n') - { - ptr1++; - len--; - } - ptr1++; - ptr2++; - } - - return (int)(ptr2 - Message); -} - - - - -VOID UISend_AX_Datagram(UCHAR * Msg, DWORD Len, UCHAR Port, UCHAR * HWADDR, BOOL Queue) -{ - MESSAGEX AXMSG; - PMESSAGEX AXPTR = &AXMSG; - int DataLen = Len; - struct PORTCONTROL * PORT = GetPortTableEntryFromSlot(Port); - - // Block includes the Msg Header (7 or 11 bytes), Len Does not! - - memcpy(AXPTR->DEST, HWADDR, 7); - - // Get BCALL or PORTCALL if set - - if (PORT && PORT->PORTBCALL[0]) - memcpy(AXPTR->ORIGIN, PORT->PORTBCALL, 7); - else if (PORT && PORT->PORTCALL[0]) - memcpy(AXPTR->ORIGIN, PORT->PORTCALL, 7); - else - memcpy(AXPTR->ORIGIN, MYCALL, 7); - - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - if (UIUIDigi[Port]) - { - // This port has a digi string - - int DigiLen = UIUIDigiLen[Port]; - UCHAR * ptr; - - memcpy(&AXPTR->CTL, UIUIDigiAX[Port], DigiLen); - - ptr = (UCHAR *)AXPTR; - ptr += DigiLen; - AXPTR = (PMESSAGEX)ptr; - - Len += DigiLen; - } - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->DATA, Msg, DataLen); - -// if (Queue) -// QueueRaw(Port, &AXMSG, Len + 16); -// else - SendRaw(Port, (char *)&AXMSG.DEST, Len + 16); - - return; - -} - - - -VOID SendUIBeacon(int Port) -{ - char UIMessage[1024]; - int Len = (int)strlen(Message[Port]); - int Index = 0; - - if (SendFromFile[Port]) - { - FILE * hFile; - - hFile = fopen(FN[Port], "rb"); - - if (hFile == 0) - return; - - Len = (int)fread(UIMessage, 1, 1024, hFile); - - fclose(hFile); - - } - else - strcpy(UIMessage, Message[Port]); - - Len = UIRemoveLF(UIMessage, Len); - - while (Len > 256) - { - UISend_AX_Datagram(&UIMessage[Index], 256, Port, UIAXDEST[Port], TRUE); - Index += 256; - Len -= 256; - Sleep(2000); - } - UISend_AX_Datagram(&UIMessage[Index], Len, Port, UIAXDEST[Port], TRUE); -} - -#ifndef LINBPQ - -typedef struct tag_dlghdr -{ - HWND hwndTab; // tab control - HWND hwndDisplay; // current child dialog box - RECT rcDisplay; // display rectangle for the tab control - - DLGTEMPLATE *apRes[33]; - -} DLGHDR; - -DLGTEMPLATE * WINAPI DoLockDlgRes(LPCSTR lpszResName); - -#endif - -HWND hwndDlg; -int PageCount; -int CurrentPage=0; // Page currently on show in tabbed Dialog - - -VOID WINAPI OnSelChanged(HWND hwndDlg); -VOID WINAPI OnChildDialogInit(HWND hwndDlg); - -#define ICC_STANDARD_CLASSES 0x00004000 - -HWND hwndDisplay; - -#define ID_TEST 102 -#define IDD_DIAGLOG1 103 -#define IDC_FROMFILE 1022 -#define IDC_EDIT1 1054 -#define IDC_FILENAME 1054 -#define IDC_EDIT2 1055 -#define IDC_MESSAGE 1055 -#define IDC_EDIT3 1056 -#define IDC_INTERVAL 1056 -#define IDC_EDIT4 1057 -#define IDC_UIDEST 1057 -#define IDC_FILE 1058 -#define IDC_TAB1 1059 -#define IDC_UIDIGIS 1059 -#define IDC_PORTNAME 1060 - -extern HKEY REGTREE; -HBRUSH bgBrush; - -VOID SetupUI(int Port) -{ - char DigiString[100], * DigiLeft; - - ConvToAX25(UIUIDEST[Port], &UIAXDEST[Port][0]); - - UIUIDigiLen[Port] = 0; - - if (UIUIDigi[Port]) - { - UIUIDigiAX[Port] = zalloc(100); - strcpy(DigiString, UIUIDigi[Port]); - DigiLeft = strlop(DigiString,','); - - while(DigiString[0]) - { - ConvToAX25(DigiString, &UIUIDigiAX[Port][UIUIDigiLen[Port]]); - UIUIDigiLen[Port] += 7; - - if (DigiLeft) - { - memmove(DigiString, DigiLeft, (int)strlen(DigiLeft) + 1); - DigiLeft = strlop(DigiString,','); - } - else - DigiString[0] = 0; - } - } -} - -#ifndef LINBPQ - -VOID SaveIntValue(config_setting_t * group, char * name, int value) -{ - config_setting_t *setting; - - setting = config_setting_add(group, name, CONFIG_TYPE_INT); - if(setting) - config_setting_set_int(setting, value); -} - -VOID SaveStringValue(config_setting_t * group, char * name, char * value) -{ - config_setting_t *setting; - - setting = config_setting_add(group, name, CONFIG_TYPE_STRING); - if (setting) - config_setting_set_string(setting, value); - -} - -#endif - -config_t cfg; - -VOID SaveUIConfig() -{ - config_setting_t *root, *group, *UIGroup; - int Port, MaxPort = GetNumberofPorts(); - char ConfigName[256]; - - if (BPQDirectory[0] == 0) - { - strcpy(ConfigName,"UIUtil.cfg"); - } - else - { - strcpy(ConfigName,BPQDirectory); - strcat(ConfigName,"/"); - strcat(ConfigName,"UIUtil.cfg"); - } - - // Get rid of old config before saving - - config_init(&cfg); - - root = config_root_setting(&cfg); - - group = config_setting_add(root, "main", CONFIG_TYPE_GROUP); - - UIGroup = config_setting_add(group, "UIUtil", CONFIG_TYPE_GROUP); - - for (Port = 1; Port <= MaxPort; Port++) - { - char Key[20]; - - sprintf(Key, "Port%d", Port); - group = config_setting_add(UIGroup, Key, CONFIG_TYPE_GROUP); - - SaveStringValue(group, "UIDEST", &UIUIDEST[Port][0]); - SaveStringValue(group, "FileName", &FN[Port][0]); - SaveStringValue(group, "Message", &Message[Port][0]); - SaveStringValue(group, "Digis", UIUIDigi[Port]); - - SaveIntValue(group, "Interval", Interval[Port]); - SaveIntValue(group, "SendFromFile", SendFromFile[Port]); - } - - if(!config_write_file(&cfg, ConfigName)) - { - fprintf(stderr, "Error while writing file.\n"); - config_destroy(&cfg); - return; - } - - config_destroy(&cfg); -} - -VOID GetUIConfig() -{ -#ifdef LINBPQ - - char Key[100]; - char CfgFN[256]; - char Digis[100]; - struct stat STAT; - - config_t cfg; - config_setting_t *group; - int Port, MaxPort = GetNumberofPorts(); - - memset((void *)&cfg, 0, sizeof(config_t)); - - config_init(&cfg); - - if (BPQDirectory[0] == 0) - { - strcpy(CfgFN,"UIUtil.cfg"); - } - else - { - strcpy(CfgFN,BPQDirectory); - strcat(CfgFN,"/"); - strcat(CfgFN,"UIUtil.cfg"); - } - - if (stat(CfgFN, &STAT) == -1) - { - Debugprintf("UIUtil Config File not found\n"); - return; - } - - if(!config_read_file(&cfg, CfgFN)) - { - fprintf(stderr, "UI Util Config Error Line %d - %s\n", config_error_line(&cfg), config_error_text(&cfg)); - - config_destroy(&cfg); - return; - } - - group = config_lookup(&cfg, "main"); - - if (group) - { - for (Port = 1; Port <= MaxPort; Port++) - { - sprintf(Key, "main.UIUtil.Port%d", Port); - - group = config_lookup (&cfg, Key); - - if (group) - { - GetStringValue(group, "UIDEST", &UIUIDEST[Port][0]); - GetStringValue(group, "FileName", &FN[Port][0]); - GetStringValue(group, "Message", &Message[Port][0]); - GetStringValue(group, "Digis", Digis); - UIUIDigi[Port] = _strdup(Digis); - - Interval[Port] = GetIntValue(group, "Interval"); - MinCounter[Port] = Interval[Port]; - - SendFromFile[Port] = GetIntValue(group, "SendFromFile"); - - SetupUI(Port); - } - } - } - -#else - - int retCode, Vallen, Type, i; - char Key[80]; - char Size[80]; - HKEY hKey; - RECT Rect; - - wsprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\UIUtil"); - - retCode = RegOpenKeyEx (REGTREE, Key, 0, KEY_QUERY_VALUE, &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"Size",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - sscanf(Size,"%d,%d,%d,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom); - - RegCloseKey(hKey); - } - - for (i=1; i<=32; i++) - { - wsprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\UIUtil\\UIPort%d", i); - - retCode = RegOpenKeyEx (REGTREE, - Key, - 0, - KEY_QUERY_VALUE, - &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=0; - RegQueryValueEx(hKey,"Digis",0, - (ULONG *)&Type, NULL, (ULONG *)&Vallen); - - if (Vallen) - { - UIUIDigi[i] = malloc(Vallen); - RegQueryValueEx(hKey,"Digis",0, - (ULONG *)&Type, UIUIDigi[i], (ULONG *)&Vallen); - } - - Vallen=4; - retCode = RegQueryValueEx(hKey, "Interval", 0, - (ULONG *)&Type, (UCHAR *)&Interval[i], (ULONG *)&Vallen); - - MinCounter[i] = Interval[i]; - - Vallen=4; - retCode = RegQueryValueEx(hKey, "SendFromFile", 0, - (ULONG *)&Type, (UCHAR *)&SendFromFile[i], (ULONG *)&Vallen); - - - Vallen=10; - retCode = RegQueryValueEx(hKey, "UIDEST", 0, &Type, &UIUIDEST[i][0], &Vallen); - - Vallen=255; - retCode = RegQueryValueEx(hKey, "FileName", 0, &Type, &FN[i][0], &Vallen); - - Vallen=999; - retCode = RegQueryValueEx(hKey, "Message", 0, &Type, &Message[i][0], &Vallen); - - SetupUI(i); - - RegCloseKey(hKey); - } - } - - SaveUIConfig(); - -#endif - - _beginthread(UIThread, 0, NULL); - -} - -#ifndef LINBPQ - -INT_PTR CALLBACK ChildDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ -// This processes messages from controls on the tab subpages - int Command; - - int retCode, disp; - char Key[80]; - HKEY hKey; - BOOL OK; - OPENFILENAME ofn; - char Digis[100]; - - int Port = PortNum[CurrentPage]; - - - switch (message) - { - case WM_NOTIFY: - - switch (((LPNMHDR)lParam)->code) - { - case TCN_SELCHANGE: - OnSelChanged(hDlg); - return TRUE; - // More cases on WM_NOTIFY switch. - case NM_CHAR: - return TRUE; - } - - break; - case WM_INITDIALOG: - OnChildDialogInit( hDlg); - return (INT_PTR)TRUE; - - case WM_CTLCOLORDLG: - - return (LONG)bgBrush; - - case WM_CTLCOLORSTATIC: - { - HDC hdcStatic = (HDC)wParam; - SetTextColor(hdcStatic, RGB(0, 0, 0)); - SetBkMode(hdcStatic, TRANSPARENT); - return (LONG)bgBrush; - } - - - case WM_COMMAND: - - Command = LOWORD(wParam); - - if (Command == 2002) - return TRUE; - - switch (Command) - { - case IDC_FILE: - - memset(&ofn, 0, sizeof (OPENFILENAME)); - ofn.lStructSize = sizeof (OPENFILENAME); - ofn.hwndOwner = hDlg; - ofn.lpstrFile = &FN[Port][0]; - ofn.nMaxFile = 250; - ofn.lpstrTitle = "File to send as beacon"; - ofn.lpstrInitialDir = BPQDirectory; - - if (GetOpenFileName(&ofn)) - SetDlgItemText(hDlg, IDC_FILENAME, &FN[Port][0]); - - break; - - - case IDOK: - - GetDlgItemText(hDlg, IDC_UIDEST, &UIUIDEST[Port][0], 10); - - if (UIUIDigi[Port]) - { - free(UIUIDigi[Port]); - UIUIDigi[Port] = NULL; - } - - if (UIUIDigiAX[Port]) - { - free(UIUIDigiAX[Port]); - UIUIDigiAX[Port] = NULL; - } - - GetDlgItemText(hDlg, IDC_UIDIGIS, Digis, 99); - - UIUIDigi[Port] = _strdup(Digis); - - GetDlgItemText(hDlg, IDC_FILENAME, &FN[Port][0], 255); - GetDlgItemText(hDlg, IDC_MESSAGE, &Message[Port][0], 1000); - - Interval[Port] = GetDlgItemInt(hDlg, IDC_INTERVAL, &OK, FALSE); - - MinCounter[Port] = Interval[Port]; - - SendFromFile[Port] = IsDlgButtonChecked(hDlg, IDC_FROMFILE); - - wsprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\UIUtil\\UIPort%d", PortNum[CurrentPage]); - - retCode = RegCreateKeyEx(REGTREE, - Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - retCode = RegSetValueEx(hKey, "UIDEST", 0, REG_SZ,(BYTE *)&UIUIDEST[Port][0], (int)strlen(&UIUIDEST[Port][0])); - retCode = RegSetValueEx(hKey, "FileName", 0, REG_SZ,(BYTE *)&FN[Port][0], (int)strlen(&FN[Port][0])); - retCode = RegSetValueEx(hKey, "Message", 0, REG_SZ,(BYTE *)&Message[Port][0], (int)strlen(&Message[Port][0])); - retCode = RegSetValueEx(hKey, "Interval", 0, REG_DWORD,(BYTE *)&Interval[Port], 4); - retCode = RegSetValueEx(hKey, "SendFromFile", 0, REG_DWORD,(BYTE *)&SendFromFile[Port], 4); - retCode = RegSetValueEx(hKey, "Digis",0, REG_SZ, Digis, (int)strlen(Digis)); - - RegCloseKey(hKey); - } - - SetupUI(Port); - - SaveUIConfig(); - - return (INT_PTR)TRUE; - - - case IDCANCEL: - - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - - case ID_TEST: - - SendUIBeacon(Port); - return TRUE; - - } - break; - - } - return (INT_PTR)FALSE; -} - - - -VOID WINAPI OnTabbedDialogInit(HWND hDlg) -{ - DLGHDR *pHdr = (DLGHDR *) LocalAlloc(LPTR, sizeof(DLGHDR)); - DWORD dwDlgBase = GetDialogBaseUnits(); - int cxMargin = LOWORD(dwDlgBase) / 4; - int cyMargin = HIWORD(dwDlgBase) / 8; - - TC_ITEM tie; - RECT rcTab; - - int i, pos, tab = 0; - INITCOMMONCONTROLSEX init; - - char PortNo[60]; - struct _EXTPORTDATA * PORTVEC; - - hwndDlg = hDlg; // Save Window Handle - - // Save a pointer to the DLGHDR structure. - -#define GWL_USERDATA (-21) - - SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) pHdr); - - // Create the tab control. - - - init.dwICC = ICC_STANDARD_CLASSES; - init.dwSize=sizeof(init); - i=InitCommonControlsEx(&init); - - pHdr->hwndTab = CreateWindow(WC_TABCONTROL, "", WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, - 0, 0, 100, 100, hwndDlg, NULL, hInstance, NULL); - - if (pHdr->hwndTab == NULL) { - - // handle error - - } - - // Add a tab for each of the child dialog boxes. - - tie.mask = TCIF_TEXT | TCIF_IMAGE; - - tie.iImage = -1; - - for (i = 1; i <= NUMBEROFPORTS; i++) - { - // Only allow UI on ax.25 ports - - PORTVEC = (struct _EXTPORTDATA * )GetPortTableEntryFromSlot(i); - - if (PORTVEC->PORTCONTROL.PORTTYPE == 16) // EXTERNAL - if (PORTVEC->PORTCONTROL.PROTOCOL == 10) // Pactor/WINMOR - if (PORTVEC->PORTCONTROL.UICAPABLE == 0) - continue; - - wsprintf(PortNo, "Port %2d", GetPortNumber(i)); - PortNum[tab] = i; - - tie.pszText = PortNo; - TabCtrl_InsertItem(pHdr->hwndTab, tab, &tie); - - pHdr->apRes[tab++] = DoLockDlgRes("PORTPAGE"); - } - - PageCount = tab; - - // Determine the bounding rectangle for all child dialog boxes. - - SetRectEmpty(&rcTab); - - for (i = 0; i < PageCount; i++) - { - if (pHdr->apRes[i]->cx > rcTab.right) - rcTab.right = pHdr->apRes[i]->cx; - - if (pHdr->apRes[i]->cy > rcTab.bottom) - rcTab.bottom = pHdr->apRes[i]->cy; - - } - - MapDialogRect(hwndDlg, &rcTab); - -// rcTab.right = rcTab.right * LOWORD(dwDlgBase) / 4; - -// rcTab.bottom = rcTab.bottom * HIWORD(dwDlgBase) / 8; - - // Calculate how large to make the tab control, so - - // the display area can accomodate all the child dialog boxes. - - TabCtrl_AdjustRect(pHdr->hwndTab, TRUE, &rcTab); - - OffsetRect(&rcTab, cxMargin - rcTab.left, cyMargin - rcTab.top); - - // Calculate the display rectangle. - - CopyRect(&pHdr->rcDisplay, &rcTab); - - TabCtrl_AdjustRect(pHdr->hwndTab, FALSE, &pHdr->rcDisplay); - - // Set the size and position of the tab control, buttons, - - // and dialog box. - - SetWindowPos(pHdr->hwndTab, NULL, rcTab.left, rcTab.top, rcTab.right - rcTab.left, rcTab.bottom - rcTab.top, SWP_NOZORDER); - - // Move the Buttons to bottom of page - - pos=rcTab.left+cxMargin; - - - // Size the dialog box. - - SetWindowPos(hwndDlg, NULL, 0, 0, rcTab.right + cyMargin + 2 * GetSystemMetrics(SM_CXDLGFRAME), - rcTab.bottom + 2 * cyMargin + 2 * GetSystemMetrics(SM_CYDLGFRAME) + GetSystemMetrics(SM_CYCAPTION), - SWP_NOMOVE | SWP_NOZORDER); - - // Simulate selection of the first item. - - OnSelChanged(hwndDlg); - -} - -// DoLockDlgRes - loads and locks a dialog template resource. - -// Returns a pointer to the locked resource. - -// lpszResName - name of the resource - -DLGTEMPLATE * WINAPI DoLockDlgRes(LPCSTR lpszResName) -{ - HRSRC hrsrc = FindResource(hInstance, lpszResName, RT_DIALOG); - HGLOBAL hglb = LoadResource(hInstance, hrsrc); - - return (DLGTEMPLATE *) LockResource(hglb); -} - -//The following function processes the TCN_SELCHANGE notification message for the main dialog box. The function destroys the dialog box for the outgoing page, if any. Then it uses the CreateDialogIndirect function to create a modeless dialog box for the incoming page. - -// OnSelChanged - processes the TCN_SELCHANGE notification. - -// hwndDlg - handle of the parent dialog box - -VOID WINAPI OnSelChanged(HWND hwndDlg) -{ - char PortDesc[40]; - int Port; - - DLGHDR *pHdr = (DLGHDR *) GetWindowLong(hwndDlg, GWL_USERDATA); - - CurrentPage = TabCtrl_GetCurSel(pHdr->hwndTab); - - // Destroy the current child dialog box, if any. - - if (pHdr->hwndDisplay != NULL) - - DestroyWindow(pHdr->hwndDisplay); - - // Create the new child dialog box. - - pHdr->hwndDisplay = CreateDialogIndirect(hInstance, pHdr->apRes[CurrentPage], hwndDlg, ChildDialogProc); - - hwndDisplay = pHdr->hwndDisplay; // Save - - Port = PortNum[CurrentPage]; - // Fill in the controls - - GetPortDescription(PortNum[CurrentPage], PortDesc); - - SetDlgItemText(hwndDisplay, IDC_PORTNAME, PortDesc); - - CheckDlgButton(hwndDisplay, IDC_FROMFILE, SendFromFile[Port]); - - SetDlgItemInt(hwndDisplay, IDC_INTERVAL, Interval[Port], FALSE); - - SetDlgItemText(hwndDisplay, IDC_UIDEST, &UIUIDEST[Port][0]); - SetDlgItemText(hwndDisplay, IDC_UIDIGIS, UIUIDigi[Port]); - - - - SetDlgItemText(hwndDisplay, IDC_FILENAME, &FN[Port][0]); - SetDlgItemText(hwndDisplay, IDC_MESSAGE, &Message[Port][0]); - - ShowWindow(pHdr->hwndDisplay, SW_SHOWNORMAL); - -} - - -//The following function processes the WM_INITDIALOG message for each of the child dialog boxes. You cannot specify the position of a dialog box created using the CreateDialogIndirect function. This function uses the SetWindowPos function to position the child dialog within the tab control's display area. - -// OnChildDialogInit - Positions the child dialog box to fall - -// within the display area of the tab control. - -VOID WINAPI OnChildDialogInit(HWND hwndDlg) -{ - HWND hwndParent = GetParent(hwndDlg); - DLGHDR *pHdr = (DLGHDR *) GetWindowLong(hwndParent, GWL_USERDATA); - - SetWindowPos(hwndDlg, HWND_TOP, pHdr->rcDisplay.left, pHdr->rcDisplay.top, 0, 0, SWP_NOSIZE); -} - - - -LRESULT CALLBACK UIWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - HKEY hKey=0; - - switch (message) { - - case WM_INITDIALOG: - OnTabbedDialogInit(hWnd); - return (INT_PTR)TRUE; - - case WM_NOTIFY: - - switch (((LPNMHDR)lParam)->code) - { - case TCN_SELCHANGE: - OnSelChanged(hWnd); - return TRUE; - // More cases on WM_NOTIFY switch. - case NM_CHAR: - return TRUE; - } - - break; - - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - case WM_CTLCOLORSTATIC: - { - HDC hdcStatic = (HDC)wParam; - SetTextColor(hdcStatic, RGB(0, 0, 0)); - SetBkMode(hdcStatic, TRANSPARENT); - - return (LONG)bgBrush; - } - - case WM_COMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) { - - case IDOK: - - return TRUE; - - default: - - return 0; - } - - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); // Remember, these are... - wmEvent = HIWORD(wParam); // ...different for Win32! - - switch (wmId) - { - case SC_RESTORE: - - return (DefWindowProc(hWnd, message, wParam, lParam)); - - case SC_MINIMIZE: - - if (MinimizetoTray) - return ShowWindow(hWnd, SW_HIDE); - else - return (DefWindowProc(hWnd, message, wParam, lParam)); - - break; - - default: - return (DefWindowProc(hWnd, message, wParam, lParam)); - } - - case WM_CLOSE: - return(DestroyWindow(hWnd)); - - default: - return (DefWindowProc(hWnd, message, wParam, lParam)); - - } - - return (0); -} - -#endif - -extern struct DATAMESSAGE * REPLYBUFFER; -char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...); -void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - char FN[250]; - FILE *hFile; - struct stat STAT; - struct PORTCONTROL * PORT = PORTTABLE; - char PortList[256] = ""; - - while (PORT) - { - if (PORT->CTEXT) - { - free(PORT->CTEXT); - PORT->CTEXT = 0; - } - - if (BPQDirectory[0] == 0) - sprintf(FN, "Port%dCTEXT.txt", PORT->PORTNUMBER); - else - sprintf(FN, "%s/Port%dCTEXT.txt", BPQDirectory, PORT->PORTNUMBER); - - if (stat(FN, &STAT) == -1) - { - PORT = PORT->PORTPOINTER; - continue; - } - - hFile = fopen(FN, "rb"); - - if (hFile) - { - char * ptr; - - PORT->CTEXT = zalloc(STAT.st_size + 1); - fread(PORT->CTEXT , 1, STAT.st_size, hFile); - fclose(hFile); - - // convert CRLF or LF to CR - - while (ptr = strstr(PORT->CTEXT, "\r\n")) - memmove(ptr, ptr + 1, strlen(ptr)); - - // Now has LF - - while (ptr = strchr(PORT->CTEXT, '\n')) - *ptr = '\r'; - - - sprintf(PortList, "%s,%d", PortList, PORT->PORTNUMBER); - } - - PORT = PORT->PORTPOINTER; - } - - if (Session) - { - Bufferptr = Cmdprintf(Session, Bufferptr, "CTEXT Read for ports %s\r", &PortList[1]); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); - } - else - Debugprintf("CTEXT Read for ports %s\r", &PortList[1]); -} - - - - - diff --git a/FreeDATA-DESKTOP-TGEL8RC.c b/FreeDATA-DESKTOP-TGEL8RC.c deleted file mode 100644 index 0c4173e..0000000 --- a/FreeDATA-DESKTOP-TGEL8RC.c +++ /dev/null @@ -1,4124 +0,0 @@ -/* -Copyright 2001-2018 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// Interface to allow G8BPQ switch to use FreeData TNC - - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include - -#ifndef WIN32 -#ifndef MACBPQ -#include -#endif -#endif - -#include "CHeaders.h" -#include "bpq32.h" -#include "tncinfo.h" - -#define SD_BOTH 0x02 - -int KillTNC(struct TNCINFO * TNC); -int RestartTNC(struct TNCINFO * TNC); - -int (WINAPI FAR *GetModuleFileNameExPtr)(); -extern int (WINAPI FAR *EnumProcessesPtr)(); -static int Socket_Data(int sock, int error, int eventcode); -VOID MoveWindows(struct TNCINFO * TNC); -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen); -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); -VOID SendInitScript(struct TNCINFO * TNC); -int ProcessEscape(UCHAR * TXMsg); -static void SendPoll(struct TNCINFO * TNC); -void SendMode(struct TNCINFO * TNC); -static int ConnecttoFreeData(int port); -void ConnectTNCPort(struct TNCINFO * TNC); -int FreeDataSendCommand(struct TNCINFO * TNC, char * data); -static void SendPing(struct TNCINFO * TNC, char * Call); -static void SendCQ(struct TNCINFO * TNC); -char * stristr (char *ch1, char *ch2); -int zEncode(unsigned char * in, unsigned char * out, int len, unsigned char * Banned); -static void SendDataMsg(struct TNCINFO * TNC, char * Call, char * Msg, int Len); -static int SendAsRaw(struct TNCINFO * TNC, char * Call, char * myCall, char * Msg, int Len); -static int SendAsFile(struct TNCINFO * TNC, char * Call, char * Msg, int Len); -char * byte_base64_encode(char *str, int len); -void xdecodeblock( unsigned char in[4], unsigned char out[3] ); -void FlushData(struct TNCINFO * TNC); -void CountRestarts(struct TNCINFO * TNC); -void StopTNC(struct TNCINFO * TNC); -int FreeDataConnect(struct TNCINFO * TNC, char * Call); -int FreeDataDisconnect(struct TNCINFO * TNC); -int FreeGetData(struct TNCINFO * TNC); -static void SendBeacon(struct TNCINFO * TNC, int Interval); - -static char ClassName[]="FREEDATASTATUS"; -static char WindowTitle[] = "FreeData Modem"; -static int RigControlRow = 205; - -#ifndef WIN32 -#include -#else -#include -#endif - -extern char * PortConfig[33]; -extern int SemHeldByAPI; - -static RECT Rect; - -extern struct TNCINFO * TNCInfo[41]; // Records are Malloc'd - -static int ProcessLine(char * buf, int Port); - -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - -#define MAXRXSIZE 512000 // Sets max size for file transfer (less base64 overhead - -char * gen_uuid() -{ - char v[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - int i; - - //3fb17ebc-bc38-4939-bc8b-74f2443281d4 - //8 dash 4 dash 4 dash 4 dash 12 - - static char buf[37] = {0}; - - //gen random for all spaces because lazy - for (i = 0; i < 36; ++i) - { - buf[i] = v[rand()%16]; - } - - //put dashes in place - buf[8] = '-'; - buf[13] = '-'; - buf[18] = '-'; - buf[23] = '-'; - - //needs end byte - buf[36] = '\0'; - - return buf; -} - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC = TNCInfo[Port]; - char errbuf[256]; - - strcpy(errbuf, buf); - - ptr = strtok(buf, " \t\n\r"); - - if (ptr == NULL) return (TRUE); - - if (*ptr =='#') return (TRUE); // comment - - if (*ptr ==';') return (TRUE); // comment - - - if (_stricmp(buf, "ADDR")) - return FALSE; // Must start with ADDR - - ptr = strtok(NULL, " \t\n\r"); - - BPQport = Port; - p_ipad = ptr; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->FreeDataInfo = zalloc(sizeof(struct FreeDataINFO)); - -// TNC->FreeDataInfo->useBaseCall = 1; // Default - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - if (p_ipad == NULL) - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - WINMORport = atoi(p_port); - - TNC->TCPPort = WINMORport; - - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(WINMORport); - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(WINMORport+1); - - TNC->HostName = malloc(strlen(p_ipad)+1); - - if (TNC->HostName == NULL) return TRUE; - - strcpy(TNC->HostName,p_ipad); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - } - - if (ptr) - { - if (_memicmp(ptr, "PATH", 4) == 0) - { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - } - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "CAPTURE", 7) == 0) - { - TNC->FreeDataInfo->Capture = _strdup(&buf[8]); - strlop(TNC->FreeDataInfo->Capture, 13); - } - else if (_memicmp(buf, "PLAYBACK", 8) == 0) - { - TNC->FreeDataInfo->Playback = _strdup(&buf[9]); - strlop(TNC->FreeDataInfo->Playback, 13); - } - - else if (_memicmp(buf, "LOGDIR ", 7) == 0) - TNC->LogPath = _strdup(&buf[7]); - - else if (_memicmp(buf, "HAMLIBHOST", 10) == 0) - { - TNC->FreeDataInfo->hamlibHost = _strdup(&buf[11]); - strlop(TNC->FreeDataInfo->hamlibHost, 13); - } - - else if (_memicmp(buf, "TuningRange", 11) == 0) - TNC->FreeDataInfo->TuningRange = atoi(&buf[12]); - - else if (_memicmp(buf, "LimitBandWidth", 14) == 0) - TNC->FreeDataInfo->LimitBandWidth = atoi(&buf[14]); - - else if (_memicmp(buf, "HAMLIBPORT", 10) == 0) - TNC->FreeDataInfo->hamlibPort = atoi(&buf[11]); - - else if (_memicmp(buf, "USEBASECALL", 11) == 0) - TNC->FreeDataInfo->useBaseCall = atoi(&buf[12]); - - else if (_memicmp(buf, "RXDIRECTORY", 11) == 0) - { - TNC->FreeDataInfo->RXDir = _strdup(&buf[12]); - strlop(TNC->FreeDataInfo->RXDir, 13); - } - - else if (standardParams(TNC, buf) == FALSE) - strcat(TNC->InitScript, buf); - - } - - return (TRUE); -} - -char * Config; -static char * ptr1, * ptr2; - -int FreeDataGetLine(char * buf) -{ -loop: - - if (ptr2 == NULL) - return 0; - - memcpy(buf, ptr1, ptr2 - ptr1 + 2); - buf[ptr2 - ptr1 + 2] = 0; - ptr1 = ptr2 + 2; - ptr2 = strchr(ptr1, 13); - - if (buf[0] < 0x20) goto loop; - if (buf[0] == '#') goto loop; - if (buf[0] == ';') goto loop; - - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - buf[strlen(buf)] = 13; - - return 1; -} - -BOOL FreeDataReadConfigFile(int Port, int ProcLine()) -{ - char buf[256],errbuf[256]; - - Config = PortConfig[Port]; - - if (Config) - { - // Using config from bpq32.cfg - - if (strlen(Config) == 0) - { - return TRUE; - } - - ptr1 = Config; - ptr2 = strchr(ptr1, 13); - - if (!ProcLine(buf, Port)) - { - WritetoConsoleLocal("\n"); - WritetoConsoleLocal("Bad config record "); - WritetoConsoleLocal(errbuf); - } - } - else - { - sprintf(buf," ** Error - No Configuration info in bpq32.cfg"); - WritetoConsoleLocal(buf); - } - - return (TRUE); -} - - - -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - - - -#define MAXBPQPORTS 32 - -static time_t ltime; - - - -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen) -{ - if (TNC->hDevice) - { - // FreeData mode. Queue to Hostmode driver - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = EncLen; - memcpy(&buffptr->Data[0], Encoded, EncLen); - - C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); - TNC->Streams[Stream].FramesQueued++; - - return; - } -} - - -VOID FreeDataChangeMYC(struct TNCINFO * TNC, char * Call) -{ - UCHAR TXMsg[100]; - int datalen; - - if (strcmp(Call, TNC->CurrentMYC) == 0) - return; // No Change - - strcpy(TNC->CurrentMYC, Call); - - datalen = sprintf(TXMsg, "MYCALL %s\r", Call); -// FreeDataSendCommand(TNC, TXMsg); -} - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int datalen; - PMSGWITHLEN buffptr; -// char txbuff[500]; - unsigned int txlen = 0; - UCHAR * TXMsg; - - size_t Param; - int Stream = 0; - HKEY hKey=0; - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct ScanEntry * Scan; - - if (TNC == NULL) - return 0; // Port not defined - - switch (fn) - { - case 7: - - // 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances - - SendPoll(TNC); - - // Check for buffered data to send - - if (TNC->FreeDataInfo->toSendTimeout) - { - TNC->FreeDataInfo->toSendTimeout--; - if (TNC->FreeDataInfo->toSendTimeout <= 0) - FlushData(TNC); - } - - return 0; - - case 1: // poll - -// FreeDataCheckRX(TNC); - - if (TNC->DAEMONCONNECTED == FALSE && TNC->DAEMONCONNECTING == FALSE) - { - // See if time to reconnect - - time(<ime); - if (ltime - TNC->lasttime > 19 ) - { - TNC->lasttime = ltime; - ConnecttoFreeData(port); - } - } - - - while (TNC->PortRecord->UI_Q) - { - int datalen; - char * Buffer; - char FECMsg[512]; - char Call[12] = " "; - struct _MESSAGE * buffptr; - int CallLen; - char * ptr = FECMsg; - - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - -/* if (TNC->CONNECTED == 0 || - TNC->Streams[0].Connecting || - TNC->Streams[0].Connected) - { - // discard if TNC not connected or sesison active - - ReleaseBuffer(buffptr); - continue; - } -*/ - datalen = buffptr->LENGTH - MSGHDDRLEN; - Buffer = &buffptr->DEST[0]; // Raw Frame - Buffer[datalen] = 0; - - // Frame has ax.25 format header. Convert to Text - - CallLen = ConvFromAX25(Buffer + 7, Call); // Origin - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - *ptr++ = '!'; - - CallLen = ConvFromAX25(Buffer, Call); // Dest - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - Buffer += 14; // TO Digis - datalen -= 14; - - while ((Buffer[-1] & 1) == 0) - { - *ptr++ = ','; - CallLen = ConvFromAX25(Buffer, Call); - memcpy(ptr, Call, CallLen); - ptr += CallLen; - Buffer += 7; // End of addr - datalen -= 7; - } - - *ptr++ = '_'; - *ptr++ = 'U'; // UI Frame - *ptr++ = 0; // delimit calls - - if (Buffer[0] == 3) // UI - { - Buffer += 2; - datalen -= 2; - } - -// FreeDataSendSingleData(TNC, FECMsg, Buffer, datalen); - - ReleaseBuffer(buffptr); - } - - - if (TNC->DiscPending) - { - TNC->DiscPending--; - - if (TNC->DiscPending == 0) - { - // Too long in Disc Pending - Kill and Restart TNC - } - } - - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - { - // Send the DISCONNECT - - FreeDataDisconnect(TNC); - strcpy(TNC->WEB_TNCSTATE, "Disconnecting"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - } - } - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && STREAM->Attached == 0) - { - // New Attach - - int calllen; - char Msg[80]; - - Debugprintf("FreeData New Attach Stream %d", Stream); - - STREAM->Attached = TRUE; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, STREAM->MyCall); - TNC->Streams[Stream].MyCall[calllen] = 0; - - - FreeDataChangeMYC(TNC, TNC->Streams[0].MyCall); - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Stop Scanning - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command(-1, Msg); - } - - if (STREAM->Attached) - CheckForDetach(TNC, Stream, STREAM, TidyClose, ForcedClose, CloseComplete); - - } - - // See if any frames for this port - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->BPQtoPACTOR_Q) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)Q_REM(&STREAM->BPQtoPACTOR_Q); - UCHAR * data = &buffptr->Data[0]; - STREAM->FramesQueued--; - txlen = (int)buffptr->Len; - - SendAsFile(TNC, TNC->FreeDataInfo->farCall, data, txlen); - } - - if (STREAM->PACTORtoBPQ_Q != 0) - { - buffptr = (PMSGWITHLEN)Q_REM(&STREAM->PACTORtoBPQ_Q); - - datalen = (int)buffptr->Len; - - buff->PORT = Stream; // Compatibility with Kam Driver - buff->PID = 0xf0; - memcpy(&buff->L2DATA, &buffptr->Data[0], datalen); // Data goes to + 7, but we have an extra byte - datalen += sizeof(void *) + 4; - - PutLengthinBuffer(buff, datalen); - - ReleaseBuffer(buffptr); - - return (1); - } - - if (STREAM->ReportDISC) // May need a delay so treat as a counter - { - STREAM->ReportDISC--; - if (STREAM->ReportDISC == 0) - { - buff->PORT = Stream; -// STREAM->Connected = 0; -// STREAM->Attached = 0; - return -1; - } - } - } - return (0); - - case 2: // send - - Stream = buff->PORT; - - if (!TNC->TNCCONNECTED) - { - // Send Error Response - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = 36; - memcpy(&buffptr->Data[0], "No Connection to TNC\r", 36); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return 0; // Don't try if not connected - } - - STREAM = &TNC->Streams[Stream]; - - if (TNC->SwallowSignon) - { - TNC->SwallowSignon = FALSE; // Discard *** connected - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - TXMsg = &buff->L2DATA[0]; - TXMsg[txlen] = 0; - - if (STREAM->Connected) - { - STREAM->PacketsSent++; - - SendDataMsg(TNC, TNC->FreeDataInfo->farCall, buff->L2DATA, txlen); - return 1; - } - - if (TNC->FreeDataInfo->Chat) - { - // Chat Mode - Send to other end - - char reply[512] = "m"; - char * p; - int Len; - - if (_stricmp(TXMsg, "/ex\r") == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - TNC->FreeDataInfo->Chat = 0; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Chat with %s ended. \r", TNC->FreeDataInfo->ChatCall); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - // Send as chat message - - //m�;send_message�;123�;64730c5c-d32c-47b4-9b11-c958fd07a185�;hhhhhhhhhhhhhhhhhh - //�;�;plain/text�; - - strlop(TXMsg, 13); - - strcpy(&reply[2], ";send_message"); - strcpy(&reply[16], ";123"); - reply[21] = ';'; - strcpy(&reply[22], gen_uuid()); - sprintf(&reply[59], ";%s\n", TXMsg); - - p = strchr(&reply[59], 0); - - p[1] = ';'; - strcpy(&p[3], ";plain/text"); - p[15] = ';'; - - Len = &p[16] - reply; - - SendAsRaw(TNC, TNC->FreeDataInfo->ChatCall, "", reply, Len); - - return 0; - } - - - - if (_memicmp(&buff->L2DATA[0], "D\r", 2) == 0 || _memicmp(&buff->L2DATA[0], "BYE\r", 4) == 0) - { - STREAM->ReportDISC = TRUE; // Tell Node - TNC->FreeDataInfo->Chat = 0; - return 0; - } - - - // See if Local command (eg RADIO) - - if (_memicmp(&buff->L2DATA[0], "RADIO ", 6) == 0) - { - sprintf(&buff->L2DATA[0], "%d %s", TNC->Port, &buff->L2DATA[6]); - - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK->CIRCUITINDEX, &buff->L2DATA[0])) - { - } - else - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return 1; // No buffers, so ignore - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", &buff->L2DATA[0]); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return 1; - } - - if (_memicmp(&buff->L2DATA[0], "OVERRIDEBUSY", 12) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - TNC->OverrideBusy = TRUE; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} OK\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - if (_memicmp(&buff->L2DATA[0], "PING ", 5) == 0) - { - char * Call = &buff->L2DATA[5]; - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - strlop(Call, 13); - strlop(Call, ' '); - SendPing(TNC, _strupr(Call)); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Ping Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "CQ", 2) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - SendCQ(TNC); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} CQ Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "CHAT ", 5) == 0) - { - char * Call = &buff->L2DATA[5]; - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - strlop(Call, 13); - strlop(Call, ' '); - - TNC->FreeDataInfo->Chat = 1; - memcpy(TNC->FreeDataInfo->ChatCall, _strupr(Call), 10); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Chat with %s. Enter /ex to exit\r", Call); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - - if (_memicmp(&TXMsg[0], "BEACON ", 7) == 0) - { - int Interval = atoi(&TXMsg[7]); - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - SendBeacon(TNC, Interval); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Ok\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - - - - // See if a Connect Command. - - if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect - { - char Connect[80]; - char loppedCall[10]; - char toCall[10]; - - char * ptr = strchr(&buff->L2DATA[2], 13); - - if (ptr) - *ptr = 0; - - // FreeDATA doesn't have the concept of a connection, so need to simulate it between the nodes - _strupr(&buff->L2DATA[2]); - - if (strlen(&buff->L2DATA[2]) > 9) - buff->L2DATA[11] = 0; - - strcpy(TNC->FreeDataInfo->toCall, &buff->L2DATA[2]); - strcpy(loppedCall, TNC->FreeDataInfo->toCall); - if (TNC->FreeDataInfo->useBaseCall) - strlop(loppedCall, '-'); - strcpy(TNC->FreeDataInfo->farCall, loppedCall); - - // MYCALL and Target call are end to end concepts - the TNC cam can only use one call, set at TNC start. and no SSID's - // Messages are sent at TNC level to the tnc call, so we send our tnc call to the other end - - - txlen = sprintf(Connect, "C %s %s %s ", &buff->L2DATA[2], STREAM->MyCall, TNC->FreeDataInfo->ourCall); - - // See if Busy -/* - if (InterlockedCheckBusy(TNC)) - { - // Channel Busy. Unless override set, wait - - if (TNC->OverrideBusy == 0) - { - // Save Command, and wait up to 10 secs - - sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - TNC->ConnectCmd = _strdup(Connect); - TNC->BusyDelay = TNC->BusyWait * 10; // BusyWait secs - return 0; - } - } -*/ - TNC->OverrideBusy = FALSE; - - memset(STREAM->RemoteCall, 0, 10); - strcpy(STREAM->RemoteCall, &buff->L2DATA[2]); - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - -// FreeDataSendCommand(TNC, Connect); - FreeDataConnect(TNC, STREAM->RemoteCall); - STREAM->Connecting = TRUE; - return 0; - - } - - // Normal data. Send to TNC - - // The TNC doesn't have any commands, so send error message - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Not connected\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - // strlop(buff->L2DATA, 13); - // txlen = SendDataMsg(TNC, TNC->, buff->L2DATA); - // FreeDataSendData(TNC, TXMsg, txlen); - - return 0; - - case 3: - - // CHECK IF OK TO SEND (And check TNC Status) - - Stream = (int)(size_t)buff; - - // FreeData TNC can buffer unlimited data - - if (TNC->Streams[Stream].Attached == 0) - return (TNC->TNCCONNECTED != 0) << 8 | 1; - - return ((TNC->TNCCONNECTED != 0) << 8 | TNC->Streams[Stream].Disconnecting << 15); // OK - - - case 4: // reinit7 - - return 0; - - case 5: // Close - - StopTNC(TNC); - return 0; - - case 6: // Scan Stop Interface - - Param = (size_t)buff; - - if (Param == 2) // Check Permission (Shouldn't happen) - { - Debugprintf("Scan Check Permission called on FreeDATA"); - return 1; // OK to change - } - - if (Param == 1) // Request Permission - { - if (!TNC->CONNECTED) - return 0; // No connection so no interlock - - if (TNC->ConnectPending == 0 && TNC->PTTState == 0) - { - TNC->FreeDataInfo->CONOK = 0; - TNC->GavePermission = TRUE; - return 0; // OK to Change - } - - if (TNC->ConnectPending) - TNC->ConnectPending--; // Time out if set too long - - return TRUE; - } - - if (Param == 3) // Release Permission - { - if (TNC->GavePermission) - { - TNC->GavePermission = FALSE; - if (TNC->ARDOPCurrentMode[0] != 'S') // Skip - TNC->FreeDataInfo->CONOK = 1; - - } - return 0; - } - - // Param is Address of a struct ScanEntry - - Scan = (struct ScanEntry *)buff; - return 0; - } - return 0; -} - -VOID FreeDataReleaseTNC(struct TNCINFO * TNC) -{ - // Set mycall back to Node or Port Call, and Start Scanner - - UCHAR TXMsg[1000]; - - FreeDataChangeMYC(TNC, TNC->NodeCall); - - // Start Scanner - - sprintf(TXMsg, "%d SCANSTART 15", TNC->Port); - - Rig_Command(-1, TXMsg); - - ReleaseOtherPorts(TNC); - -} - -VOID FreeDataSuspendPort(struct TNCINFO * TNC) -{ - TNC->FreeDataInfo->CONOK = 0; -} - -VOID FreeDataReleasePort(struct TNCINFO * TNC) -{ - TNC->FreeDataInfo->CONOK = 1; -} - - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, "" - "" - "FreDATA Status" - "

FreeData Status" - "

", - TNC->Port); - - - Len += sprintf(&Buff[Len], ""); - - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); -// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
Proto State%s
Traffic%s
TNC Restarts
"); - - Len += sprintf(&Buff[Len], "", TNC->WebBuffer); - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - -#ifndef LINBPQ - -#define BGCOLOUR RGB(236,233,216) -static HBRUSH RedBrush = NULL; -HBRUSH GreenBrush; -HBRUSH BlueBrush; -static HBRUSH bgBrush = NULL; - -extern HWND ClientWnd, FrameWnd; -extern int OffsetH, OffsetW; - -extern HMENU hMainFrameMenu; -extern HMENU hBaseMenu; -extern HANDLE hInstance; - -extern HKEY REGTREE; - - -/* -static LRESULT CALLBACK PacWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - MINMAXINFO * mmi; - PAINTSTRUCT ps; - HDC hdc; - - int i; - struct TNCINFO * TNC; - - HKEY hKey; - char Key[80]; - int retCode, disp; - - for (i=0; i<41; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC->hDlg == hWnd) - break; - } - - if (TNC == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - switch (message) { - - case WM_CREATE: - - break; - - case WM_PAINT: - - hdc = BeginPaint(hWnd, &ps); - -// SelectObject(ps.hdc, RedBrush); - SelectObject(ps.hdc, GreenBrush); -// SelectObject(ps.hdc, GetStockObject(GRAY_BRUSH)); - - EndPaint(hWnd, &ps); - break; - - case WM_GETMINMAXINFO: - - if (TNC->ClientHeight) - { - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = TNC->ClientWidth; - mmi->ptMaxSize.y = TNC->ClientHeight; - mmi->ptMaxTrackSize.x = TNC->ClientWidth; - mmi->ptMaxTrackSize.y = TNC->ClientHeight; - } - - break; - - - case WM_MDIACTIVATE: - { - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - - if (TNC->hMenu) - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)TNC->hMenu, "Actions"); - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - -// SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) TNC->hMenu, (LPARAM) TNC->hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - // call DrawMenuBar after the menu items are set - DrawMenuBar(FrameWnd); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - } - - - - case WM_INITMENUPOPUP: - - if (wParam == (WPARAM)TNC->hMenu) - { - if (TNC->ProgramPath) - { - if (strstr(TNC->ProgramPath, " TNC") || strstr(TNC->ProgramPath, "ARDOP") || strstr(TNC->ProgramPath, "VARA")) - { - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_ENABLED); - - break; - } - } - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_GRAYED); - } - - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - case WINMOR_KILL: - - KillTNC(TNC); - break; - - case WINMOR_RESTART: - - KillTNC(TNC); - RestartTNC(TNC); - break; - - case WINMOR_RESTARTAFTERFAILURE: - - TNC->RestartAfterFailure = !TNC->RestartAfterFailure; - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", TNC->Port); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - RegSetValueEx(hKey,"TNC->RestartAfterFailure",0,REG_DWORD,(BYTE *)&TNC->RestartAfterFailure, 4); - RegCloseKey(hKey); - } - break; - - case ARDOP_ABORT: - - if (TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SIZING: - case WM_SIZE: - - MoveWindows(TNC); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - - case SC_RESTORE: - - TNC->Minimized = FALSE; - break; - - case SC_MINIMIZE: - - TNC->Minimized = TRUE; - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - - case WM_CTLCOLORSTATIC: - { - HDC hdcStatic = (HDC)wParam; - SetTextColor(hdcStatic, RGB(0, 0, 0)); - SetBkMode(hdcStatic, TRANSPARENT); - return (LONG)bgBrush; - } - - case WM_DESTROY: - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); -} -*/ - -#endif - - - -VOID * FreeDataExtInit(EXTPORTDATA * PortEntry) -{ - int port; - char Msg[255]; - char * ptr; - struct TNCINFO * TNC; - char * TempScript; - u_long param = 1; - int line; - - srand(time(NULL)); - - port = PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); - WritetoConsole(Msg); - - return ExtProc; - } - - if (TNC->FreeDataInfo->TuningRange == 0) - TNC->FreeDataInfo->TuningRange = 50; - -#ifndef LINBPQ - - if (bgBrush == NULL) - { - bgBrush = CreateSolidBrush(BGCOLOUR); - RedBrush = CreateSolidBrush(RGB(255,0,0)); - GreenBrush = CreateSolidBrush(RGB(0,255,0)); - BlueBrush = CreateSolidBrush(RGB(0,0,255)); - } - -#endif - - Consoleprintf("FreeData Host %s %d", TNC->HostName, TNC->TCPPort); - - TNC->Port = port; - TNC->Hardware = H_FREEDATA; - - TNC->ARDOPDataBuffer = malloc(MAXRXSIZE); - TNC->ARDOPBuffer = malloc(8192); - - TNC->PortRecord = PortEntry; - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - memcpy(TNC->NodeCall, MYNODECALL, 10); - else - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - memcpy(TNC->FreeDataInfo->ourCall, TNC->NodeCall, 10); - strlop(TNC->FreeDataInfo->ourCall, ' '); - if (TNC->FreeDataInfo->useBaseCall) - strlop(TNC->FreeDataInfo->ourCall, '-'); - - if (TNC->FreeDataInfo->hamlibHost == 0) - TNC->FreeDataInfo->hamlibHost = _strdup("127.0.0.1"); - - if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) - TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - - if (TNC->PacketChannels > 1) - TNC->PacketChannels = 1; - - PortEntry->MAXHOSTMODESESSIONS = TNC->PacketChannels + 1; - - PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only - PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream - - PortEntry->PORTCONTROL.UICAPABLE = TRUE; - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 236; - - TNC->SuspendPortProc = FreeDataSuspendPort; - TNC->ReleasePortProc = FreeDataReleasePort; - -// PortEntry->PORTCONTROL.PORTSTARTCODE = KAMStartPort; -// PortEntry->PORTCONTROL.PORTSTOPCODE = KAMStopPort; - - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - // Set Essential Params and MYCALL - - // Put overridable ones on front, essential ones on end - - TempScript = zalloc(1000); - - // cant think of any yet - - if (TNC->InitScript) - { - strcat(TempScript, TNC->InitScript); - free(TNC->InitScript); - } - - TNC->InitScript = TempScript; - - // Set MYCALL - - sprintf(Msg, "MYCALL %s\r", TNC->NodeCall); - strcat(TNC->InitScript, Msg); - - strcpy(TNC->CurrentMYC, TNC->NodeCall); - - if (TNC->WL2K == NULL) - if (PortEntry->PORTCONTROL.WL2KInfo.RMSCall[0]) // Alrerady decoded - TNC->WL2K = &PortEntry->PORTCONTROL.WL2KInfo; - - PortEntry->PORTCONTROL.TNC = TNC; - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 520; - TNC->WebWinY = 500; - TNC->WebBuffer = zalloc(5000); - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - TNC->WEB_CHANSTATE = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_PROTOSTATE = zalloc(100); - TNC->WEB_RESTARTTIME = zalloc(100); - TNC->WEB_RESTARTS = zalloc(100); - - TNC->WEB_MODE = zalloc(20); - TNC->WEB_TRAFFIC = zalloc(100); - - -#ifndef LINBPQ - - line = 6; - - if (TNC->TXFreq) - { - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow + 22, PacWndProc, 500, 450, ForcedClose); - - InitCommonControls(); // loads common control's DLL - - CreateWindowEx(0, "STATIC", "TX Tune", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNE = CreateWindowEx(0, TRACKBAR_CLASS, "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNEVAL = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE, 320,line,30,20, TNC->hDlg, NULL, hInstance, NULL); - - SendMessage(TNC->xIDC_TXTUNE, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG(-200, 200)); // min. & max. positions - - line += 22; - } - else - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 450, ForcedClose); - - CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,450,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,line,106,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,520,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,line,110,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,144,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Proto State", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_PROTOSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,line,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,116,line,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,line,20,20 , TNC->hDlg, NULL, hInstance, NULL); - CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, - 0,170,250,300, TNC->hDlg, NULL, hInstance, NULL); - - TNC->ClientHeight = 450; - TNC->ClientWidth = 500; - - TNC->hMenu = CreatePopupMenu(); - - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill TNC TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart TNC TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after failed Connection"); - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); - - MoveWindows(TNC); -#endif - - time(&TNC->lasttime); // Get initial time value - - ConnecttoFreeData(port); - TNC->FreeDataInfo->CONOK = 1; - - return ExtProc; -} - - -VOID TidyClose(struct TNCINFO * TNC, int Stream) -{ - // We don't get data acks, so can't check for bytes outstanding - - FreeDataDisconnect(TNC); -} - -VOID ForcedClose(struct TNCINFO * TNC, int Stream) -{ - FreeDataDisconnect(TNC); -} - - - -VOID CloseComplete(struct TNCINFO * TNC, int Stream) -{ - if (Stream == 0) - { - FreeDataReleaseTNC(TNC); - } -} - -VOID FreeDataAbort(struct TNCINFO * TNC) -{ - FreeDataSendCommand(TNC, "ABORT\r"); -} - -// Host Mode Stuff (we reuse some routines in SCSPactor) - -VOID FreeDataDoTermModeTimeout(struct TNCINFO * TNC) -{ - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->ReinitState == 0) - { - //Checking if in Terminal Mode - Try to set back to Term Mode - - TNC->ReinitState = 1; - return; - } - - if (TNC->ReinitState == 1) - { - // Forcing back to Term Mode - - TNC->ReinitState = 0; - return; - } - - if (TNC->ReinitState == 3) - { - return; - } -} - -static RECT Rect1 = {30, 160, 400, 195}; - -int zEncode(unsigned char * in, unsigned char * out, int len, unsigned char * Banned) -{ - // Replace forbidden chars with =xx - - unsigned char * ptr = out; - unsigned char c; - - while (len--) - { - c = *(in++); - - if (strchr(&Banned[0], c)) - { - *(out++) = '='; - *(out++) = (c >> 4) + 'A'; - *(out++) = (c & 15) + 'A'; - } - else - *(out++) = c; - } - - return (out - ptr); -} - - - -VOID FreeDataProcessTNCMessage(struct TNCINFO * TNC, char * Call, unsigned char * Msg, int Len) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * toCall, * fromCall, * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - // First Byte of Message is Type. Messages can be commands or short (<120) data packets - // Data is encoded with =xx replacing restricted chars - - Msg[Len] = 0; - - switch (Msg[0]) - { - case 'C': - - // Connect Request. C G8BPQ-10 GM8BPQ-2 (Target, Origin) - - toCall = strtok_s(&Msg[2], " ", &Context); - fromCall = strtok_s(NULL, " ", &Context); - tncCall = strtok_s(NULL, " ", &Context); - - strcpy(TNC->FreeDataInfo->farCall, tncCall); - - ConvToAX25Ex(fromCall, axcall); // Allow -T and -R SSID's for MPS - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(axcall) == FALSE) - { - Debugprintf("FreeData Call from %s rejected", fromCall); - - // Send 'd' - - Sleep(1000); - FreeDataDisconnect(TNC); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(axcall, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - Sleep(1000); - FreeDataSendCommand(TNC, "d"); - - Debugprintf("FreeDara Call from %s not in ValidCalls - rejected", Call); - return; - } - } - } - - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(toCall, Appl) == 0) - break; - } - - if (App < 32) - { - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(Call, "-T" ) || strstr(Call, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - if (!CheckAppl(TNC, AppName)) - { - Sleep(1000); - FreeDataSendCommand(TNC, "dApplication not Available"); - return; - } - } - - ProcessIncommingConnectEx(TNC, fromCall, 0, TRUE, TRUE); - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - // if connect to an application, send command - - if (AppName[0]) - { - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf(buffptr->Data, "%s\r", AppName); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - } - - TNC->ConnectPending = FALSE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, toCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - if (SESS->Frequency == 1500) - { - // try to get from WL2K record - - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - } - } - SESS->Mode = TNC->WL2KMode; - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, toCall); - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - SESS->Mode = WL2K->mode; - } - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - STREAM->Connected = TRUE; - - // Send Connect ACK - Sleep(1000); - FreeDataSendCommand(TNC, "c"); - return; - - case 'c': - - // Connect ACK - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - STREAM->Connected = TRUE; - STREAM->Connecting = FALSE; - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connected to %s\r", TNC->FreeDataInfo->toCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - - return; - - case 'D': - - // Disconnect Command - - FreeDataSendCommand(TNC, "d"); - - // Drop through to disconnect this end - - case 'd': - - // Disconnect complete (response to sending "D") - // Or connect refused in response to "C" - - if (STREAM->Connecting) - { - // Connection Refused - If there is a message, pass to appl - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - if (Msg[1]) - buffptr->Len = sprintf(buffptr->Data, "Connect Rejected - %s\r", &Msg[1]); - else - buffptr->Len = sprintf(buffptr->Data, "Connect Rejected\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - return; - } - - // Release Session - - if (STREAM->Connected) - { - // Create a traffic record - - char logmsg[120]; - time_t Duration; - - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - } - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - return; - - case 'B': - - // Was Base64, but has been expanded - just send to User - - // If len > blocksize, fragment - - Len--; - Msg++; // Remove Type - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Msg, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Msg, 256); - Len -= 256; - Msg += 256; - STREAM->BytesRXed += 256; - - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Msg, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Msg, Len); - STREAM->BytesRXed += Len; - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - return; - - case 'I': - - // Encoded Response - - // Undo = transparency - - ptr = Msg + 1; - - while (ptr = strchr(ptr, '=')) - { - // Next two chars are a hex value - - a = ptr[1] - 'A'; - b = ptr[2] - 'A'; - memmove(ptr, ptr + 2, Len); - ptr[0] = (a << 4) + b; - ptr++; - } - - buffptr = GetBuff(); - buffptr->Len = sprintf(buffptr->Data, "%s", &Msg[1]); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - return; - - case 'f': - - // FreeDATA File Transfer - - // Seems to be f null fn null data - //f.;Makefile.;.;123123123.; - { - char * FN; - time_t CRC; - int FileLen; - char Filename[256]; - FILE * fp1; - unsigned char * ptr; - char Text[64]; - int textLen; - - - if (TNC->FreeDataInfo->RXDir == NULL) - { - Debugprintf("FreeDATA RXDIRECTORY not set - file transfer ignored"); - return; - } - - FN = _strdup(&Msg[3]); - ptr = &Msg[4] + strlen(FN); - - ptr = ptr + strlen(ptr) + 2; - CRC = atoi(ptr); - ptr = ptr + strlen(ptr) + 2; - - FileLen = Len - (ptr - Msg); - - sprintf(Filename, "%s\\%s", TNC->FreeDataInfo->RXDir, FN); - - fp1 = fopen(Filename, "wb"); - - if (fp1) - { - fwrite(ptr, 1, FileLen, fp1); - fclose(fp1); - textLen = sprintf(Text, "File %s received from %s \r", FN, Call); - WritetoTrace(TNC, Text, textLen); - } - else - Debugprintf("FreeDATA - File %s create failed %s", Filename); - - - free(FN); - return; - - } - - - } - - if (STREAM->Attached == 0) - return; - - - buffptr = GetBuff(); - - if (buffptr == 0) - { - return; // No buffers, so ignore - } - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", Msg); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - -} - - -VOID FreeDataProcessNewConnect(struct TNCINFO * TNC, char * fromCall, char * toCall) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - strcpy(TNC->FreeDataInfo->farCall, fromCall); - - ConvToAX25Ex(fromCall, axcall); // Allow -T and -R SSID's for MPS - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(axcall) == FALSE) - { - Debugprintf("FreeData Call from %s rejected", fromCall); - - // Send 'd' - - Sleep(1000); - FreeDataDisconnect(TNC); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(axcall, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - Sleep(1000); - FreeDataDisconnect(TNC); - - Debugprintf("FreeData Call from %s not in ValidCalls - rejected", fromCall); - return; - } - } - } - - // The TNC responds to any SSID so we can use incomming call as Appl Call - // No we can't - it responds but reports the configured call not the called call -/* - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(toCall, Appl) == 0) - break; - } - - if (App < 32) - { - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(fromCall, "-T" ) || strstr(fromCall, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - if (!CheckAppl(TNC, AppName)) - { - Sleep(1000); - FreeDataSendCommand(TNC, "dApplication not Available"); - return; - } - } - -*/ - - ProcessIncommingConnectEx(TNC, fromCall, 0, TRUE, TRUE); - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - // if connect to an application, send command - - if (AppName[0]) - { - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf(buffptr->Data, "%s\r", AppName); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - } - - TNC->ConnectPending = FALSE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, toCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - if (SESS->Frequency == 1500) - { - // try to get from WL2K record - - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - } - } - SESS->Mode = TNC->WL2KMode; - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, toCall); - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - SESS->Mode = WL2K->mode; - } - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - STREAM->Connected = TRUE; - - return; - -} - -VOID FreeDataProcessConnectAck(struct TNCINFO * TNC, char * Call, unsigned char * Msg, int Len) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * toCall, * fromCall, * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - STREAM->Connected = TRUE; - STREAM->Connecting = FALSE; - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connected to %s\r", TNC->FreeDataInfo->toCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - - return; - -} -extern char LOC[7]; -/* -Line 104: if received_json["type"] == 'PING' and received_json["command"] == "PING": -Line 111: if received_json["type"] == 'ARQ' and received_json["command"] == "sendFile": -Line 142: if received_json["type"] == 'ARQ' and received_json["command"] == "sendMessage": -Line 173: if received_json["type"] == 'ARQ' and received_json["command"] == "stopTransmission": -Line 182: if received_json["type"] == 'GET' and received_json["command"] == 'STATION_INFO': -Line 195: if received_json["type"] == 'GET' and received_json["command"] == 'TNC_STATE': -Line 244: if received_json["type"] == 'GET' and received_json["command"] == 'RX_BUFFER': -Line 258: if received_json["type"] == 'GET' and received_json["command"] == 'RX_MSG_BUFFER': -Line 272: if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_BUFFER': -Line 275: if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_MSG_BUFFER': -*/ - -//{\"type\" : \"ARQ\", \"command\" : \"sendMessage\", \"dxcallsign\" : \"G8BPQ\", \"mode\" : \"10\", \"n_frames\" : \"1\", \"data\" : \"Hello Hello\" , \"checksum\" : \"123\", \"timestamp\" : 1642580748576} - - - -static unsigned char BANNED[] = {'"', '=', ':', '{', '}', '[', ']', '/', 13, 0}; // I think only need to escape = ": CR Null - - -static void SendDataMsg(struct TNCINFO * TNC, char * Call, char * Msg, int Len) -{ - // We can't base64 encode chunks. so buffer as original data and encode on send - - SendAsFile(TNC, TNC->FreeDataInfo->farCall, Msg, Len); - WritetoTrace(TNC, Msg, Len); - - return; -} - - - -static int SendAsRaw(struct TNCINFO * TNC, char * Call, char * myCall, char * Msg, int Len) -{ - char Message[16284]; - char * Base64; - - // TNC now only supports send_raw, with base64 encoded data - - char Template[] = "{\"type\" : \"arq\", \"command\" : \"send_raw\", \"uuid\" : \"%s\",\"parameter\":" - "[{\"dxcallsign\" : \"%s\", \"mode\": \"255\", \"n_frames\" : \"1\", \"data\" : \"%s\"}]}\n"; - - - Base64 = byte_base64_encode(Msg, Len); - - Len = sprintf(Message, Template, gen_uuid(), Call, Base64); - - free(Base64); - return send(TNC->TCPDataSock, Message, Len, 0); -} - -void FlushData(struct TNCINFO * TNC) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Info = TNC->FreeDataInfo; - int Len = Info->toSendCount; - - // We need to flag as data (B) then base64 encode it - - memmove(&Info->toSendData[1], Info->toSendData, Len); - Info->toSendData[0] = 'B'; - Len++; - - SendAsRaw(TNC, Info->farCall, Info->ourCall, Info->toSendData, Len); - - Info->toSendCount = 0; - Info->toSendTimeout = 0; - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - -} - -static int SendAsFile(struct TNCINFO * TNC, char * Call, char * Msg, int Len) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Info = TNC->FreeDataInfo; - - // Add to buffer - - if ((Info->toSendCount + Len) > 8192) // Reasonable Limit - { - // Send the buffered bit - - FlushData(TNC); - } - - memcpy(&Info->toSendData[Info->toSendCount], Msg, Len); - Info->toSendCount += Len; - Info->toSendTimeout = 10; // About a second - - STREAM->BytesTXed += Len; - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - return Len; -} - -static int SendTNCCommand(struct TNCINFO * TNC, char * Type, char * Command) -{ - char Message[256]; - int Len; - - Len = sprintf(Message, "{\"type\" : \"%s\", \"command\" : \"%s\"}\n", Type, Command); - return send(TNC->TCPDataSock, Message, Len, 0); -} - -static void SendPoll(struct TNCINFO * TNC) -{ - char DataMsgPoll[] = "{\"type\" : \"GET\", \"command\" : \"RX_MSG_BUFFER\"}\n"; -// char DaemonPoll[] = "{\"type\" : \"GET\", \"command\" : \"DAEMON_STATE\"}\n"; - char TNCPoll[] = "{\"type\" : \"GET\", \"command\" : \"TNC_STATE\", \"timestamp\" : 0}\n"; - - // Poll daemon rapidly until tnc is connected, then every 5 secs - - if ((TNC->PollDelay++ > 50))// || !TNC->TNCCONNECTED) && TNC->DAEMONCONNECTED) - { -// ret = send(TNC->TCPSock, (char *)&DaemonPoll, strlen(DaemonPoll), 0); - TNC->PollDelay = 0; - - } - - if (TNC->TNCCONNECTED) - { -// ret = send(TNC->TCPDataSock, (char *)&TNCPoll, strlen(TNCPoll), 0); - -// if (TNC->PollDelay & 1) -// ret = SendTNCCommand(TNC, "GET", "RX_BUFFER"); -// else if (TNC->PollDelay & 2) -// ret = SendTNCCommand(TNC, "GET", "RX_MSG_BUFFER"); -// else -// ret = send(TNC->TCPDataSock, (char *)&TNCPoll, strlen(TNCPoll), 0); - - - } - return; -} - -static void SendPing(struct TNCINFO * TNC, char * Call) -{ - char Ping[] = "{\"type\" : \"ping\", \"command\" : \"ping\", \"dxcallsign\" : \"%s\", \"timestamp\" : %d}\n"; - char Message[256]; - int Len, ret; - - Len = sprintf(Message, Ping, Call, time(NULL)); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - -static void SendCQ(struct TNCINFO * TNC) -{ - char CQ[] = "{\"type\" : \"broadcast\", \"command\" : \"cqcqcq\"}\n"; - - char Message[256]; - int Len, ret; - - Len = sprintf(Message, CQ); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - -static void SendBeacon(struct TNCINFO * TNC, int Interval) -{ - char Template1[] = "{\"type\" : \"broadcast\", \"command\" : \"start_beacon\", \"parameter\" : \"%d\"}\n"; - char Template2[] = "{\"type\" : \"broadcast\", \"command\" : \"stop_beacon\"}\n"; - - char Message[256]; - int Len, ret; - - if (Interval > 0) - Len = sprintf(Message, Template1, Interval); - else - Len = sprintf(Message, Template2); - - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - - -unsigned short int compute_crc(unsigned char *buf,int len); - - -int FreeDataWriteCommBlock(struct TNCINFO * TNC) -{ - if (TNC->hDevice) - return WriteCOMBlock(TNC->hDevice, TNC->TXBuffer, TNC->TXLen); - - return 0; -} - -char * getObjectFromArray(char * Msg) -{ - // This gets the next object from an array ({} = object, [] = array - // We look for the end of the object same number of { and }, teminate after } and return pointer to next object - // So we have terminated Msg, and returned next object in array - - // Only call if Msg is the next object in array - - - char * ptr = Msg; - char c; - - int Open = 0; - int Close = 0; - - while (c = *(ptr++)) - { - if (c == '{') Open ++; else if (c == '}') Close ++; - - if (Open == Close) - { - *(ptr++) = 0; - return ptr; - } - } - return 0; -} -/* - ["DATACHANNEL;RECEIVEDOPENER","ARQ;RECEIVING","ARQ;RECEIVING;SUCCESS"] [{"DXCALLSIGN":"GM8BPQ -{"DXCALLSIGN":"GM8BPQ","DXGRID":"","TIMESTAMP":1642847440,"RXDATA":[{"dt":"f","fn":"config.json", -"ft":"application\/json","d":"data:application\/json;base64, -ewogICAgInRuY19ob3N0IiA6ICIxMjcuMC4wLjEiLAogICAgInRuY19wb3J0IiA6ICIzMDAwIiwKICAgICJkYWVtb25faG9zdCIgOiAiMTI3LjAuMC4xIiwKICAgICJkYWVtb25fcG9ydCIgOiAiMzAwMSIsCiAgICAibXljYWxsIiA6ICJBQTBBQSIsCiAgICAibXlncmlkIiA6ICJBQTExZWEiICAgIAp9" -,"crc":"123123123"}]} -*/ -void ProcessFileObject(struct TNCINFO * TNC, char * This) -{ - char * Call; - char * LOC; - char * FN; - char * Type; - char * ptr, * ptr2; - int Len, NewLen; - - Call = strchr(This, ':'); - Call += 2; - This = strlop(Call, '"'); - - LOC = strchr(This, ':'); - LOC += 2; - This = strlop(LOC, '"'); - - FN = strstr(This, "fn"); - FN += 5; - This = strlop(FN, '"'); - - Type = strstr(This, "base64"); - Type += 7; - This = strlop(Type, '"'); - - // Decode Base64 - - Len = strlen(Type); - - Debugprintf("RX %d %s %d", TNC->Port, FN, Len); - - ptr = ptr2 = Type; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - NewLen = (int)(ptr2 - Type); - - if (*(ptr-1) == '=') - NewLen--; - - if (*(ptr-2) == '=') - NewLen--; - - Type[NewLen] = 0; - - Type --; - - Type[0] = 'B'; ; // Base64 Info - - FreeDataProcessTNCMessage(TNC, Call, Type, NewLen + 1); - - -} - -void ProcessMessageObject(struct TNCINFO * TNC, char * This) -{ - // This gets Message from a RX_MSG_BUFFER array element. - - char * Call; - char * LOC; - char * Type; - char * Msg; - int Len; - char * ptr, * ptr2; - - char * ID; - char * TYPE; - char * SEQ; - char * UUID; - char * TEXT; - char * NOIDEA; - char * FORMAT; - char * FILENAME; - int fileLen; - - int n; - - - Call = strstr(This, "dxcallsign"); - Call += 13; - This = strlop(Call, '"'); - - LOC = strchr(This, ':'); - LOC += 2; - This = strlop(LOC, '"'); - - Msg = strstr(This, "\"data\""); - Msg += 8; - This = strlop(Msg, '"'); - - // Decode Base64 - - // FreeData replaces / with \/ so need to undo - - ptr2 = strstr(Msg, "\\/"); - - while (ptr2) - { - memmove(ptr2, ptr2 + 1, strlen(ptr2)); - ptr2 = strstr(ptr2, "\\/"); - } - - Len = strlen(Msg); - - ptr = ptr2 = Msg; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - Len = (int)(ptr2 - Msg); - - if (*(ptr-1) == '=') - Len--; - - if (*(ptr-2) == '=') - Len--; - - Msg[Len] = 0; - -//m�;send_message�;123�;64730c5c-d32c-47b4-9b11-c958fd07a185�;hhhhhhhhhhhhhhhhhh -//�;�;plain/text�; - -//m;send_message;123;64730c5c-d32c-47b4-9b11-c958fd07a185;hhhhhhhhhhhhhhhhhh -//;;plain/text; - - // Message elements seem to be delimited by null ; - // Guessing labels - - ID = Msg; - - if (ID[0] == 'B') - { - // BPQ Message - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - - if (STREAM->Attached) - { - if (STREAM->Connected == 1 && STREAM->Connecting == 0) - { - char * Line = &ID[1]; - Len -= 1; - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Line, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, 256); - Len -= 256; - Line += 256; - STREAM->BytesRXed += 256; - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Line, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, Len); - STREAM->BytesRXed += Len; - - } - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - } - return; - } - - n = strlen(ID) + 2; - Msg += n; - Len -= n; - - if (ID[0] == 'm') - { - // ?? Chat ?? comes from a send raw ?? - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - TYPE = Msg; - n = strlen(TYPE) + 2; - Msg += n; - Len -= n; - - SEQ = Msg; - n = strlen(SEQ) + 2; - Msg += n; - Len -= n; - - UUID = Msg; - n = strlen(UUID) + 2; - Msg += n; - Len -= n; - - TEXT = Msg; - n = strlen(TEXT) + 2; - Msg += n; - Len -= n; - - NOIDEA = Msg; - n = strlen(NOIDEA) + 2; - Msg += n; - Len -= n; - - FORMAT = Msg; - n = strlen(FORMAT) + 2; - Msg += n; - Len -= n; - - // if Atached, send to user - - if (STREAM->Attached) - { - if (STREAM->Connected == 0 && STREAM->Connecting == 0) - { - // Just attached - send as Chat Message - - char Line[560]; - char * rest; - - // Send line by line - - rest = strlop(TEXT, 10); // FreeData chat uses LF - - while (TEXT && TEXT[0]) - { - Len = strlen(TEXT); - if (Len > 512) - TEXT[512] = 0; - - Len = sprintf(Line, "Chat From %-10s%s\r", Call, TEXT); - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Line, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, 256); - Len -= 256; - TEXT += 256; - STREAM->BytesRXed += 256; - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Line, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, Len); - STREAM->BytesRXed += Len; - - TEXT = rest; - rest = strlop(TEXT, 10); // FreeData chat ues LF - } - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - } - } - else - { - // Send Not Available Message -//m�;send_message�;123�;64730c5c-d32c-47b4-9b11-c958fd07a185�;hhhhhhhhhhhhhhhhhh -//�;�;plain/text�; - - char reply[512] = "m"; - char * p; - - strcat(TEXT, "\r"); - WritetoTrace(TNC, TEXT, strlen(TEXT)); - - strcpy(&reply[2], ";send_message"); - strcpy(&reply[16], ";123"); - reply[21] = ';'; - strcpy(&reply[22], gen_uuid()); - sprintf(&reply[59], ";Message received but user not on line\n"); - - p = strchr(&reply[59], 0); - - p[1] = ';'; - strcpy(&p[3], ";plain/text"); - p[15] = ';'; - - Len = &p[16] - reply; - - SendAsRaw(TNC, Call, TNC->FreeDataInfo->ourCall, reply, Len); - } - return; - - } - else if (ID[0] == 'f') - { - // File Tranfer - - char Filename[256]; - FILE * fp1; - char Text[64]; - int textLen; - - - FILENAME = Msg; - n = strlen(FILENAME) + 2; - Msg += n; - Len -= n; - - TYPE = Msg; - n = strlen(TYPE) + 2; - Msg += n; - Len -= n; - - SEQ = Msg; // ?? Maybe = 123123123 - n = strlen(SEQ) + 2; - Msg += n; - Len -= n; - - TEXT = Msg; // The file - fileLen = Len; - - if (TNC->FreeDataInfo->RXDir == NULL) - { - Debugprintf("FreeDATA RXDIRECTORY not set - file transfer ignored"); - return; - } - - sprintf(Filename, "%s\\%s", TNC->FreeDataInfo->RXDir, FILENAME); - - fp1 = fopen(Filename, "wb"); - - if (fp1) - { - fwrite(TEXT, 1, fileLen, fp1); - fclose(fp1); - textLen = sprintf(Text, "File %s received from %s \r", FILENAME, Call); - WritetoTrace(TNC, Text, textLen); - } - else - Debugprintf("FreeDATA - File %s create failed %s", Filename); - - return; - } - else if (ID[0] == 'm') - { - - } - - - - - - - - - - -// FreeDataProcessTNCMessage(TNC, Call, Msg, strlen(Msg)); -} - -void processJSONINFO(struct TNCINFO * TNC, char * Info, char * Call, double snr) -{ - char * LOC = ""; - char * ptr, * Context; - - // Info is an array. Normally only one element, but should check - - ptr = strtok_s(&Info[1], ",]", &Context); - - while (ptr && ptr[1]) - { - if (strstr(ptr, "BEACON;RECEIVING")) - { - char CQ[64]; - int Len; - - Len = sprintf(CQ, "Beacon received from %s SNR %3.1f\r", Call, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (Call) - UpdateMH(TNC, Call, '!', 'I'); - } - if (strstr(ptr, "PING;RECEIVING")) - { - // Add to MH - - if (Call) - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "CQ;RECEIVING")) - { - char CQ[64]; - int Len; - - Len = sprintf(CQ, "CQ received from %s SNR %3.1f\r", Call, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "PING;RECEIVEDACK")) - { - char Msg[128]; - int Len; - - Len = sprintf(Msg, "Ping Response from %s SNR %3.1f\r", Call, snr); - FreeDataProcessTNCMessage(TNC, Call, Msg, Len); - - // Add to MH - - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "TRANSMITTING;FAILED")) - { - // Failed to send a message - if it was a connect request tell appl - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - if (STREAM->Connecting) - { - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connect Failed\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - } - } - ptr = strtok_s(NULL, ",]", &Context); - } -} - - - - - - -char * getJSONValue(char * Msg, char * Key) -{ - char * ptr, *ptr2, *value = 0; - int vallen, keylen = strlen(Key); - char c; - - // We Null Terminate the value, so we must look for keys in reverse order - - ptr = strstr(Msg, Key); - - if (ptr) - { - ptr += (keylen + 1); - - if (*(ptr) == '[') - { - // Array - - int Open = 0; - int Close = 0; - - ptr2 = ptr; - - while (c = *(ptr++)) - { - if (c == '[') - Open ++; - else if (c == ']') - Close ++; - - if (Open == Close) - { - vallen = ptr - ptr2; - value = ptr2; - value[vallen] = 0; - return value; - } - } - } - else if (*(ptr) == '\"') - { - // String - - ptr2 = ptr; - ptr = strchr(ptr + 1, '\"'); - if (ptr) - { - ptr++; - vallen = ptr - ptr2; - value = ptr2; - value[vallen] = 0; - } - } - } - return value; -} - - -char stopTNC[] = "{\"type\" : \"SET\", \"command\": \"STOPTNC\" , \"parameter\": \"---\" }\r"; - - -void ProcessDAEMONJSON(struct TNCINFO * TNC, char * Msg, int Len) -{ - char * ptr; - char * capture, * playback; - - - if (memcmp(Msg, "{\"command\":\"daemon_state\"", 25) == 0) - { -/* - {"COMMAND":"DAEMON_STATE","DAEMON_STATE":[{"STATUS":"stopped"}], - "PYTHON_VERSION":"3.9", - "HAMLIB_VERSION":"4.0", - "INPUT_DEVICES":[{"ID":5,"NAME":"pulse"},{"ID":9,"NAME":"default"}], - "OUTPUT_DEVICES":[{"ID":0,"NAME":"bcm2835 Headphones: - (hw:0,0)"},{"ID":1,"NAME":"sysdefault"},{"ID":2,"NAME":"lavrate"},{"ID":3,"NAME":"samplerate"},{"ID":4,"NAME":"speexrate"},{"ID":5,"NAME":"pulse"},{"ID":6,"NAME":"upmix"},{"ID":7,"NAME":"vdownmix"},{"ID":8,"NAME":"dmix"},{"ID":9,"NAME":"default"}], - "SERIAL_DEVICES":[{"PORT":"\/dev\/ttyAMA0","DESCRIPTION":"ttyAMA0 [1dff]"}], - "CPU":"39.6", - "RAM":"38.6", - "VERSION":"0.1-prototype"} -*/ - - Msg += 25; - - playback = getJSONValue(Msg, "\"output_devices\""); - capture = getJSONValue(Msg, "\"input_devices\""); - - if (TNC->CaptureDevices) - free(TNC->CaptureDevices); - - TNC->CaptureDevices = _strdup(capture); - - if (TNC->PlaybackDevices) - free(TNC->PlaybackDevices); - - TNC->PlaybackDevices = _strdup(playback); - - ptr = getJSONValue(Msg, "\"daemon_state\""); - - if (strstr(ptr, "stopped")) - { - TNC->FreeDataInfo->TNCRunning = 0; - // if we have Capture and Playback devices, then start the TNC, else look in message for them - - if (TNC->CaptureDevices) - { - if (TNC->FreeDataInfo->startingTNC == 0) - { - // Find Capture and Playback indices - - struct FreeDataINFO * Info = TNC->FreeDataInfo; - char * devptr = stristr(TNC->CaptureDevices, Info->Capture); - int capindex = -1, playindex = -1; - char startTNC[] = "{\"type\":\"set\",\"command\":\"start_tnc\"," - "\"parameter\":" - "[{\"mycall\":\"%s\"," - "\"mygrid\":\"%s\"," - "\"rx_audio\":\"%d\"," - "\"tx_audio\":\"%d\"," - "\"radiocontrol\":\"disabled\"," - "\"devicename\":\"RIG_MODEL_NETRIGCTL\"," - "\"deviceport\":\"COM99\"," - "\"pttprotocol\":\"USB\"," - "\"pttport\":\"COM99\"," - "\"serialspeed\":\"19200\"," - "\"data_bits\":\"8\"," - "\"stop_bits\":\"1\"," - "\"handshake\":\"None\"," - "\"rigctld_ip\":\"%s\"," - "\"rigctld_port\":\"%d\"," - "\"enable_scatter\":\"False\"," - "\"enable_fft\":\"False\"," - "\"enable_fsk\":\"False\"," - "\"low_bandwidth_mode\":\"%s\"," //False - "\"tuning_range_fmin\":\"%3.1f\"," //-50.0 - "\"tuning_range_fmax\":\"%3.1f\"," // 50.0 - "\"tx_audio_level\":\"125\"," - "\"respond_to_cq\":\"True\"," - "\"rx_buffer_size\":\"16\"}]}\n"; - - - char Command[2048]; - int Len; - - if (devptr) - { - while (*(--devptr) != '{'); // find start of subparam - capindex = atoi(&devptr[6]); - } - - devptr = stristr(TNC->PlaybackDevices, Info->Playback); - - if (devptr) - { - while (*(--devptr) != '{'); // find start of subparam - playindex = atoi(&devptr[6]); - } - - if (capindex > -1 && playindex > -1) - { - Len = sprintf(Command, startTNC, TNC->FreeDataInfo->ourCall, LOC, capindex, playindex, - TNC->FreeDataInfo->hamlibHost, TNC->FreeDataInfo->hamlibPort, - TNC->FreeDataInfo->LimitBandWidth ? "True" : "False", - TNC->FreeDataInfo->TuningRange * -1.0, - TNC->FreeDataInfo->TuningRange * 1.0); - - send(TNC->TCPSock, Command, Len, 0); -// TNC->FreeDataInfo->startingTNC = 5; - } - } - } - else - { - ptr = getJSONValue(Msg, "\"version\""); - - } - return; - } - TNC->FreeDataInfo->TNCRunning = 1; - - if (TNC->TNCCONNECTED == FALSE && TNC->TNCCONNECTING == FALSE) - ConnectTNCPort(TNC); - - return; - - } - - Debugprintf(Msg); -} - -void StopTNC(struct TNCINFO * TNC) -{ - char stopTNC[] = "{\"type\" : \"set\", \"command\": \"stop_tnc\" , \"parameter\": \"---\"}"; - - if (TNC->TNCCONNECTED) - { - send(TNC->TCPSock, stopTNC, strlen(stopTNC), 0); - closesocket(TNC->TCPDataSock); - } -} - - -void ProcessTNCJSON(struct TNCINFO * TNC, char * Msg, int Len) -{ - char * ptr; - - if (memcmp(Msg, "{\"ptt\":", 7) == 0) - { - if (strstr(Msg, "True")) - { -// TNC->Busy = TNC->BusyHold * 10; // BusyHold delay - - if (TNC->PTTMode) - Rig_PTT(TNC, TRUE); - } - else - { - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); - } - return; - } - - if (memcmp(Msg, "{\"command_response\"", 19) == 0) - { - Debugprintf("%d %s", TNC->Port, Msg); - return; - } - - - if (memcmp(Msg, "{\"command\":\"tnc_state\"", 22) == 0) - { -/* -{"command":"tnc_state","ptt_state":"False","tnc_state":"IDLE","arq_state":"False","arq_session":"False", -"arq_session_state":"disconnected","audio_rms":"0","snr":"0","frequency":"None","speed_level":"1", -"mode":"None","bandwidth":"None","fft":"[0]","channel_busy":"False","scatter":[],"rx_buffer_length":"0", -"rx_msg_buffer_length":"0","arq_bytes_per_minute":"0","arq_bytes_per_minute_burst":"0","arq_compression_factor":"0", -"arq_transmission_percent":"0","total_bytes":"0","beacon_state":"False", -"stations":[],"mycallsign":"GM8BPQ-6","dxcallsign":"AA0AA","dxgrid":""} -*/ - char * LOC = 0; - char * Stations; - char * myCall = 0; - char * farCall = 0; - double snr; - int arqstate = 0; - int rx_buffer_length = 0; - int rx_msg_buffer_length = 0; - - Msg += 23; - - ptr = strstr(Msg, "rx_buffer_length"); - - if (ptr) - rx_buffer_length = atoi(&ptr[19]); - - ptr = strstr(Msg, "rx_msg_buffer_length"); - - if (ptr) - rx_msg_buffer_length = atoi(&ptr[23]); - - ptr = strstr(Msg, "snr"); - - if (ptr) - snr = atof(ptr + 6); - - Stations = getJSONValue(Msg, "\"stations\""); - - if (Stations) - { - ptr = Stations + strlen(Stations) + 1; - LOC = getJSONValue(ptr, "\"dxgrid\""); - farCall = getJSONValue(ptr, "\"dxcallsign\""); - myCall = getJSONValue(ptr, "\"mycallsign\""); - - if (myCall && farCall) - { - myCall++; - strlop(myCall, '"'); - farCall++; - strlop(farCall, '"'); - } - } - - // Look for changes in arq_session_state - - ptr = strstr(Msg, "\"arq_session_state\""); - - if (ptr) - { - struct STREAMINFO * STREAM = &TNC->Streams[0]; - ptr += 21; - - if (memcmp(ptr, "disconnected", 10) == 0) - { - if (TNC->FreeDataInfo->arqstate != 1) - { - TNC->FreeDataInfo->arqstate = 1; - Debugprintf("%d arq_session_state %s", TNC->Port, "disconnected"); - } - - // if connected this is a new disconnect - - if (STREAM->Connected) - { - // Create a traffic record - - char logmsg[120]; - time_t Duration; - - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - } - } - else if (memcmp(ptr, "connecting", 10) == 0) - { - if (TNC->FreeDataInfo->arqstate != 2) - { - TNC->FreeDataInfo->arqstate = 2; - Debugprintf("%d arq_session_state %s", TNC->Port, "connecting"); - } - } - else if (memcmp(ptr, "connected", 9) == 0) - { - // if connection is idle this is an incoming connect - - if (TNC->FreeDataInfo->arqstate != 3) - { - TNC->FreeDataInfo->arqstate = 3; - Debugprintf("%d arq_session_state %s", TNC->Port, "connected"); - } - - if (STREAM->Connecting == FALSE && STREAM->Connected == FALSE) - { - FreeDataProcessNewConnect(TNC, farCall, myCall); - } - - // if connecting it is a connect ack - - else if (STREAM->Connecting) - { - FreeDataProcessConnectAck(TNC, farCall, Msg, Len); - } - } - - else if (memcmp(ptr, "disconnecting", 12) == 0) - { - if (TNC->FreeDataInfo->arqstate != 4) - { - TNC->FreeDataInfo->arqstate = 4; - Debugprintf("%d arq_session_state %s", TNC->Port, "disconnecting"); - } - } - else if (memcmp(ptr, "failed", 5) == 0) - { - PMSGWITHLEN buffptr; - - if (TNC->FreeDataInfo->arqstate != 5) - { - TNC->FreeDataInfo->arqstate = 5; - Debugprintf("%d arq_session_state %s", TNC->Port, "failed"); - } - - if (STREAM->Connecting) - { - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connect Failed\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - } - } - } - - if (rx_buffer_length || rx_msg_buffer_length) - FreeGetData(TNC); - - ptr = getJSONValue(Msg, "\"info\""); - - if (ptr == NULL) - return; - - if (strcmp(ptr, "[]") != 0) - { - - processJSONINFO(TNC, ptr, farCall, snr); - Debugprintf("%d %s %s", TNC->Port, ptr, farCall); - } - - return; - } - - if (memcmp(Msg, "{\"freedata\":\"tnc-message\"", 25) == 0) - { - char * mycall = strstr(Msg, "mycall"); - char * dxcall = strstr(Msg, "dxcall"); - char * dxgrid = strstr(Msg, "dxgrid"); - char * snrptr = strstr(Msg, "snr"); - float snr = 0; - char CQ[64]; - int Len; - - Msg += 26; - - if (mycall && dxcall && dxgrid) - { - mycall += 13; - strlop(mycall, '"'); - - dxcall += 13; - strlop(dxcall, '"'); - - dxgrid += 9; - strlop(dxgrid, '"'); - } - - - if (dxcall && strstr(dxcall, "-0")) - strlop(dxcall, '-'); - - if (snrptr) - snr = atof(&snrptr[6]); - - if (memcmp(Msg, "\"beacon\":\"received\"", 18) == 0) - { - if (mycall && dxcall && dxgrid) - { - Len = sprintf(CQ, "Beacon received from %s SNR %3.1f", dxcall, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (dxcall) - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - if (memcmp(Msg, "\"cq\":\"received\"", 14) == 0) - { - if (mycall && dxcall && dxgrid) - { - Len = sprintf(CQ, "CQ received from %s", dxcall); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (dxcall) - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - if (memcmp(Msg, "\"ping\":\"received\"", 16) == 0) - { - if (mycall && dxcall && dxgrid) - { - Len = sprintf(CQ, "PING received from %s SNR %3.1f", dxcall, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (dxcall) - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - if (memcmp(Msg, "\"ping\":\"acknowledge\"", 16) == 0) - { - if (mycall && dxcall && dxgrid) - { - char Msg[128]; - - Len = sprintf(Msg, "Ping Response from %s SNR %3.1f\r", dxcall, snr); - FreeDataProcessTNCMessage(TNC, dxcall, Msg, Len); - - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - - - - - - Debugprintf("%d %s", TNC->Port, Msg); - return; - } - - if (memcmp(Msg, "{\"command\":\"rx_buffer\"", 22) == 0) - { - char * Next, * This; - - // Delete from TNC - - SendTNCCommand(TNC, "set", "del_rx_buffer"); Msg += 22; - - ptr = getJSONValue(Msg, "\"eof\""); - ptr = getJSONValue(Msg, "\"data-array\""); - - This = ptr; - - if (This[1] == '{') // Array of objects - { - This++; - do - { - Next = getObjectFromArray(This); - ProcessMessageObject(TNC, This); - This = Next; - - } while (Next && Next[0] == '{'); - } - - return; - } - - Debugprintf("%d %s", TNC->Port, Msg); - - -// {"COMMAND":"RX_BUFFER","DATA-ARRAY":[],"EOF":"EOF"} -/* {"COMMAND":"RX_BUFFER","DATA-ARRAY":[{"DXCALLSIGN":"GM8BPQ","DXGRID":"","TIMESTAMP":1642579504, -"RXDATA":[{"dt":"f","fn":"main.js","ft":"text\/javascript" -,"d":"data:text\/javascript;base64,Y29uc3Qge.....9KTsK","crc":"123123123"}]}],"EOF":"EOF"} - - - -{"arq":"received","uuid":"a1346319-6eb0-42aa-b5a0-c9493c8ccdca","timestamp":1645812393,"dxcallsign":"G8BPQ-2","dxgrid":"","data":"QyBHOEJQUS0yIEc4QlBRLTIgRzhCUFEtMiA="} -{"ptt":"True"} - - -*/ - if (memcmp(Msg, "{\"arq\":\"received\"", 17) == 0) - { - int NewLen; - char * ptr, *ptr2, *Type; - char * Call = 0; - char * myCall = 0; - - Msg += 17; - - ptr = getJSONValue(Msg, "\"data\""); - Type = ++ptr; - - // Decode Base64 - - // FreeData replaces / with \/ so need to undo - - ptr2 = strstr(Type, "\\/"); - - while (ptr2) - { - memmove(ptr2, ptr2 + 1, strlen(ptr2)); - ptr2 = strstr(ptr2, "\\/"); - } - - Len = strlen(Type) - 1; - - // Debugprintf("RX %d %s %d", TNC->Port, FN, Len); - - ptr = ptr2 = Type; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - NewLen = (int)(ptr2 - Type); - - if (*(ptr-1) == '=') - NewLen--; - - if (*(ptr-2) == '=') - NewLen--; - - Type[NewLen] = 0; - - myCall = getJSONValue(Msg, "\"mycallsign\""); - Call = getJSONValue(Msg, "\"dxcallsign\""); - - if (Call) - { - Call++; - strlop(Call, '"'); - } - - if (myCall) - { - myCall++; - strlop(myCall, '"'); - } - - - FreeDataProcessTNCMessage(TNC, Call, Type, NewLen); - - return; - } - - if (memcmp(Msg, "{\"COMMAND\":\"RX_MSG_BUFFER\"", 26) == 0) - { - char * Next, * This; - - Msg += 26; - ptr = getJSONValue(Msg, "\"EOF\""); - ptr = getJSONValue(Msg, "\"DATA-ARRAY\""); - - This = ptr; - - if (This[1] == '{') // Array of objects - { - This++; - do { - Next = getObjectFromArray(This); - ProcessMessageObject(TNC, This); - This = Next; - } while (Next && Next[0] == '{'); - - // Delete from TNC - - SendTNCCommand(TNC, "SET", "DEL_RX_MSG_BUFFER"); - } - - - return; - } -} - -int FreeDataConnect(struct TNCINFO * TNC, char * Call) -{ - char Connect[] = "{\"type\" : \"arq\", \"command\": \"connect\" , \"dxcallsign\": \"%s\"}\n"; - char Msg[128]; - int Len; - - Len = sprintf(Msg, Connect, Call); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - -int FreeDataDisconnect(struct TNCINFO * TNC) -{ - char Disconnect[] = "{\"type\" : \"arq\", \"command\": \"disconnect\"}\n"; - char Msg[128]; - int Len; - -// return FreeDataSendCommand(TNC, "D"); - - Len = sprintf(Msg, Disconnect); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - - -int FreeGetData(struct TNCINFO * TNC) -{ - char GetData[] = "{\"type\" : \"get\", \"command\": \"rx_buffer\"}\n"; - char Msg[128]; - int Len; - - Len = sprintf(Msg, GetData); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - -int FreeDataSendCommand(struct TNCINFO * TNC, char * Msg) -{ - // Commands are simulated as Messages to the remote BPQ. The TNC itself does not handle any commands - - // First Byte of MSG is a Type - Command or Data. MSG has a limited character set Use =xx for Now. - - // Current Types - C = Connect, D = Disconnect, I = info - - SendAsRaw(TNC, TNC->FreeDataInfo->farCall, TNC->FreeDataInfo->ourCall, Msg, strlen(Msg)); - return 0; -} - -void FreeDataProcessDaemonMsg(struct TNCINFO * TNC) -{ - int InputLen, MsgLen; - char * ptr; - int OpenBraces; - int CloseBraces; - char c; - - - // shouldn't get several messages per packet, as each should need an ack - // May get message split over packets - - if (TNC->InputLen > 8000) // Shouldnt have packets longer than this - TNC->InputLen=0; - - InputLen=recv(TNC->TCPSock, &TNC->ARDOPBuffer[TNC->InputLen], 8191 - TNC->InputLen, 0); - - if (InputLen == 8191) - c = 0; - - - if (InputLen == 0 || InputLen == SOCKET_ERROR) - { - // Does this mean closed? - - closesocket(TNC->TCPSock); - - TNC->TCPSock = 0; - - TNC->DAEMONCONNECTED = FALSE; - TNC->Streams[0].ReportDISC = TRUE; - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - return; - } - - TNC->InputLen += InputLen; - -loop: - TNC->ARDOPBuffer[TNC->InputLen] = 0; // So we cat use string functions - - // Message should be json. We know the format, so don't need a general parser, but need to know if complete. - // I think counting { and } and stopping if equal should work; - - - if (TNC->ARDOPBuffer[0] != '{') - { - TNC->InputLen = 0; - return; - } - - ptr = &TNC->ARDOPBuffer[0]; - - OpenBraces = 0; - CloseBraces = 0; - - while (c = *(ptr++)) - { - if (c == '{') - OpenBraces ++; - else if (c == '}') - CloseBraces ++; - - if (OpenBraces == CloseBraces) - { - MsgLen = ptr - (char * )TNC->ARDOPBuffer; - - ProcessDAEMONJSON(TNC, TNC->ARDOPBuffer, MsgLen); - - if (TNC->InputLen == 0 || *ptr == 0) - { - TNC->InputLen = 0; - return; - } - - // More in buffer - - memmove(TNC->ARDOPBuffer, ptr, TNC->InputLen - MsgLen); - - TNC->InputLen -= MsgLen; - goto loop; - } - - } - // Message Incomplete - wait for rest; -} - - - - - - -void FreeDataProcessTNCMsg(struct TNCINFO * TNC) -{ - int DataInputLen, MsgLen; - char * ptr, * endptr; - int maxlen; - - // May get message split over packets or multiple messages per packet - - // A complete file transfer arrives as one message, so can bw very long - - - if (TNC->DataInputLen > MAXRXSIZE) // Shouldnt have packets longer than this - TNC->DataInputLen=0; - - maxlen = MAXRXSIZE - TNC->DataInputLen; - - if (maxlen >1400) - maxlen = 1400; - - DataInputLen = recv(TNC->TCPDataSock, &TNC->ARDOPDataBuffer[TNC->DataInputLen], maxlen, 0); - - if (DataInputLen == 0 || DataInputLen == SOCKET_ERROR) - { - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - closesocket(TNC->TCPDataSock); - - TNC->TCPDataSock = 0; - - TNC->TNCCONNECTED = FALSE; - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - return; - } - - TNC->DataInputLen += DataInputLen; - - TNC->ARDOPDataBuffer[TNC->DataInputLen] = 0; // So we can use string functions - - // Message should be json. We know the format, so don't need a general parser, but need to know if complete. - // I think counting { and } and stopping if equal should work; - -// Debugprintf(TNC->ARDOPDataBuffer); - - //I think now messages end with LF - -loop: - - endptr = strchr(TNC->ARDOPDataBuffer, 10); - - if (endptr == 0) - return; - - *(endptr) = 0; - - if (TNC->ARDOPDataBuffer[0] != '{') - { - TNC->DataInputLen = 0; - return; - } - - ptr = &TNC->ARDOPDataBuffer[0]; - - MsgLen = endptr - ptr; - - ProcessTNCJSON(TNC, ptr, MsgLen); - - // MsgLen doesnt include lf - - MsgLen++; - - if (TNC->DataInputLen == MsgLen) - { - TNC->DataInputLen = 0; - return; - } - - // More in buffer - - ptr += MsgLen; - TNC->DataInputLen -= MsgLen; - - memmove(TNC->ARDOPDataBuffer, ptr, TNC->DataInputLen + 1); - - goto loop; - - // Message Incomplete - wait for rest; -} - - - -VOID FreeDataThread(void * portptr); - -int ConnecttoFreeData(int port) -{ - _beginthread(FreeDataThread, 0, (void *)(size_t)port); - - return 0; -} - -static SOCKADDR_IN sinx; -static SOCKADDR_IN rxaddr; - - -VOID FreeDataThread(void * portptr) -{ - // FreeData TNC has two sessions, not sure why! - - // Messages are JSON encapulated - // Opens deamon socket. TNC socket is only available once Start TNC command sent - // Looks for data on socket(s) - - int port = (int)(size_t)portptr; - char Msg[255]; - int err, i, ret; - u_long param=1; - BOOL bcopt=TRUE; - struct hostent * HostEnt; - struct TNCINFO * TNC = TNCInfo[port]; - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - - if (TNC->HostName == NULL) - return; - - TNC->BusyFlags = 0; - - TNC->DAEMONCONNECTING = TRUE; - - Sleep(3000); // Allow init to complete - -// printf("Starting FreeDATA Thread\n"); - -// if on Windows and Localhost see if TNC is running - -#ifdef WIN32 - - if (strcmp(TNC->HostName, "127.0.0.1") == 0) - { - // can only check if running on local host - - TNC->PID = GetListeningPortsPID(TNC->destaddr.sin_port); - - if (TNC->PID == 0) - goto TNCNotRunning; - - // Get the File Name in case we want to restart it. - - if (TNC->ProgramPath == NULL) - { - if (GetModuleFileNameExPtr) - { - HANDLE hProc; - char ExeName[256] = ""; - - hProc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, TNC->PID); - - if (hProc) - { - GetModuleFileNameExPtr(hProc, 0, ExeName, 255); - CloseHandle(hProc); - - TNC->ProgramPath = _strdup(ExeName); - } - } - } - goto TNCRunning; - } - -#endif - -TNCNotRunning: - - // Not running or can't check, restart if we have a path - -/* if (TNC->ProgramPath) - { - Consoleprintf("Trying to (re)start TNC %s", TNC->ProgramPath); - - if (RestartTNC(TNC)) - CountRestarts(TNC); - - Sleep(TNC->AutoStartDelay); - } -*/ -TNCRunning: - - if (TNC->Alerted == FALSE) - { - sprintf(TNC->WEB_COMMSSTATE, "Connecting to Daemon"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - - TNC->destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - TNC->Datadestaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - - if (TNC->destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - { - TNC->DAEMONCONNECTING = FALSE; - sprintf(Msg, "Resolve Failed for FreeData Host - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - return; // Resolve failed - } - memcpy(&TNC->destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - memcpy(&TNC->Datadestaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - -// closesocket(TNC->TCPDataSock); -// closesocket(TNC->TCPSock); - - TNC->TCPDataSock=socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for FreeData TNC socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->DAEMONCONNECTING = FALSE; - return; - } - - TNC->TCPSock = socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for FreeData Data Daemon socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->DAEMONCONNECTING = FALSE; - closesocket(TNC->TCPDataSock); - - return; - } - - setsockopt(TNC->TCPSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(TNC->TCPSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - // Connect Daemon Port - - if (connect(TNC->TCPSock,(LPSOCKADDR) &TNC->Datadestaddr,sizeof(TNC->Datadestaddr)) == 0) - { - // - // Connected successful - // - } - else - { - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - i=sprintf(Msg, "Connect Failed for FreeData Daemon socket - error code = %d\r\n", err); - WritetoConsole(Msg); - sprintf(TNC->WEB_COMMSSTATE, "Connection to Daemon failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->Alerted = TRUE; - } - - closesocket(TNC->TCPSock); - TNC->TCPSock = 0; - TNC->DAEMONCONNECTING = FALSE; - - RestartTNC(TNC); - return; - } - - Sleep(1000); - - TNC->LastFreq = 0; - - TNC->DAEMONCONNECTING = FALSE; - TNC->DAEMONCONNECTED = TRUE; - TNC->BusyFlags = 0; - TNC->InputLen = 0; - TNC->Alerted = FALSE; - - TNC->Alerted = TRUE; - - sprintf(TNC->WEB_COMMSSTATE, "Connected to FreeData Daemon"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - sprintf(Msg, "Connected to FreeData Daemon Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - - #ifndef LINBPQ -// FreeSemaphore(&Semaphore); - Sleep(1000); // Give VARA time to update Window title -// EnumWindows(EnumVARAWindowsProc, (LPARAM)TNC); -// GetSemaphore(&Semaphore, 52); -#endif - - while (TNC->DAEMONCONNECTED || TNC->TNCCONNECTED) - { - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - if (TNC->DAEMONCONNECTED) - FD_SET(TNC->TCPSock,&readfs); - - if (TNC->TCPSock) - FD_SET(TNC->TCPSock,&errorfs); - - if (TNC->TNCCONNECTED) - FD_SET(TNC->TCPDataSock,&readfs); - -// FD_ZERO(&writefs); - -// if (TNC->BPQtoWINMOR_Q) FD_SET(TNC->TCPSock,&writefs); // Need notification of busy clearing - - if (TNC->TNCCONNECTING || TNC->TNCCONNECTED) FD_SET(TNC->TCPDataSock,&errorfs); - - timeout.tv_sec = 90; - timeout.tv_usec = 0; // We should get messages more frequently that this - - ret = select((int)TNC->TCPSock + 1, &readfs, NULL, &errorfs, &timeout); - - if (ret == SOCKET_ERROR) - { - Debugprintf("FreeData Select failed %d ", WSAGetLastError()); - goto Lost; - } - if (ret > 0) - { - // See what happened - - if (FD_ISSET(TNC->TCPDataSock, &readfs)) - { - GetSemaphore(&Semaphore, 52); - FreeDataProcessTNCMsg(TNC); - FreeSemaphore(&Semaphore); - } - - if (FD_ISSET(TNC->TCPSock, &readfs)) - { - GetSemaphore(&Semaphore, 52); - FreeDataProcessDaemonMsg(TNC); - FreeSemaphore(&Semaphore); - } - - if (FD_ISSET(TNC->TCPDataSock, &errorfs)) - { -Lost: - sprintf(Msg, "FreeData Daemon Connection lost for Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to Daemon lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->TNCCONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - closesocket(TNC->TCPDataSock); - TNC->TCPDataSock = 0; - } - - if (FD_ISSET(TNC->TCPSock, &errorfs)) - { - sprintf(Msg, "FreeData Daemon Connection lost for Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to Daemon lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->DAEMONCONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - closesocket(TNC->TCPSock); - TNC->TCPSock = 0; - } - continue; - } - else - { - } - } - - if (TNC->TCPDataSock) - { - shutdown(TNC->TCPDataSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPDataSock); - } - - if (TNC->TCPSock) - { - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPSock); - } - - sprintf(Msg, "FreeData Thread Terminated Port %d\r\n", TNC->Port); - WritetoConsole(Msg); -} - -void ConnectTNCPort(struct TNCINFO * TNC) -{ - char Msg[255]; - int err; - int bcopt = TRUE; - - TNC->TNCCONNECTING = TRUE; - - TNC->TCPDataSock = socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - sprintf(Msg, "Socket Failed for FreeData TNC socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->TNCCONNECTING = FALSE; - return; - } - - setsockopt(TNC->TCPDataSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(TNC->TCPDataSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - if (connect(TNC->TCPDataSock,(LPSOCKADDR) &TNC->destaddr,sizeof(TNC->destaddr)) == 0) - { - // Connected successful - - sprintf(TNC->WEB_COMMSSTATE, "Connected to FreeData TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->TNCCONNECTING = FALSE; - TNC->TNCCONNECTED = TRUE; - TNC->Alerted = FALSE; - return; - } - - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - sprintf(Msg, "Connect Failed for FreeData TNC socket - error code = %d Port %d\n", - err, htons(TNC->destaddr.sin_port)); - - WritetoConsole(Msg); - TNC->Alerted = TRUE; - TNC->TNCCONNECTING = FALSE; - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - - closesocket(TNC->TCPDataSock); - - TNC->TCPDataSock = 0; - TNC->TNCCONNECTING = FALSE; - return; -} - diff --git a/FreeDATA-HPLaptop-2.c b/FreeDATA-HPLaptop-2.c deleted file mode 100644 index abf9b7c..0000000 --- a/FreeDATA-HPLaptop-2.c +++ /dev/null @@ -1,4654 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// Interface to allow G8BPQ switch to use FreeData TNC - - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include - -#ifndef WIN32 -#ifndef MACBPQ -#include -#endif -#endif - -#include "CHeaders.h" -#include "bpq32.h" -#include "tncinfo.h" - -#define SD_BOTH 0x02 - -#define FREEDATABUFLEN 16384 // TCP buffer size - -int KillTNC(struct TNCINFO * TNC); -static int RestartTNC(struct TNCINFO * TNC); - -int (WINAPI FAR *GetModuleFileNameExPtr)(); -extern int (WINAPI FAR *EnumProcessesPtr)(); -static int Socket_Data(int sock, int error, int eventcode); -VOID MoveWindows(struct TNCINFO * TNC); -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen); -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); -VOID SendInitScript(struct TNCINFO * TNC); -int ProcessEscape(UCHAR * TXMsg); -static void SendPoll(struct TNCINFO * TNC); -void SendMode(struct TNCINFO * TNC); -static int ConnecttoFreeData(int port); -void ConnectTNCPort(struct TNCINFO * TNC); -int FreeDataSendCommand(struct TNCINFO * TNC, char * data); -static void SendPing(struct TNCINFO * TNC, char * Call); -static void SendCQ(struct TNCINFO * TNC); -char * stristr (char *ch1, char *ch2); -int zEncode(unsigned char * in, unsigned char * out, int len, unsigned char * Banned); -static void SendDataMsg(struct TNCINFO * TNC, char * Call, char * Msg, int Len); -static int SendAsRaw(struct TNCINFO * TNC, char * Call, char * myCall, char * Msg, int Len); -static int SendAsFile(struct TNCINFO * TNC, char * Call, char * Msg, int Len); -char * byte_base64_encode(char *str, int len); -void xdecodeblock( unsigned char in[4], unsigned char out[3] ); -void FlushData(struct TNCINFO * TNC); -void CountRestarts(struct TNCINFO * TNC); -void StopTNC(struct TNCINFO * TNC); -int FreeDataConnect(struct TNCINFO * TNC, char * Call); -int FreeDataDisconnect(struct TNCINFO * TNC); -int FreeGetData(struct TNCINFO * TNC); -static void SendBeacon(struct TNCINFO * TNC, int Interval); -void buildParamString(struct TNCINFO * TNC, char * line); -VOID FreeDataSuspendPort(struct TNCINFO * TNC); -VOID FreeDataReleasePort(struct TNCINFO * TNC); - - -static char ClassName[]="FREEDATASTATUS"; -static char WindowTitle[] = "FreeData Modem"; -static int RigControlRow = 205; - -#ifndef WIN32 -#include -#define MAXPNAMELEN 32 -#else -#include -#endif - -extern char * PortConfig[33]; -extern int SemHeldByAPI; - -static RECT Rect; - -extern struct TNCINFO * TNCInfo[41]; // Records are Malloc'd - -static int ProcessLine(char * buf, int Port); - -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - -#define MAXRXSIZE 512000 // Sets max size for file transfer (less base64 overhead - -int CaptureCount = 0; -int PlaybackCount = 0; - -int CaptureIndex = -1; // Card number -int PlayBackIndex = -1; - - - -char CaptureNames[16][MAXPNAMELEN + 2] = { "" }; -char PlaybackNames[16][MAXPNAMELEN + 2] = { "" }; - - -#ifdef WIN32 - -#include - -#pragma comment(lib, "winmm.lib") - -WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 12000, 24000, 2, 16, 0 }; - -WAVEOUTCAPS pwoc; -WAVEINCAPS pwic; - - -char * CaptureDevices = NULL; -char * PlaybackDevices = NULL; - -HWAVEOUT hWaveOut = 0; -HWAVEIN hWaveIn = 0; - -#endif - - -char * gen_uuid() -{ - char v[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - int i; - - //3fb17ebc-bc38-4939-bc8b-74f2443281d4 - //8 dash 4 dash 4 dash 4 dash 12 - - static char buf[37] = {0}; - - //gen random for all spaces because lazy - for (i = 0; i < 36; ++i) - { - buf[i] = v[rand()%16]; - } - - //put dashes in place - buf[8] = '-'; - buf[13] = '-'; - buf[18] = '-'; - buf[23] = '-'; - - //needs end byte - buf[36] = '\0'; - - return buf; -} - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC = TNCInfo[Port]; - char errbuf[256]; - - strcpy(errbuf, buf); - - ptr = strtok(buf, " \t\n\r"); - - if (ptr == NULL) return (TRUE); - - if (*ptr =='#') return (TRUE); // comment - - if (*ptr ==';') return (TRUE); // comment - - - if (_stricmp(buf, "ADDR")) - return FALSE; // Must start with ADDR - - ptr = strtok(NULL, " \t\n\r"); - - BPQport = Port; - p_ipad = ptr; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->FreeDataInfo = zalloc(sizeof(struct FreeDataINFO)); - -// TNC->FreeDataInfo->useBaseCall = 1; // Default - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - if (p_ipad == NULL) - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - WINMORport = atoi(p_port); - - TNC->TCPPort = WINMORport; - - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(WINMORport); - - TNC->HostName = malloc(strlen(p_ipad)+1); - - if (TNC->HostName == NULL) return TRUE; - - strcpy(TNC->HostName,p_ipad); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - } - - if (ptr) - { - if (_memicmp(ptr, "PATH", 4) == 0) - { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - } - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "CAPTURE", 7) == 0) - { - TNC->FreeDataInfo->Capture = _strupr(_strdup(&buf[8])); - strlop(TNC->FreeDataInfo->Capture, 13); - } - else if (_memicmp(buf, "PLAYBACK", 8) == 0) - { - TNC->FreeDataInfo->Playback = _strupr(_strdup(&buf[9])); - strlop(TNC->FreeDataInfo->Playback, 13); - } - - else if (_memicmp(buf, "LOGDIR ", 7) == 0) - TNC->LogPath = _strdup(&buf[7]); - - else if (_memicmp(buf, "HAMLIBHOST", 10) == 0) - { - TNC->FreeDataInfo->hamlibHost = _strdup(&buf[11]); - strlop(TNC->FreeDataInfo->hamlibHost, 13); - } - - else if (_memicmp(buf, "TuningRange", 11) == 0) - TNC->FreeDataInfo->TuningRange = atoi(&buf[12]); - - else if (_memicmp(buf, "TXLevel", 6) == 0) - TNC->FreeDataInfo->TXLevel = atoi(&buf[7]); - - else if (_memicmp(buf, "Explorer", 8) == 0) - TNC->FreeDataInfo->Explorer = atoi(&buf[9]); - - - else if (_memicmp(buf, "LimitBandWidth", 14) == 0) - TNC->FreeDataInfo->LimitBandWidth = atoi(&buf[15]); - - else if (_memicmp(buf, "HAMLIBPORT", 10) == 0) - TNC->FreeDataInfo->hamlibPort = atoi(&buf[11]); - - else if (_memicmp(buf, "USEBASECALL", 11) == 0) - TNC->FreeDataInfo->useBaseCall = atoi(&buf[12]); - - else if (_memicmp(buf, "RXDIRECTORY", 11) == 0) - { - TNC->FreeDataInfo->RXDir = _strdup(&buf[12]); - strlop(TNC->FreeDataInfo->RXDir, 13); - } - - else if (standardParams(TNC, buf) == FALSE) - strcat(TNC->InitScript, buf); - - } - - return (TRUE); -} - -char * Config; -static char * ptr1, * ptr2; - -int FreeDataGetLine(char * buf) -{ -loop: - - if (ptr2 == NULL) - return 0; - - memcpy(buf, ptr1, ptr2 - ptr1 + 2); - buf[ptr2 - ptr1 + 2] = 0; - ptr1 = ptr2 + 2; - ptr2 = strchr(ptr1, 13); - - if (buf[0] < 0x20) goto loop; - if (buf[0] == '#') goto loop; - if (buf[0] == ';') goto loop; - - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - buf[strlen(buf)] = 13; - - return 1; -} - -BOOL FreeDataReadConfigFile(int Port, int ProcLine()) -{ - char buf[256],errbuf[256]; - - Config = PortConfig[Port]; - - if (Config) - { - // Using config from bpq32.cfg - - if (strlen(Config) == 0) - { - return TRUE; - } - - ptr1 = Config; - ptr2 = strchr(ptr1, 13); - - if (!ProcLine(buf, Port)) - { - WritetoConsoleLocal("\n"); - WritetoConsoleLocal("Bad config record "); - WritetoConsoleLocal(errbuf); - } - } - else - { - sprintf(buf," ** Error - No Configuration info in bpq32.cfg"); - WritetoConsoleLocal(buf); - } - - return (TRUE); -} - - - -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - - - -#define MAXBPQPORTS 32 - -static time_t ltime; - - - -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen) -{ - if (TNC->hDevice) - { - // FreeData mode. Queue to Hostmode driver - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = EncLen; - memcpy(&buffptr->Data[0], Encoded, EncLen); - - C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); - TNC->Streams[Stream].FramesQueued++; - - return; - } -} - - -VOID FreeDataChangeMYC(struct TNCINFO * TNC, char * Call) -{ - UCHAR TXMsg[100]; - int datalen; - - if (strcmp(Call, TNC->CurrentMYC) == 0) - return; // No Change - - strcpy(TNC->CurrentMYC, Call); - - datalen = sprintf(TXMsg, "MYCALL %s\r", Call); -// FreeDataSendCommand(TNC, TXMsg); -} - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int datalen; - PMSGWITHLEN buffptr; -// char txbuff[500]; - unsigned int txlen = 0; - UCHAR * TXMsg; - - size_t Param; - int Stream = 0; - HKEY hKey=0; - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct ScanEntry * Scan; - - if (TNC == NULL) - return 0; // Port not defined - - switch (fn) - { - case 7: - - // 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances - - SendPoll(TNC); - - // Check for buffered data to send - - if (TNC->FreeDataInfo->toSendTimeout) - { - TNC->FreeDataInfo->toSendTimeout--; - if (TNC->FreeDataInfo->toSendTimeout <= 0) - FlushData(TNC); - } - - return 0; - - case 1: // poll - -// FreeDataCheckRX(TNC); - - if (TNC->TNCCONNECTED == FALSE && TNC->TNCCONNECTING == FALSE) - { - // See if time to reconnect - - time(<ime); - if (ltime - TNC->lasttime > 9 ) - { - TNC->lasttime = ltime; - ConnecttoFreeData(port); - } - } - - - while (TNC->PortRecord->UI_Q) - { - int datalen; - char * Buffer; - char FECMsg[512]; - char Call[12] = " "; - struct _MESSAGE * buffptr; - int CallLen; - char * ptr = FECMsg; - - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - -/* if (TNC->CONNECTED == 0 || - TNC->Streams[0].Connecting || - TNC->Streams[0].Connected) - { - // discard if TNC not connected or sesison active - - ReleaseBuffer(buffptr); - continue; - } -*/ - datalen = buffptr->LENGTH - MSGHDDRLEN; - Buffer = &buffptr->DEST[0]; // Raw Frame - Buffer[datalen] = 0; - - // Frame has ax.25 format header. Convert to Text - - CallLen = ConvFromAX25(Buffer + 7, Call); // Origin - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - *ptr++ = '!'; - - CallLen = ConvFromAX25(Buffer, Call); // Dest - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - Buffer += 14; // TO Digis - datalen -= 14; - - while ((Buffer[-1] & 1) == 0) - { - *ptr++ = ','; - CallLen = ConvFromAX25(Buffer, Call); - memcpy(ptr, Call, CallLen); - ptr += CallLen; - Buffer += 7; // End of addr - datalen -= 7; - } - - *ptr++ = '_'; - *ptr++ = 'U'; // UI Frame - *ptr++ = 0; // delimit calls - - if (Buffer[0] == 3) // UI - { - Buffer += 2; - datalen -= 2; - } - -// FreeDataSendSingleData(TNC, FECMsg, Buffer, datalen); - - ReleaseBuffer(buffptr); - } - - - if (TNC->DiscPending) - { - TNC->DiscPending--; - - if (TNC->DiscPending == 0) - { - // Too long in Disc Pending - Kill and Restart TNC - } - } - - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - { - // Send the DISCONNECT - - FreeDataDisconnect(TNC); - strcpy(TNC->WEB_TNCSTATE, "Disconnecting"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - } - } - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && STREAM->Attached == 0) - { - // New Attach - - int calllen; - char Msg[80]; - - Debugprintf("FreeData New Attach Stream %d", Stream); - - STREAM->Attached = TRUE; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, STREAM->MyCall); - TNC->Streams[Stream].MyCall[calllen] = 0; - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - // Stop Listening, and set MYCALL to user's call - - FreeDataSuspendPort(TNC); - FreeDataChangeMYC(TNC, TNC->Streams[0].MyCall); - TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Stop Scanning - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command(-1, Msg); - } - - if (STREAM->Attached) - CheckForDetach(TNC, Stream, STREAM, TidyClose, ForcedClose, CloseComplete); - - } - - // See if any frames for this port - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->BPQtoPACTOR_Q) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)Q_REM(&STREAM->BPQtoPACTOR_Q); - UCHAR * data = &buffptr->Data[0]; - STREAM->FramesQueued--; - txlen = (int)buffptr->Len; - - SendAsFile(TNC, TNC->FreeDataInfo->farCall, data, txlen); - } - - if (STREAM->PACTORtoBPQ_Q != 0) - { - buffptr = (PMSGWITHLEN)Q_REM(&STREAM->PACTORtoBPQ_Q); - - datalen = (int)buffptr->Len; - - buff->PORT = Stream; // Compatibility with Kam Driver - buff->PID = 0xf0; - memcpy(&buff->L2DATA, &buffptr->Data[0], datalen); // Data goes to + 7, but we have an extra byte - datalen += sizeof(void *) + 4; - - PutLengthinBuffer(buff, datalen); - - ReleaseBuffer(buffptr); - - return (1); - } - - if (STREAM->ReportDISC) // May need a delay so treat as a counter - { - STREAM->ReportDISC--; - if (STREAM->ReportDISC == 0) - { - buff->PORT = Stream; -// STREAM->Connected = 0; -// STREAM->Attached = 0; - return -1; - } - } - } - return (0); - - case 2: // send - - Stream = buff->PORT; - - if (!TNC->TNCCONNECTED) - { - // Send Error Response - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = 36; - memcpy(&buffptr->Data[0], "No Connection to TNC\r", 36); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return 0; // Don't try if not connected - } - - STREAM = &TNC->Streams[Stream]; - - if (TNC->SwallowSignon) - { - TNC->SwallowSignon = FALSE; // Discard *** connected - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - TXMsg = &buff->L2DATA[0]; - TXMsg[txlen] = 0; - - if (STREAM->Connected) - { - STREAM->PacketsSent++; - - SendDataMsg(TNC, TNC->FreeDataInfo->farCall, buff->L2DATA, txlen); - return 1; - } - - if (TNC->FreeDataInfo->Chat) - { - // Chat Mode - Send to other end - - char reply[512] = "m"; - char * p; - int Len; - - if (_stricmp(TXMsg, "/ex\r") == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - TNC->FreeDataInfo->Chat = 0; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Chat with %s ended. \r", TNC->FreeDataInfo->ChatCall); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - // Send as chat message - - //m�;send_message�;123�;64730c5c-d32c-47b4-9b11-c958fd07a185�;hhhhhhhhhhhhhhhhhh - //�;�;plain/text�; - - strlop(TXMsg, 13); - - strcpy(&reply[2], ";send_message"); - strcpy(&reply[16], ";123"); - reply[21] = ';'; - strcpy(&reply[22], gen_uuid()); - sprintf(&reply[59], ";%s\n", TXMsg); - - p = strchr(&reply[59], 0); - - p[1] = ';'; - strcpy(&p[3], ";plain/text"); - p[15] = ';'; - - Len = &p[16] - reply; - - SendAsRaw(TNC, TNC->FreeDataInfo->ChatCall, "", reply, Len); - - return 0; - } - - - - if (_memicmp(&buff->L2DATA[0], "D\r", 2) == 0 || _memicmp(&buff->L2DATA[0], "BYE\r", 4) == 0) - { - STREAM->ReportDISC = TRUE; // Tell Node - TNC->FreeDataInfo->Chat = 0; - return 0; - } - - - // See if Local command (eg RADIO) - - if (_memicmp(&buff->L2DATA[0], "RADIO ", 6) == 0) - { - sprintf(&buff->L2DATA[0], "%d %s", TNC->Port, &buff->L2DATA[6]); - - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK->CIRCUITINDEX, &buff->L2DATA[0])) - { - } - else - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return 1; // No buffers, so ignore - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", &buff->L2DATA[0]); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return 1; - } - - if (_memicmp(&buff->L2DATA[0], "OVERRIDEBUSY", 12) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - TNC->OverrideBusy = TRUE; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} OK\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - if (_memicmp(&buff->L2DATA[0], "PING ", 5) == 0) - { - char * Call = &buff->L2DATA[5]; - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - strlop(Call, 13); - strlop(Call, ' '); - SendPing(TNC, _strupr(Call)); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Ping Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "CQ", 2) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - SendCQ(TNC); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} CQ Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - - if (_memicmp(&buff->L2DATA[0], "CQ", 2) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - SendCQ(TNC); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} CQ Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "TXLEVEL ", 8) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - int Level = atoi(&buff->L2DATA[8]); - char TXL[] = "{\"type\" : \"set\", \"command\" : \"tx_audio_level\", \"value\": \"%d\"}\n"; - char Message[256]; - int Len, ret; - - Len = sprintf(Message, TXL, Level); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} TXLevel Set\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return 0; - } - - if (_memicmp(&buff->L2DATA[0], "SENDTEST", 8) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - char TXF[] = "{\"type\" : \"set\", \"command\" : \"send_test_frame\"}\n"; - char Message[256]; - int Len, ret; - - Len = sprintf(Message, TXF); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Test Frame Requested\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return 0; - } - - if (_memicmp(&buff->L2DATA[0], "CHAT ", 5) == 0) - { - char * Call = &buff->L2DATA[5]; - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - strlop(Call, 13); - strlop(Call, ' '); - - TNC->FreeDataInfo->Chat = 1; - memcpy(TNC->FreeDataInfo->ChatCall, _strupr(Call), 10); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Chat with %s. Enter /ex to exit\r", Call); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - - if (_memicmp(&TXMsg[0], "BEACON ", 7) == 0) - { - int Interval = atoi(&TXMsg[7]); - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - SendBeacon(TNC, Interval); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Ok\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - - - - // See if a Connect Command. - - if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect - { - char Connect[80]; - char loppedCall[10]; - char toCall[10]; - - char * ptr = strchr(&buff->L2DATA[2], 13); - - if (ptr) - *ptr = 0; - - // FreeDATA doesn't have the concept of a connection, so need to simulate it between the nodes - _strupr(&buff->L2DATA[2]); - - if (strlen(&buff->L2DATA[2]) > 9) - buff->L2DATA[11] = 0; - - strcpy(TNC->FreeDataInfo->toCall, &buff->L2DATA[2]); - strcpy(loppedCall, TNC->FreeDataInfo->toCall); - if (TNC->FreeDataInfo->useBaseCall) - strlop(loppedCall, '-'); - strcpy(TNC->FreeDataInfo->farCall, loppedCall); - - // MYCALL and Target call are end to end concepts - the TNC cam can only use one call, set at TNC start. and no SSID's - // Messages are sent at TNC level to the tnc call, so we send our tnc call to the other end - - - txlen = sprintf(Connect, "C %s %s %s ", &buff->L2DATA[2], STREAM->MyCall, TNC->FreeDataInfo->ourCall); - - // See if Busy -/* - if (InterlockedCheckBusy(TNC)) - { - // Channel Busy. Unless override set, wait - - if (TNC->OverrideBusy == 0) - { - // Save Command, and wait up to 10 secs - - sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - TNC->ConnectCmd = _strdup(Connect); - TNC->BusyDelay = TNC->BusyWait * 10; // BusyWait secs - return 0; - } - } -*/ - TNC->OverrideBusy = FALSE; - - memset(STREAM->RemoteCall, 0, 10); - strcpy(STREAM->RemoteCall, &buff->L2DATA[2]); - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - -// FreeDataSendCommand(TNC, Connect); - FreeDataConnect(TNC, STREAM->RemoteCall); - STREAM->Connecting = TRUE; - return 0; - - } - - // Normal data. Send to TNC - - // The TNC doesn't have any commands, so send error message - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Not connected\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - // strlop(buff->L2DATA, 13); - // txlen = SendDataMsg(TNC, TNC->, buff->L2DATA); - // FreeDataSendData(TNC, TXMsg, txlen); - - return 0; - - case 3: - - // CHECK IF OK TO SEND (And check TNC Status) - - Stream = (int)(size_t)buff; - - // FreeData TNC can buffer unlimited data - - if (TNC->Streams[Stream].Attached == 0) - return (TNC->TNCCONNECTED != 0) << 8 | 1; - - return ((TNC->TNCCONNECTED != 0) << 8 | TNC->Streams[Stream].Disconnecting << 15); // OK - - case 5: // Close - - StopTNC(TNC); - - // Drop through - - case 4: // reinit7 - - if (TNC->TCPDataSock) - { - shutdown(TNC->TCPDataSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPDataSock); - } - - if (TNC->WeStartedTNC) - KillTNC(TNC); - - - return 0; - - case 6: // Scan Stop Interface - - Param = (size_t)buff; - - if (Param == 2) // Check Permission (Shouldn't happen) - { - Debugprintf("Scan Check Permission called on FreeDATA"); - return 1; // OK to change - } - - if (Param == 1) // Request Permission - { - if (!TNC->CONNECTED) - return 0; // No connection so no interlock - - if (TNC->ConnectPending == 0 && TNC->PTTState == 0) - { - FreeDataSuspendPort(TNC); - TNC->GavePermission = TRUE; - return 0; // OK to Change - } - - if (TNC->ConnectPending) - TNC->ConnectPending--; // Time out if set too long - - return TRUE; - } - - if (Param == 3) // Release Permission - { - if (TNC->GavePermission) - { - TNC->GavePermission = FALSE; - if (TNC->ARDOPCurrentMode[0] != 'S') // Skip - FreeDataReleasePort(TNC); - } - return 0; - } - - // Param is Address of a struct ScanEntry - - Scan = (struct ScanEntry *)buff; - return 0; - } - return 0; -} - -VOID FreeDataReleaseTNC(struct TNCINFO * TNC) -{ - // Set mycall back to Node or Port Call, and Start Scanner - - UCHAR TXMsg[1000]; - - FreeDataChangeMYC(TNC, TNC->NodeCall); - - // Start Scanner - - sprintf(TXMsg, "%d SCANSTART 15", TNC->Port); - - Rig_Command(-1, TXMsg); - - FreeDataReleasePort(TNC); - ReleaseOtherPorts(TNC); -} -VOID FreeDataSuspendPort(struct TNCINFO * TNC) -{ - char CMD[] = "{\"type\" : \"set\", \"command\" : \"respond_to_cq\", \"value\": \"False\"}\n"; - send(TNC->TCPDataSock, CMD, strlen(CMD), 0); -} - -VOID FreeDataReleasePort(struct TNCINFO * TNC) -{ - char CMD[] = "{\"type\" : \"set\", \"command\" : \"respond_to_cq\", \"value\": \"True\"}\n"; - send(TNC->TCPDataSock, CMD, strlen(CMD), 0); -} - - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, "" - "" - "FreDATA Status" - "

FreeData Status" - "

", - TNC->Port); - - - Len += sprintf(&Buff[Len], ""); - - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); -// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
Proto State%s
Traffic%s
TNC Restarts
"); - - Len += sprintf(&Buff[Len], "", TNC->WebBuffer); - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - -#ifndef LINBPQ - -#define BGCOLOUR RGB(236,233,216) -static HBRUSH RedBrush = NULL; -HBRUSH GreenBrush; -HBRUSH BlueBrush; -static HBRUSH bgBrush = NULL; - -extern HWND ClientWnd, FrameWnd; -extern int OffsetH, OffsetW; - -extern HMENU hMainFrameMenu; -extern HMENU hBaseMenu; -extern HANDLE hInstance; - -extern HKEY REGTREE; - - -/* -static LRESULT CALLBACK PacWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - MINMAXINFO * mmi; - PAINTSTRUCT ps; - HDC hdc; - - int i; - struct TNCINFO * TNC; - - HKEY hKey; - char Key[80]; - int retCode, disp; - - for (i=0; i<41; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC->hDlg == hWnd) - break; - } - - if (TNC == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - switch (message) { - - case WM_CREATE: - - break; - - case WM_PAINT: - - hdc = BeginPaint(hWnd, &ps); - -// SelectObject(ps.hdc, RedBrush); - SelectObject(ps.hdc, GreenBrush); -// SelectObject(ps.hdc, GetStockObject(GRAY_BRUSH)); - - EndPaint(hWnd, &ps); - break; - - case WM_GETMINMAXINFO: - - if (TNC->ClientHeight) - { - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = TNC->ClientWidth; - mmi->ptMaxSize.y = TNC->ClientHeight; - mmi->ptMaxTrackSize.x = TNC->ClientWidth; - mmi->ptMaxTrackSize.y = TNC->ClientHeight; - } - - break; - - - case WM_MDIACTIVATE: - { - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - - if (TNC->hMenu) - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)TNC->hMenu, "Actions"); - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - -// SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) TNC->hMenu, (LPARAM) TNC->hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - // call DrawMenuBar after the menu items are set - DrawMenuBar(FrameWnd); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - } - - - - case WM_INITMENUPOPUP: - - if (wParam == (WPARAM)TNC->hMenu) - { - if (TNC->ProgramPath) - { - if (strstr(TNC->ProgramPath, " TNC") || strstr(TNC->ProgramPath, "ARDOP") || strstr(TNC->ProgramPath, "VARA")) - { - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_ENABLED); - - break; - } - } - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_GRAYED); - } - - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - case WINMOR_KILL: - - KillTNC(TNC); - break; - - case WINMOR_RESTART: - - KillTNC(TNC); - RestartTNC(TNC); - break; - - case WINMOR_RESTARTAFTERFAILURE: - - TNC->RestartAfterFailure = !TNC->RestartAfterFailure; - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", TNC->Port); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - RegSetValueEx(hKey,"TNC->RestartAfterFailure",0,REG_DWORD,(BYTE *)&TNC->RestartAfterFailure, 4); - RegCloseKey(hKey); - } - break; - - case ARDOP_ABORT: - - if (TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SIZING: - case WM_SIZE: - - MoveWindows(TNC); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - - case SC_RESTORE: - - TNC->Minimized = FALSE; - break; - - case SC_MINIMIZE: - - TNC->Minimized = TRUE; - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - - case WM_CTLCOLORSTATIC: - { - HDC hdcStatic = (HDC)wParam; - SetTextColor(hdcStatic, RGB(0, 0, 0)); - SetBkMode(hdcStatic, TRANSPARENT); - return (LONG)bgBrush; - } - - case WM_DESTROY: - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); -} -*/ - -#endif - - - -VOID * FreeDataExtInit(EXTPORTDATA * PortEntry) -{ - int port; - char Msg[255]; - char * ptr; - struct TNCINFO * TNC; - char * TempScript; - u_long param = 1; - int line; - int i; - - srand(time(NULL)); - - port = PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); - WritetoConsole(Msg); - - return ExtProc; - } - - if (TNC->FreeDataInfo->TuningRange == 0) - TNC->FreeDataInfo->TuningRange = 50; - - if (TNC->FreeDataInfo->TXLevel == 0) - TNC->FreeDataInfo->TXLevel = 50; - - if (TNC->AutoStartDelay == 0) - TNC->AutoStartDelay = 2000; - -#ifndef LINBPQ - - if (bgBrush == NULL) - { - bgBrush = CreateSolidBrush(BGCOLOUR); - RedBrush = CreateSolidBrush(RGB(255,0,0)); - GreenBrush = CreateSolidBrush(RGB(0,255,0)); - BlueBrush = CreateSolidBrush(RGB(0,0,255)); - } - -#endif - - Consoleprintf("FreeData Host %s %d", TNC->HostName, TNC->TCPPort); - - TNC->Port = port; - TNC->Hardware = H_FREEDATA; - - TNC->WeStartedTNC = 1; - - TNC->ARDOPDataBuffer = malloc(MAXRXSIZE); - TNC->ARDOPBuffer = malloc(FREEDATABUFLEN); - - TNC->PortRecord = PortEntry; - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - memcpy(TNC->NodeCall, MYNODECALL, 10); - else - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - memcpy(TNC->FreeDataInfo->ourCall, TNC->NodeCall, 10); - strlop(TNC->FreeDataInfo->ourCall, ' '); - if (TNC->FreeDataInfo->useBaseCall) - strlop(TNC->FreeDataInfo->ourCall, '-'); - - if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) - TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - - if (TNC->PacketChannels > 1) - TNC->PacketChannels = 1; - - PortEntry->MAXHOSTMODESESSIONS = TNC->PacketChannels + 1; - - PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only - PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream - - PortEntry->PORTCONTROL.UICAPABLE = TRUE; - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 236; - - TNC->SuspendPortProc = FreeDataSuspendPort; - TNC->ReleasePortProc = FreeDataReleasePort; - -// PortEntry->PORTCONTROL.PORTSTARTCODE = KAMStartPort; -// PortEntry->PORTCONTROL.PORTSTOPCODE = KAMStopPort; - - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - // Set Essential Params and MYCALL - - // Put overridable ones on front, essential ones on end - - TempScript = zalloc(1000); - - // cant think of any yet - - if (TNC->InitScript) - { - strcat(TempScript, TNC->InitScript); - free(TNC->InitScript); - } - - TNC->InitScript = TempScript; - - // Set MYCALL - - sprintf(Msg, "MYCALL %s\r", TNC->NodeCall); - strcat(TNC->InitScript, Msg); - - strcpy(TNC->CurrentMYC, TNC->NodeCall); - - if (TNC->WL2K == NULL) - if (PortEntry->PORTCONTROL.WL2KInfo.RMSCall[0]) // Already decoded - TNC->WL2K = &PortEntry->PORTCONTROL.WL2KInfo; - - PortEntry->PORTCONTROL.TNC = TNC; - - // Build SSID List - - if (TNC->LISTENCALLS) - { - strcpy(TNC->FreeDataInfo->SSIDList, TNC->LISTENCALLS); - } - else - { - APPLCALLS * APPL; - char Appl[11] = ""; - char * List = TNC->FreeDataInfo->SSIDList; - char * SSIDptr; - int SSID; - int Listptr; - - // list is a set of numbers separated by spaces eg 0 2 10 - - SSIDptr = strchr(TNC->NodeCall, '-'); - if (SSIDptr) - SSID = atoi(SSIDptr + 1); - else - SSID = 0; - - Listptr = sprintf(List, "%d", SSID); - - for (i = 0; i < 32; i++) - { - APPL=&APPLCALLTABLE[i]; - - if (APPL->APPLCALL_TEXT[0] > ' ') - { - char * ptr; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - - SSIDptr = strchr(Appl, '-'); - if (SSIDptr) - SSID = atoi(SSIDptr + 1); - else - SSID = 0; - - Listptr += sprintf(&List[Listptr], " %d", SSID); - } - } - List[Listptr] = 0; - } - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 520; - TNC->WebWinY = 500; - TNC->WebBuffer = zalloc(5000); - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - TNC->WEB_CHANSTATE = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_PROTOSTATE = zalloc(100); - TNC->WEB_RESTARTTIME = zalloc(100); - TNC->WEB_RESTARTS = zalloc(100); - - TNC->WEB_MODE = zalloc(20); - TNC->WEB_TRAFFIC = zalloc(100); - -#ifndef LINBPQ - - line = 6; - - if (TNC->TXFreq) - { - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow + 22, PacWndProc, 500, 450, ForcedClose); - - InitCommonControls(); // loads common control's DLL - - CreateWindowEx(0, "STATIC", "TX Tune", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNE = CreateWindowEx(0, TRACKBAR_CLASS, "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNEVAL = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE, 320,line,30,20, TNC->hDlg, NULL, hInstance, NULL); - - SendMessage(TNC->xIDC_TXTUNE, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG(-200, 200)); // min. & max. positions - - line += 22; - } - else - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 450, ForcedClose); - - CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,450,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,line,106,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,520,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,line,110,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,144,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Proto State", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_PROTOSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,line,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,116,line,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,line,20,20 , TNC->hDlg, NULL, hInstance, NULL); - CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, - 0,170,250,300, TNC->hDlg, NULL, hInstance, NULL); - - TNC->ClientHeight = 450; - TNC->ClientWidth = 500; - - TNC->hMenu = CreatePopupMenu(); - - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill Freedata TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart Freedata TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after failed Connection"); - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); - - MoveWindows(TNC); -#endif - - strcpy(TNC->WEB_CHANSTATE, "Idle"); - SetWindowText(TNC->xIDC_CHANSTATE, TNC->WEB_CHANSTATE) - - // Convert sound card name to index - -#ifdef WIN32 - - if (CaptureDevices == NULL) // DOn't do it again if more that one port - { - CaptureCount = waveInGetNumDevs(); - - CaptureDevices = malloc((MAXPNAMELEN + 2) * CaptureCount); - CaptureDevices[0] = 0; - - printf("Capture Devices"); - - for (i = 0; i < CaptureCount; i++) - { - waveInOpen(&hWaveIn, i, &wfx, 0, 0, CALLBACK_NULL); //WAVE_MAPPER - waveInGetDevCaps((UINT_PTR)hWaveIn, &pwic, sizeof(WAVEINCAPS)); - - if (CaptureDevices) - strcat(CaptureDevices, ","); - strcat(CaptureDevices, pwic.szPname); - Debugprintf("%d %s", i + 1, pwic.szPname); - memcpy(&CaptureNames[i][0], pwic.szPname, MAXPNAMELEN); - _strupr(&CaptureNames[i][0]); - } - - PlaybackCount = waveOutGetNumDevs(); - - PlaybackDevices = malloc((MAXPNAMELEN + 2) * PlaybackCount); - PlaybackDevices[0] = 0; - - Debugprintf("Playback Devices"); - - for (i = 0; i < PlaybackCount; i++) - { - waveOutOpen(&hWaveOut, i, &wfx, 0, 0, CALLBACK_NULL); //WAVE_MAPPER - waveOutGetDevCaps((UINT_PTR)hWaveOut, &pwoc, sizeof(WAVEOUTCAPS)); - - if (PlaybackDevices[0]) - strcat(PlaybackDevices, ","); - strcat(PlaybackDevices, pwoc.szPname); - Debugprintf("%i %s", i + 1, pwoc.szPname); - memcpy(&PlaybackNames[i][0], pwoc.szPname, MAXPNAMELEN); - _strupr(&PlaybackNames[i][0]); - waveOutClose(hWaveOut); - } - } - -#endif - - time(&TNC->lasttime); // Get initial time value - - ConnecttoFreeData(port); - return ExtProc; -} - - -VOID TidyClose(struct TNCINFO * TNC, int Stream) -{ - // We don't get data acks, so can't check for bytes outstanding - - FreeDataDisconnect(TNC); -} - -VOID ForcedClose(struct TNCINFO * TNC, int Stream) -{ - FreeDataDisconnect(TNC); -} - - - -VOID CloseComplete(struct TNCINFO * TNC, int Stream) -{ - if (Stream == 0) - { - FreeDataReleaseTNC(TNC); - } - - - -} - -VOID FreeDataAbort(struct TNCINFO * TNC) -{ - FreeDataSendCommand(TNC, "ABORT\r"); -} - -// Host Mode Stuff (we reuse some routines in SCSPactor) - -VOID FreeDataDoTermModeTimeout(struct TNCINFO * TNC) -{ - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->ReinitState == 0) - { - //Checking if in Terminal Mode - Try to set back to Term Mode - - TNC->ReinitState = 1; - return; - } - - if (TNC->ReinitState == 1) - { - // Forcing back to Term Mode - - TNC->ReinitState = 0; - return; - } - - if (TNC->ReinitState == 3) - { - return; - } -} - -static RECT Rect1 = {30, 160, 400, 195}; - -int zEncode(unsigned char * in, unsigned char * out, int len, unsigned char * Banned) -{ - // Replace forbidden chars with =xx - - unsigned char * ptr = out; - unsigned char c; - - while (len--) - { - c = *(in++); - - if (strchr(&Banned[0], c)) - { - *(out++) = '='; - *(out++) = (c >> 4) + 'A'; - *(out++) = (c & 15) + 'A'; - } - else - *(out++) = c; - } - - return (out - ptr); -} - - - -VOID FreeDataProcessTNCMessage(struct TNCINFO * TNC, char * Call, unsigned char * Msg, int Len) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * toCall, * fromCall, * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - // First Byte of Message is Type. Messages can be commands or short (<120) data packets - // Data is encoded with =xx replacing restricted chars - - Msg[Len] = 0; - - switch (Msg[0]) - { - case 'C': - - // Connect Request. C G8BPQ-10 GM8BPQ-2 (Target, Origin) - - toCall = strtok_s(&Msg[2], " ", &Context); - fromCall = strtok_s(NULL, " ", &Context); - tncCall = strtok_s(NULL, " ", &Context); - - strcpy(TNC->FreeDataInfo->farCall, tncCall); - - ConvToAX25Ex(fromCall, axcall); // Allow -T and -R SSID's for MPS - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(axcall) == FALSE) - { - Debugprintf("FreeData Call from %s rejected", fromCall); - - // Send 'd' - - Sleep(1000); - FreeDataDisconnect(TNC); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(axcall, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - Sleep(1000); - FreeDataSendCommand(TNC, "d"); - - Debugprintf("FreeDara Call from %s not in ValidCalls - rejected", Call); - return; - } - } - } - - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(toCall, Appl) == 0) - break; - } - - if (App < 32) - { - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(Call, "-T" ) || strstr(Call, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - if (!CheckAppl(TNC, AppName)) - { - Sleep(1000); - FreeDataSendCommand(TNC, "dApplication not Available"); - return; - } - } - - ProcessIncommingConnectEx(TNC, fromCall, 0, TRUE, TRUE); - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - // if connect to an application, send command - - if (AppName[0]) - { - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf(buffptr->Data, "%s\r", AppName); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - } - - TNC->ConnectPending = FALSE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, toCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - if (SESS->Frequency == 1500) - { - // try to get from WL2K record - - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - } - } - SESS->Mode = TNC->WL2KMode; - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, toCall); - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - SESS->Mode = WL2K->mode; - } - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - STREAM->Connected = TRUE; - - // Send Connect ACK - Sleep(1000); - FreeDataSendCommand(TNC, "c"); - return; - - case 'c': - - // Connect ACK - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - STREAM->Connected = TRUE; - STREAM->Connecting = FALSE; - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connected to %s\r", TNC->FreeDataInfo->toCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - - return; - - case 'D': - - // Disconnect Command - - FreeDataSendCommand(TNC, "d"); - - // Drop through to disconnect this end - - case 'd': - - // Disconnect complete (response to sending "D") - // Or connect refused in response to "C" - - if (STREAM->Connecting) - { - // Connection Refused - If there is a message, pass to appl - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - if (Msg[1]) - buffptr->Len = sprintf(buffptr->Data, "Connect Rejected - %s\r", &Msg[1]); - else - buffptr->Len = sprintf(buffptr->Data, "Connect Rejected\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - return; - } - - // Release Session - - if (STREAM->Connected) - { - // Create a traffic record - - char logmsg[120]; - time_t Duration; - - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - } - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - return; - - case 'B': - - // Was Base64, but has been expanded - just send to User - - // If len > blocksize, fragment - - Len--; - Msg++; // Remove Type - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Msg, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Msg, 256); - Len -= 256; - Msg += 256; - STREAM->BytesRXed += 256; - - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Msg, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Msg, Len); - STREAM->BytesRXed += Len; - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - return; - - case 'I': - - // Encoded Response - - // Undo = transparency - - ptr = Msg + 1; - - while (ptr = strchr(ptr, '=')) - { - // Next two chars are a hex value - - a = ptr[1] - 'A'; - b = ptr[2] - 'A'; - memmove(ptr, ptr + 2, Len); - ptr[0] = (a << 4) + b; - ptr++; - } - - buffptr = GetBuff(); - buffptr->Len = sprintf(buffptr->Data, "%s", &Msg[1]); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - return; - - case 'f': - - // FreeDATA File Transfer - - // Seems to be f null fn null data - //f.;Makefile.;.;123123123.; - { - char * FN; - time_t CRC; - int FileLen; - char Filename[256]; - FILE * fp1; - unsigned char * ptr; - char Text[64]; - int textLen; - - - if (TNC->FreeDataInfo->RXDir == NULL) - { - Debugprintf("FreeDATA RXDIRECTORY not set - file transfer ignored"); - return; - } - - FN = _strdup(&Msg[3]); - ptr = &Msg[4] + strlen(FN); - - ptr = ptr + strlen(ptr) + 2; - CRC = atoi(ptr); - ptr = ptr + strlen(ptr) + 2; - - FileLen = Len - (ptr - Msg); - - sprintf(Filename, "%s\\%s", TNC->FreeDataInfo->RXDir, FN); - - fp1 = fopen(Filename, "wb"); - - if (fp1) - { - fwrite(ptr, 1, FileLen, fp1); - fclose(fp1); - textLen = sprintf(Text, "File %s received from %s \r", FN, Call); - WritetoTrace(TNC, Text, textLen); - } - else - Debugprintf("FreeDATA - File %s create failed %s", Filename); - - - free(FN); - return; - - } - - - } - - if (STREAM->Attached == 0) - return; - - - buffptr = GetBuff(); - - if (buffptr == 0) - { - return; // No buffers, so ignore - } - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", Msg); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - -} - - -VOID FreeDataProcessNewConnect(struct TNCINFO * TNC, char * fromCall, char * toCall) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - strcpy(TNC->FreeDataInfo->farCall, fromCall); - - ConvToAX25Ex(fromCall, axcall); // Allow -T and -R SSID's for MPS - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(axcall) == FALSE) - { - Debugprintf("FreeData Call from %s rejected", fromCall); - - // Send 'd' - - Sleep(1000); - FreeDataDisconnect(TNC); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(axcall, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - Sleep(1000); - FreeDataDisconnect(TNC); - - Debugprintf("FreeData Call from %s not in ValidCalls - rejected", fromCall); - return; - } - } - } - - // The TNC responds to any SSID so we can use incomming call as Appl Call - // No we can't - it responds but reports the configured call not the called call - - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(toCall, Appl) == 0) - break; - } - - if (App < 32) - { - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(fromCall, "-T" ) || strstr(fromCall, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - if (!CheckAppl(TNC, AppName)) - { - Sleep(1000); - FreeDataSendCommand(TNC, "dApplication not Available"); - return; - } - } - - ProcessIncommingConnectEx(TNC, fromCall, 0, TRUE, TRUE); - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - // if connect to an application, send command - - if (AppName[0]) - { - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf(buffptr->Data, "%s\r", AppName); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - } - - TNC->ConnectPending = FALSE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, toCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - if (SESS->Frequency == 1500) - { - // try to get from WL2K record - - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - } - } - SESS->Mode = TNC->WL2KMode; - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, toCall); - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - SESS->Mode = WL2K->mode; - } - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - STREAM->Connected = TRUE; - - return; - -} - -VOID FreeDataProcessConnectAck(struct TNCINFO * TNC, char * Call, unsigned char * Msg, int Len) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * toCall, * fromCall, * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - STREAM->Connected = TRUE; - STREAM->Connecting = FALSE; - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connected to %s\r", TNC->FreeDataInfo->toCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - - return; - -} -extern char LOC[7]; -/* -Line 104: if received_json["type"] == 'PING' and received_json["command"] == "PING": -Line 111: if received_json["type"] == 'ARQ' and received_json["command"] == "sendFile": -Line 142: if received_json["type"] == 'ARQ' and received_json["command"] == "sendMessage": -Line 173: if received_json["type"] == 'ARQ' and received_json["command"] == "stopTransmission": -Line 182: if received_json["type"] == 'GET' and received_json["command"] == 'STATION_INFO': -Line 195: if received_json["type"] == 'GET' and received_json["command"] == 'TNC_STATE': -Line 244: if received_json["type"] == 'GET' and received_json["command"] == 'RX_BUFFER': -Line 258: if received_json["type"] == 'GET' and received_json["command"] == 'RX_MSG_BUFFER': -Line 272: if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_BUFFER': -Line 275: if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_MSG_BUFFER': -*/ - -//{\"type\" : \"ARQ\", \"command\" : \"sendMessage\", \"dxcallsign\" : \"G8BPQ\", \"mode\" : \"10\", \"n_frames\" : \"1\", \"data\" : \"Hello Hello\" , \"checksum\" : \"123\", \"timestamp\" : 1642580748576} - - - -static unsigned char BANNED[] = {'"', '=', ':', '{', '}', '[', ']', '/', 13, 0}; // I think only need to escape = ": CR Null - - -static void SendDataMsg(struct TNCINFO * TNC, char * Call, char * Msg, int Len) -{ - // We can't base64 encode chunks. so buffer as original data and encode on send - - SendAsFile(TNC, TNC->FreeDataInfo->farCall, Msg, Len); - WritetoTrace(TNC, Msg, Len); - - return; -} - - - -static int SendAsRaw(struct TNCINFO * TNC, char * Call, char * myCall, char * Msg, int Len) -{ - char Message[16284]; - char * Base64; - - // TNC now only supports send_raw, with base64 encoded data - - char Template[] = "{\"type\" : \"arq\", \"command\" : \"send_raw\", \"uuid\" : \"%s\",\"parameter\":" - "[{\"dxcallsign\" : \"%s\", \"mode\": \"255\", \"n_frames\" : \"1\", \"data\" : \"%s\"}]}\n"; - - - Base64 = byte_base64_encode(Msg, Len); - - Len = sprintf(Message, Template, gen_uuid(), Call, Base64); - - free(Base64); - return send(TNC->TCPDataSock, Message, Len, 0); -} - -void FlushData(struct TNCINFO * TNC) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Info = TNC->FreeDataInfo; - int Len = Info->toSendCount; - - // We need to flag as data (B) then base64 encode it - - memmove(&Info->toSendData[1], Info->toSendData, Len); - Info->toSendData[0] = 'B'; - Len++; - - SendAsRaw(TNC, Info->farCall, Info->ourCall, Info->toSendData, Len); - - Info->toSendCount = 0; - Info->toSendTimeout = 0; - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - -} - -static int SendAsFile(struct TNCINFO * TNC, char * Call, char * Msg, int Len) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Info = TNC->FreeDataInfo; - - // Add to buffer - - if ((Info->toSendCount + Len) > 8192) // Reasonable Limit - { - // Send the buffered bit - - FlushData(TNC); - } - - memcpy(&Info->toSendData[Info->toSendCount], Msg, Len); - Info->toSendCount += Len; - Info->toSendTimeout = 10; // About a second - - STREAM->BytesTXed += Len; - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - return Len; -} - -static int SendTNCCommand(struct TNCINFO * TNC, char * Type, char * Command) -{ - char Message[256]; - int Len; - - Len = sprintf(Message, "{\"type\" : \"%s\", \"command\" : \"%s\"}\n", Type, Command); - return send(TNC->TCPDataSock, Message, Len, 0); -} - -static void SendPoll(struct TNCINFO * TNC) -{ - return; -} - -static void SendPing(struct TNCINFO * TNC, char * Call) -{ - char Ping[] = "{\"type\" : \"ping\", \"command\" : \"ping\", \"dxcallsign\" : \"%s\", \"timestamp\" : %d}\n"; - char Message[256]; - int Len, ret; - - Len = sprintf(Message, Ping, Call, time(NULL)); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - -static void SendCQ(struct TNCINFO * TNC) -{ - char CQ[] = "{\"type\" : \"broadcast\", \"command\" : \"cqcqcq\"}\n"; - - char Message[256]; - int Len, ret; - - Len = sprintf(Message, CQ); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - -static void SendBeacon(struct TNCINFO * TNC, int Interval) -{ - char Template1[] = "{\"type\" : \"broadcast\", \"command\" : \"start_beacon\", \"parameter\" : \"%d\"}\n"; - char Template2[] = "{\"type\" : \"broadcast\", \"command\" : \"stop_beacon\"}\n"; - - char Message[256]; - int Len, ret; - - if (Interval > 0) - Len = sprintf(Message, Template1, Interval); - else - Len = sprintf(Message, Template2); - - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - - -unsigned short int compute_crc(unsigned char *buf,int len); - - -int FreeDataWriteCommBlock(struct TNCINFO * TNC) -{ - if (TNC->hDevice) - return WriteCOMBlock(TNC->hDevice, TNC->TXBuffer, TNC->TXLen); - - return 0; -} - -char * getObjectFromArray(char * Msg) -{ - // This gets the next object from an array ({} = object, [] = array - // We look for the end of the object same number of { and }, teminate after } and return pointer to next object - // So we have terminated Msg, and returned next object in array - - // Only call if Msg is the next object in array - - - char * ptr = Msg; - char c; - - int Open = 0; - int Close = 0; - - while (c = *(ptr++)) - { - if (c == '{') Open ++; else if (c == '}') Close ++; - - if (Open == Close) - { - *(ptr++) = 0; - return ptr; - } - } - return 0; -} -/* - ["DATACHANNEL;RECEIVEDOPENER","ARQ;RECEIVING","ARQ;RECEIVING;SUCCESS"] [{"DXCALLSIGN":"GM8BPQ -{"DXCALLSIGN":"GM8BPQ","DXGRID":"","TIMESTAMP":1642847440,"RXDATA":[{"dt":"f","fn":"config.json", -"ft":"application\/json","d":"data:application\/json;base64, -ewogICAgInRuY19ob3N0IiA6ICIxMjcuMC4wLjEiLAogICAgInRuY19wb3J0IiA6ICIzMDAwIiwKICAgICJkYWVtb25faG9zdCIgOiAiMTI3LjAuMC4xIiwKICAgICJkYWVtb25fcG9ydCIgOiAiMzAwMSIsCiAgICAibXljYWxsIiA6ICJBQTBBQSIsCiAgICAibXlncmlkIiA6ICJBQTExZWEiICAgIAp9" -,"crc":"123123123"}]} -*/ -void ProcessFileObject(struct TNCINFO * TNC, char * This) -{ - char * Call; - char * LOC; - char * FN; - char * Type; - char * ptr, * ptr2; - int Len, NewLen; - - Call = strchr(This, ':'); - Call += 2; - This = strlop(Call, '"'); - - LOC = strchr(This, ':'); - LOC += 2; - This = strlop(LOC, '"'); - - FN = strstr(This, "fn"); - FN += 5; - This = strlop(FN, '"'); - - Type = strstr(This, "base64"); - Type += 7; - This = strlop(Type, '"'); - - // Decode Base64 - - Len = strlen(Type); - - Debugprintf("RX %d %s %d", TNC->Port, FN, Len); - - ptr = ptr2 = Type; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - NewLen = (int)(ptr2 - Type); - - if (*(ptr-1) == '=') - NewLen--; - - if (*(ptr-2) == '=') - NewLen--; - - Type[NewLen] = 0; - - Type --; - - Type[0] = 'B'; ; // Base64 Info - - FreeDataProcessTNCMessage(TNC, Call, Type, NewLen + 1); - - -} - -void ProcessMessageObject(struct TNCINFO * TNC, char * This) -{ - // This gets Message from a RX_MSG_BUFFER array element. - - char * Call; - char * LOC; - char * Type; - char * Msg; - int Len; - char * ptr, * ptr2; - - char * ID; - char * TYPE; - char * SEQ; - char * UUID; - char * TEXT; - char * NOIDEA; - char * FORMAT; - char * FILENAME; - int fileLen; - - int n; - - - Call = strstr(This, "dxcallsign"); - Call += 13; - This = strlop(Call, '"'); - - LOC = strchr(This, ':'); - LOC += 2; - This = strlop(LOC, '"'); - - Msg = strstr(This, "\"data\""); - Msg += 8; - This = strlop(Msg, '"'); - - // Decode Base64 - - // FreeData replaces / with \/ so need to undo - - ptr2 = strstr(Msg, "\\/"); - - while (ptr2) - { - memmove(ptr2, ptr2 + 1, strlen(ptr2)); - ptr2 = strstr(ptr2, "\\/"); - } - - Len = strlen(Msg); - - ptr = ptr2 = Msg; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - Len = (int)(ptr2 - Msg); - - if (*(ptr-1) == '=') - Len--; - - if (*(ptr-2) == '=') - Len--; - - Msg[Len] = 0; - -//m�;send_message�;123�;64730c5c-d32c-47b4-9b11-c958fd07a185�;hhhhhhhhhhhhhhhhhh -//�;�;plain/text�; - -//m;send_message;123;64730c5c-d32c-47b4-9b11-c958fd07a185;hhhhhhhhhhhhhhhhhh -//;;plain/text; - - // Message elements seem to be delimited by null ; - // Guessing labels - - ID = Msg; - - if (ID[0] == 'B') - { - // BPQ Message - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - - if (STREAM->Attached) - { - if (STREAM->Connected == 1 && STREAM->Connecting == 0) - { - char * Line = &ID[1]; - Len -= 1; - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Line, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, 256); - Len -= 256; - Line += 256; - STREAM->BytesRXed += 256; - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Line, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, Len); - STREAM->BytesRXed += Len; - - } - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - } - return; - } - - n = strlen(ID) + 2; - Msg += n; - Len -= n; - - if (ID[0] == 'm') - { - // ?? Chat ?? comes from a send raw ?? - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - TYPE = Msg; - n = strlen(TYPE) + 2; - Msg += n; - Len -= n; - - SEQ = Msg; - n = strlen(SEQ) + 2; - Msg += n; - Len -= n; - - UUID = Msg; - n = strlen(UUID) + 2; - Msg += n; - Len -= n; - - TEXT = Msg; - n = strlen(TEXT) + 2; - Msg += n; - Len -= n; - - NOIDEA = Msg; - n = strlen(NOIDEA) + 2; - Msg += n; - Len -= n; - - FORMAT = Msg; - n = strlen(FORMAT) + 2; - Msg += n; - Len -= n; - - // if Atached, send to user - - if (STREAM->Attached) - { - if (STREAM->Connected == 0 && STREAM->Connecting == 0) - { - // Just attached - send as Chat Message - - char Line[560]; - char * rest; - - // Send line by line - - rest = strlop(TEXT, 10); // FreeData chat uses LF - - while (TEXT && TEXT[0]) - { - Len = strlen(TEXT); - if (Len > 512) - TEXT[512] = 0; - - Len = sprintf(Line, "Chat From %-10s%s\r", Call, TEXT); - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Line, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, 256); - Len -= 256; - TEXT += 256; - STREAM->BytesRXed += 256; - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Line, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, Len); - STREAM->BytesRXed += Len; - - TEXT = rest; - rest = strlop(TEXT, 10); // FreeData chat ues LF - } - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - } - } - else - { - // Send Not Available Message -//m�;send_message�;123�;64730c5c-d32c-47b4-9b11-c958fd07a185�;hhhhhhhhhhhhhhhhhh -//�;�;plain/text�; - - char reply[512] = "m"; - char * p; - - strcat(TEXT, "\r"); - WritetoTrace(TNC, TEXT, strlen(TEXT)); - - strcpy(&reply[2], ";send_message"); - strcpy(&reply[16], ";123"); - reply[21] = ';'; - strcpy(&reply[22], gen_uuid()); - sprintf(&reply[59], ";Message received but user not on line\n"); - - p = strchr(&reply[59], 0); - - p[1] = ';'; - strcpy(&p[3], ";plain/text"); - p[15] = ';'; - - Len = &p[16] - reply; - - SendAsRaw(TNC, Call, TNC->FreeDataInfo->ourCall, reply, Len); - } - return; - - } - else if (ID[0] == 'f') - { - // File Tranfer - - char Filename[256]; - FILE * fp1; - char Text[64]; - int textLen; - - - FILENAME = Msg; - n = strlen(FILENAME) + 2; - Msg += n; - Len -= n; - - TYPE = Msg; - n = strlen(TYPE) + 2; - Msg += n; - Len -= n; - - SEQ = Msg; // ?? Maybe = 123123123 - n = strlen(SEQ) + 2; - Msg += n; - Len -= n; - - TEXT = Msg; // The file - fileLen = Len; - - if (TNC->FreeDataInfo->RXDir == NULL) - { - Debugprintf("FreeDATA RXDIRECTORY not set - file transfer ignored"); - return; - } - - sprintf(Filename, "%s\\%s", TNC->FreeDataInfo->RXDir, FILENAME); - - fp1 = fopen(Filename, "wb"); - - if (fp1) - { - fwrite(TEXT, 1, fileLen, fp1); - fclose(fp1); - textLen = sprintf(Text, "File %s received from %s \r", FILENAME, Call); - WritetoTrace(TNC, Text, textLen); - } - else - Debugprintf("FreeDATA - File %s create failed %s", Filename); - - return; - } - else if (ID[0] == 'm') - { - - } - - - - - - - - - - -// FreeDataProcessTNCMessage(TNC, Call, Msg, strlen(Msg)); -} - -void processJSONINFO(struct TNCINFO * TNC, char * Info, char * Call, double snr) -{ - char * LOC = ""; - char * ptr, * Context; - - // Info is an array. Normally only one element, but should check - - ptr = strtok_s(&Info[1], ",]", &Context); - - while (ptr && ptr[1]) - { - if (strstr(ptr, "BEACON;RECEIVING")) - { - char CQ[64]; - int Len; - - Len = sprintf(CQ, "Beacon received from %s SNR %3.1f\r", Call, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (Call) - UpdateMH(TNC, Call, '!', 'I'); - } - if (strstr(ptr, "PING;RECEIVING")) - { - // Add to MH - - if (Call) - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "CQ;RECEIVING")) - { - char CQ[64]; - int Len; - - Len = sprintf(CQ, "CQ received from %s SNR %3.1f\r", Call, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "PING;RECEIVEDACK")) - { - char Msg[128]; - int Len; - - Len = sprintf(Msg, "Ping Response from %s SNR %3.1f\r", Call, snr); - FreeDataProcessTNCMessage(TNC, Call, Msg, Len); - - // Add to MH - - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "TRANSMITTING;FAILED")) - { - // Failed to send a message - if it was a connect request tell appl - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - if (STREAM->Connecting) - { - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connect Failed\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - } - } - ptr = strtok_s(NULL, ",]", &Context); - } -} - - - - - - -char * getJSONValue(char * Msg, char * Key) -{ - char * ptr, *ptr2, *value = 0; - int vallen, keylen = strlen(Key); - char c; - - // We Null Terminate the value, so we must look for keys in reverse order - - ptr = strstr(Msg, Key); - - if (ptr) - { - ptr += (keylen + 1); - - if (*(ptr) == '[') - { - // Array - - int Open = 0; - int Close = 0; - - ptr2 = ptr; - - while (c = *(ptr++)) - { - if (c == '[') - Open ++; - else if (c == ']') - Close ++; - - if (Open == Close) - { - vallen = ptr - ptr2; - value = ptr2; - value[vallen] = 0; - return value; - } - } - } - else if (*(ptr) == '\"') - { - // String - - ptr2 = ptr; - ptr = strchr(ptr + 1, '\"'); - if (ptr) - { - ptr++; - vallen = ptr - ptr2; - value = ptr2; - value[vallen] = 0; - } - } - } - return value; -} - - -char stopTNC[] = "{\"type\" : \"SET\", \"command\": \"STOPTNC\" , \"parameter\": \"---\" }\r"; - - -void StopTNC(struct TNCINFO * TNC) -{ - if (TNC->TCPDataSock) - closesocket(TNC->TCPDataSock); -} - - -void ProcessTNCJSON(struct TNCINFO * TNC, char * Msg, int Len) -{ - char * ptr; - - if (memcmp(Msg, "{\"ptt\":", 7) == 0) - { - if (strstr(Msg, "True")) - { -// TNC->Busy = TNC->BusyHold * 10; // BusyHold delay - - if (TNC->PTTMode) - Rig_PTT(TNC, TRUE); - } - else - { - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); - } - return; - } - - if (memcmp(Msg, "{\"command_response\"", 19) == 0) - { - Debugprintf("%d %s", TNC->Port, Msg); - return; - } - - - if (memcmp(Msg, "{\"command\":\"tnc_state\"", 22) == 0) - { -/* -{"command":"tnc_state","ptt_state":"False","tnc_state":"IDLE","arq_state":"False","arq_session":"False", -"arq_session_state":"disconnected","audio_rms":"0","snr":"0","frequency":"None","speed_level":"1", -"mode":"None","bandwidth":"None","fft":"[0]","channel_busy":"False","scatter":[],"rx_buffer_length":"0", -"rx_msg_buffer_length":"0","arq_bytes_per_minute":"0","arq_bytes_per_minute_burst":"0","arq_compression_factor":"0", -"arq_transmission_percent":"0","total_bytes":"0","beacon_state":"False", -"stations":[],"mycallsign":"GM8BPQ-6","dxcallsign":"AA0AA","dxgrid":""} -*/ - char * LOC = 0; - char * Stations; - char * myCall = 0; - char * farCall = 0; - double snr; - int arqstate = 0; - int rx_buffer_length = 0; - int rx_msg_buffer_length = 0; - - Msg += 23; - - ptr = strstr(Msg, "tnc_state"); - - if (ptr) - { - if (ptr[12] == 'B' && TNC->Busy == FALSE) - { - TNC->Busy = TRUE; - strcpy(TNC->WEB_CHANSTATE, "Busy"); - SetWindowText(TNC->xIDC_CHANSTATE, TNC->WEB_CHANSTATE); - } - else if (ptr[12] == 'I' && TNC->Busy) - { - TNC->Busy = FALSE; - strcpy(TNC->WEB_CHANSTATE, "Idle"); - SetWindowText(TNC->xIDC_CHANSTATE, TNC->WEB_CHANSTATE); - } - } - - ptr = strstr(Msg, "rx_buffer_length"); - - if (ptr) - rx_buffer_length = atoi(&ptr[19]); - - ptr = strstr(Msg, "rx_msg_buffer_length"); - - if (ptr) - rx_msg_buffer_length = atoi(&ptr[23]); - - ptr = strstr(Msg, "snr"); - - if (ptr) - snr = atof(ptr + 6); - - Stations = getJSONValue(Msg, "\"stations\""); - - if (Stations) - { - ptr = Stations + strlen(Stations) + 1; - LOC = getJSONValue(ptr, "\"dxgrid\""); - farCall = getJSONValue(ptr, "\"dxcallsign\""); - myCall = getJSONValue(ptr, "\"mycallsign\""); - - if (myCall && farCall) - { - myCall++; - strlop(myCall, '"'); - farCall++; - strlop(farCall, '"'); - } - } - - // Look for changes in arq_session_state - - ptr = strstr(Msg, "\"arq_session_state\""); - - if (ptr) - { - struct STREAMINFO * STREAM = &TNC->Streams[0]; - ptr += 21; - - if (memcmp(ptr, "disconnected", 10) == 0) - { - if (TNC->FreeDataInfo->arqstate != 1) - { - TNC->FreeDataInfo->arqstate = 1; - Debugprintf("%d arq_session_state %s", TNC->Port, "disconnected"); - } - - // if connected this is a new disconnect - - if (STREAM->Connected) - { - // Create a traffic record - - char logmsg[120]; - time_t Duration; - - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - } - } - else if (memcmp(ptr, "connecting", 10) == 0) - { - if (TNC->FreeDataInfo->arqstate != 2) - { - TNC->FreeDataInfo->arqstate = 2; - Debugprintf("%d arq_session_state %s", TNC->Port, "connecting"); - } - } - else if (memcmp(ptr, "connected", 9) == 0) - { - // if connection is idle this is an incoming connect - - if (TNC->FreeDataInfo->arqstate != 3) - { - TNC->FreeDataInfo->arqstate = 3; - Debugprintf("%d arq_session_state %s", TNC->Port, "connected"); - } - - if (STREAM->Connecting == FALSE && STREAM->Connected == FALSE) - { - FreeDataProcessNewConnect(TNC, farCall, myCall); - } - - // if connecting it is a connect ack - - else if (STREAM->Connecting) - { - FreeDataProcessConnectAck(TNC, farCall, Msg, Len); - } - } - - else if (memcmp(ptr, "disconnecting", 12) == 0) - { - if (TNC->FreeDataInfo->arqstate != 4) - { - TNC->FreeDataInfo->arqstate = 4; - Debugprintf("%d arq_session_state %s", TNC->Port, "disconnecting"); - } - } - else if (memcmp(ptr, "failed", 5) == 0) - { - PMSGWITHLEN buffptr; - - if (TNC->FreeDataInfo->arqstate != 5) - { - TNC->FreeDataInfo->arqstate = 5; - Debugprintf("%d arq_session_state %s", TNC->Port, "failed"); - } - - if (STREAM->Connecting) - { - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connect Failed\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - } - } - } - - if (rx_buffer_length || rx_msg_buffer_length) - FreeGetData(TNC); - - ptr = getJSONValue(Msg, "\"info\""); - - if (ptr == NULL) - return; - - if (strcmp(ptr, "[]") != 0) - { - - processJSONINFO(TNC, ptr, farCall, snr); - Debugprintf("%d %s %s", TNC->Port, ptr, farCall); - } - - return; - } - - if (memcmp(Msg, "{\"freedata\":\"tnc-message\"", 25) == 0) - { - char * mycall = strstr(Msg, "mycall"); - char * dxcall = strstr(Msg, "dxcall"); - char * dxgrid = strstr(Msg, "dxgrid"); - char * snrptr = strstr(Msg, "snr"); - float snr = 0; - char CQ[64]; - int Len; - - Msg += 26; - - if (mycall && dxcall && dxgrid) - { - mycall += 13; - strlop(mycall, '"'); - - dxcall += 13; - strlop(dxcall, '"'); - - dxgrid += 9; - strlop(dxgrid, '"'); - } - - - if (dxcall && strstr(dxcall, "-0")) - strlop(dxcall, '-'); - - if (snrptr) - snr = atof(&snrptr[6]); - - if (memcmp(Msg, "\"beacon\":\"received\"", 18) == 0) - { - if (mycall && dxcall && dxgrid) - { - Len = sprintf(CQ, "Beacon received from %s SNR %3.1f", dxcall, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (dxcall) - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - if (memcmp(Msg, "\"cq\":\"received\"", 14) == 0) - { - if (mycall && dxcall && dxgrid) - { - Len = sprintf(CQ, "CQ received from %s", dxcall); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (dxcall) - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - if (memcmp(Msg, "\"ping\":\"received\"", 16) == 0) - { - if (mycall && dxcall && dxgrid) - { - Len = sprintf(CQ, "PING received from %s SNR %3.1f", dxcall, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (dxcall) - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - if (memcmp(Msg, "\"ping\":\"acknowledge\"", 16) == 0) - { - if (mycall && dxcall && dxgrid) - { - char Msg[128]; - - Len = sprintf(Msg, "Ping Response from %s SNR %3.1f\r", dxcall, snr); - FreeDataProcessTNCMessage(TNC, dxcall, Msg, Len); - - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - - - - - - Debugprintf("%d %s", TNC->Port, Msg); - return; - } - - if (memcmp(Msg, "{\"command\":\"rx_buffer\"", 22) == 0) - { - char * Next, * This; - - // Delete from TNC - - SendTNCCommand(TNC, "set", "del_rx_buffer"); Msg += 22; - - ptr = getJSONValue(Msg, "\"eof\""); - ptr = getJSONValue(Msg, "\"data-array\""); - - This = ptr; - - if (This[1] == '{') // Array of objects - { - This++; - do - { - Next = getObjectFromArray(This); - ProcessMessageObject(TNC, This); - This = Next; - - } while (Next && Next[0] == '{'); - } - - return; - } - - Debugprintf("%d %s", TNC->Port, Msg); - - -// {"COMMAND":"RX_BUFFER","DATA-ARRAY":[],"EOF":"EOF"} -/* {"COMMAND":"RX_BUFFER","DATA-ARRAY":[{"DXCALLSIGN":"GM8BPQ","DXGRID":"","TIMESTAMP":1642579504, -"RXDATA":[{"dt":"f","fn":"main.js","ft":"text\/javascript" -,"d":"data:text\/javascript;base64,Y29uc3Qge.....9KTsK","crc":"123123123"}]}],"EOF":"EOF"} - - - -{"arq":"received","uuid":"a1346319-6eb0-42aa-b5a0-c9493c8ccdca","timestamp":1645812393,"dxcallsign":"G8BPQ-2","dxgrid":"","data":"QyBHOEJQUS0yIEc4QlBRLTIgRzhCUFEtMiA="} -{"ptt":"True"} - - -*/ - if (memcmp(Msg, "{\"arq\":\"received\"", 17) == 0) - { - int NewLen; - char * ptr, *ptr2, *Type; - char * Call = 0; - char * myCall = 0; - - Msg += 17; - - ptr = getJSONValue(Msg, "\"data\""); - Type = ++ptr; - - // Decode Base64 - - // FreeData replaces / with \/ so need to undo - - ptr2 = strstr(Type, "\\/"); - - while (ptr2) - { - memmove(ptr2, ptr2 + 1, strlen(ptr2)); - ptr2 = strstr(ptr2, "\\/"); - } - - Len = strlen(Type) - 1; - - // Debugprintf("RX %d %s %d", TNC->Port, FN, Len); - - ptr = ptr2 = Type; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - NewLen = (int)(ptr2 - Type); - - if (*(ptr-1) == '=') - NewLen--; - - if (*(ptr-2) == '=') - NewLen--; - - Type[NewLen] = 0; - - myCall = getJSONValue(Msg, "\"mycallsign\""); - Call = getJSONValue(Msg, "\"dxcallsign\""); - - if (Call) - { - Call++; - strlop(Call, '"'); - } - - if (myCall) - { - myCall++; - strlop(myCall, '"'); - } - - - FreeDataProcessTNCMessage(TNC, Call, Type, NewLen); - - return; - } - - if (memcmp(Msg, "{\"COMMAND\":\"RX_MSG_BUFFER\"", 26) == 0) - { - char * Next, * This; - - Msg += 26; - ptr = getJSONValue(Msg, "\"EOF\""); - ptr = getJSONValue(Msg, "\"DATA-ARRAY\""); - - This = ptr; - - if (This[1] == '{') // Array of objects - { - This++; - do { - Next = getObjectFromArray(This); - ProcessMessageObject(TNC, This); - This = Next; - } while (Next && Next[0] == '{'); - - // Delete from TNC - - SendTNCCommand(TNC, "SET", "DEL_RX_MSG_BUFFER"); - } - - - return; - } -} - -int FreeDataConnect(struct TNCINFO * TNC, char * Call) -{ - char Connect[] = "{\"type\" : \"arq\", \"command\": \"connect\" , \"dxcallsign\": \"%s\"}\n"; - char Msg[128]; - int Len; - - Len = sprintf(Msg, Connect, Call); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - -int FreeDataDisconnect(struct TNCINFO * TNC) -{ - char Disconnect[] = "{\"type\" : \"arq\", \"command\": \"disconnect\"}\n"; - char Msg[128]; - int Len; - -// return FreeDataSendCommand(TNC, "D"); - - Len = sprintf(Msg, Disconnect); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - - -int FreeGetData(struct TNCINFO * TNC) -{ - char GetData[] = "{\"type\" : \"get\", \"command\": \"rx_buffer\"}\n"; - char Msg[128]; - int Len; - - Len = sprintf(Msg, GetData); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - -int FreeDataSendCommand(struct TNCINFO * TNC, char * Msg) -{ - // Commands are simulated as Messages to the remote BPQ. The TNC itself does not handle any commands - - // First Byte of MSG is a Type - Command or Data. MSG has a limited character set Use =xx for Now. - - // Current Types - C = Connect, D = Disconnect, I = info - - SendAsRaw(TNC, TNC->FreeDataInfo->farCall, TNC->FreeDataInfo->ourCall, Msg, strlen(Msg)); - return 0; -} - -void FreeDataProcessTNCMsg(struct TNCINFO * TNC) -{ - int DataInputLen, MsgLen; - char * ptr, * endptr; - int maxlen; - - // May get message split over packets or multiple messages per packet - - // A complete file transfer arrives as one message, so can bw very long - - - if (TNC->DataInputLen > MAXRXSIZE) // Shouldnt have packets longer than this - TNC->DataInputLen=0; - - maxlen = MAXRXSIZE - TNC->DataInputLen; - - if (maxlen >1400) - maxlen = 1400; - - DataInputLen = recv(TNC->TCPDataSock, &TNC->ARDOPDataBuffer[TNC->DataInputLen], maxlen, 0); - - if (DataInputLen == 0 || DataInputLen == SOCKET_ERROR) - { - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - closesocket(TNC->TCPDataSock); - - TNC->TCPDataSock = 0; - - TNC->TNCCONNECTED = FALSE; - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - return; - } - - TNC->DataInputLen += DataInputLen; - - TNC->ARDOPDataBuffer[TNC->DataInputLen] = 0; // So we can use string functions - - // Message should be json. We know the format, so don't need a general parser, but need to know if complete. - // I think counting { and } and stopping if equal should work; - -// Debugprintf(TNC->ARDOPDataBuffer); - - //I think now messages end with LF - -loop: - - endptr = strchr(TNC->ARDOPDataBuffer, 10); - - if (endptr == 0) - return; - - *(endptr) = 0; - - if (TNC->ARDOPDataBuffer[0] != '{') - { - TNC->DataInputLen = 0; - return; - } - - ptr = &TNC->ARDOPDataBuffer[0]; - - MsgLen = endptr - ptr; - - ProcessTNCJSON(TNC, ptr, MsgLen); - - // MsgLen doesnt include lf - - MsgLen++; - - if (TNC->DataInputLen == MsgLen) - { - TNC->DataInputLen = 0; - return; - } - - // More in buffer - - ptr += MsgLen; - TNC->DataInputLen -= MsgLen; - - memmove(TNC->ARDOPDataBuffer, ptr, TNC->DataInputLen + 1); - - goto loop; - - // Message Incomplete - wait for rest; -} - - - -VOID FreeDataThread(void * portptr); - -int ConnecttoFreeData(int port) -{ - _beginthread(FreeDataThread, 0, (void *)(size_t)port); - - return 0; -} - -static SOCKADDR_IN sinx; -static SOCKADDR_IN rxaddr; - - -VOID FreeDataThread(void * portptr) -{ - // Messages are JSON encapulated - // Now We run tnc directly so don't open daemon socket - // Looks for data on socket(s) - - int port = (int)(size_t)portptr; - char Msg[255]; - int err, i, ret; - u_long param=1; - BOOL bcopt=TRUE; - struct hostent * HostEnt; - struct TNCINFO * TNC = TNCInfo[port]; - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - char Params[512]; - - if (TNC->HostName == NULL) - return; - - buildParamString(TNC, Params); - - TNC->BusyFlags = 0; - - TNC->TNCCONNECTING = TRUE; - - Sleep(3000); // Allow init to complete - -// printf("Starting FreeDATA Thread\n"); - -// if on Windows and Localhost see if TNC is running - -#ifdef WIN32 - - if (strcmp(TNC->HostName, "127.0.0.1") == 0) - { - // can only check if running on local host - - TNC->PID = GetListeningPortsPID(TNC->Datadestaddr.sin_port); - - if (TNC->PID == 0) - goto TNCNotRunning; - - // Get the File Name in case we want to restart it. - - if (TNC->ProgramPath == NULL) - { - if (GetModuleFileNameExPtr) - { - HANDLE hProc; - char ExeName[256] = ""; - - hProc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, TNC->PID); - - if (hProc) - { - GetModuleFileNameExPtr(hProc, 0, ExeName, 255); - CloseHandle(hProc); - - TNC->ProgramPath = _strdup(ExeName); - } - } - } - goto TNCRunning; - } - -#endif - -TNCNotRunning: - - // Not running or can't check, restart if we have a path - - if (TNC->ProgramPath) - { - Consoleprintf("Trying to (re)start TNC %s", TNC->ProgramPath); - - if (RestartTNC(TNC)) - CountRestarts(TNC); - - Sleep(TNC->AutoStartDelay); - } - -TNCRunning: - - if (TNC->Alerted == FALSE) - { - sprintf(TNC->WEB_COMMSSTATE, "Connecting to TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - - TNC->Datadestaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - - if (TNC->Datadestaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - { - TNC->TNCCONNECTING = FALSE; - sprintf(Msg, "Resolve Failed for FreeData Host - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - return; // Resolve failed - } - memcpy(&TNC->Datadestaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - - TNC->TCPDataSock=socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for FreeData TNC socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->TNCCONNECTING = FALSE; - return; - } - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - // Connect TNC Port - - if (connect(TNC->TCPDataSock,(LPSOCKADDR) &TNC->Datadestaddr,sizeof(TNC->Datadestaddr)) == 0) - { - // - // Connected successful - // - } - else - { - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - i=sprintf(Msg, "Connect Failed for FreeData TNC socket - error code = %d\r\n", err); - WritetoConsole(Msg); - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->Alerted = TRUE; - } - - closesocket(TNC->TCPDataSock); - TNC->TCPDataSock = 0; - TNC->TNCCONNECTING = FALSE; - - return; - } - - Sleep(1000); - - TNC->LastFreq = 0; - - TNC->TNCCONNECTING = FALSE; - TNC->TNCCONNECTED = TRUE; - TNC->BusyFlags = 0; - TNC->InputLen = 0; - TNC->Alerted = FALSE; - - TNC->Alerted = TRUE; - - sprintf(TNC->WEB_COMMSSTATE, "Connected to FreeData TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - sprintf(Msg, "Connected to FreeData TNC Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - - #ifndef LINBPQ -// FreeSemaphore(&Semaphore); - Sleep(1000); // Give VARA time to update Window title -// EnumWindows(EnumVARAWindowsProc, (LPARAM)TNC); -// GetSemaphore(&Semaphore, 52); -#endif - - while (TNC->TNCCONNECTED) - { - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - if (TNC->TNCCONNECTED) - FD_SET(TNC->TCPDataSock,&readfs); - - if (TNC->TNCCONNECTING || TNC->TNCCONNECTED) FD_SET(TNC->TCPDataSock,&errorfs); - - timeout.tv_sec = 300; - timeout.tv_usec = 0; - - ret = select((int)TNC->TCPDataSock + 1, &readfs, NULL, &errorfs, &timeout); - - if (ret == SOCKET_ERROR) - { - Debugprintf("FreeData Select failed %d ", WSAGetLastError()); - goto Lost; - } - - // If nothing doing send get rx_buffer as link validation poll - - if (ret == 0) - { - char GetData[] = "{\"type\" : \"get\", \"command\": \"rx_buffer\"}\n"; - int Len; - - Len = send(TNC->TCPDataSock, GetData, strlen(GetData), 0); - - if (Len != strlen(GetData)) - goto closeThread; - } - else - { - // See what happened - - if (FD_ISSET(TNC->TCPDataSock, &readfs)) - { - GetSemaphore(&Semaphore, 52); - FreeDataProcessTNCMsg(TNC); - FreeSemaphore(&Semaphore); - } - - if (FD_ISSET(TNC->TCPDataSock, &errorfs)) - { -Lost: - sprintf(Msg, "FreeData TNC Connection lost for Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->TNCCONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - closesocket(TNC->TCPDataSock); - TNC->TCPDataSock = 0; - } - - continue; - } - } - -closeThread: - - if (TNC->TCPDataSock) - { - shutdown(TNC->TCPDataSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPDataSock); - } - - sprintf(Msg, "FreeData Thread Terminated Port %d\r\n", TNC->Port); - WritetoConsole(Msg); -} - -void ConnectTNCPort(struct TNCINFO * TNC) -{ - char Msg[255]; - int err; - int bcopt = TRUE; - - TNC->TNCCONNECTING = TRUE; - - TNC->TCPDataSock = socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - sprintf(Msg, "Socket Failed for FreeData TNC socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->TNCCONNECTING = FALSE; - return; - } - - setsockopt(TNC->TCPDataSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(TNC->TCPDataSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - if (connect(TNC->TCPDataSock,(LPSOCKADDR) &TNC->Datadestaddr,sizeof(TNC->Datadestaddr)) == 0) - { - // Connected successful - - sprintf(TNC->WEB_COMMSSTATE, "Connected to FreeData TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->TNCCONNECTING = FALSE; - TNC->TNCCONNECTED = TRUE; - TNC->Alerted = FALSE; - return; - } - - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - sprintf(Msg, "Connect Failed for FreeData TNC socket - error code = %d Port %d\n", - err, htons(TNC->Datadestaddr.sin_port)); - - WritetoConsole(Msg); - TNC->Alerted = TRUE; - TNC->TNCCONNECTING = FALSE; - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - - closesocket(TNC->TCPDataSock); - - TNC->TCPDataSock = 0; - TNC->TNCCONNECTING = FALSE; - return; -} - -void buildParamString(struct TNCINFO * TNC, char * line) -{ - // choices=[, "direct", "rigctl", "rigctld"], - - struct FreeDataINFO * FDI = TNC->FreeDataInfo; - int capindex = -1, playindex = -1; - int i; - - // Python adds sound mapper on front and counts Playback after Capture - - for (i = 0; i < CaptureCount; i++) - { - if (strstr(&CaptureNames[i][0], TNC->FreeDataInfo->Capture)) - { - capindex = i + 1; - break; - } - } - - for (i = 0; i < PlaybackCount; i++) - { - if (strstr(&PlaybackNames[i][0], TNC->FreeDataInfo->Playback)) - { - playindex = i + CaptureCount + 2; - break; - } - } - - sprintf(line, - "--mycall %s --ssid %s --mygrid %s --rx %d --tx %d --port %d --radiocontrol %s " - "--tuning_range_fmin %3.1f --tuning_range_fmax %3.1f --tx-audio-level %d", - - FDI->ourCall, FDI->SSIDList, LOC, capindex, playindex, TNC->TCPPort, FDI->hamlibHost ? "rigctld" : "disabled", - FDI->TuningRange * -1.0, FDI->TuningRange * 1.0, FDI->TXLevel); - - if (FDI->hamlibHost) - sprintf(line, "%s --rigctld_ip %s --rigctld_port %d", line, FDI->hamlibHost, FDI->hamlibPort); - - if (FDI->LimitBandWidth) - strcat(line, " --500hz"); - - if (FDI->Explorer) - strcat(line, " --explorer"); - - - // Add these to the end if needed - // --scatter - // --fft - // --fsk - // --qrv (respond to cq) - -} - -#ifndef WIN32 - -#include - -char ** WriteDevices = NULL; -int WriteDeviceCount = 0; - -char ** ReadDevices = NULL; -int ReadDeviceCount = 0; - - -int GetOutputDeviceCollection() -{ - // Get all the suitable devices and put in a list for GetNext to return - - snd_ctl_t *handle= NULL; - snd_pcm_t *pcm= NULL; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - snd_pcm_hw_params_t *pars; - snd_pcm_format_mask_t *fmask; - char NameString[256]; - - Debugprintf("Playback Devices\n"); - - // free old struct if called again - -// while (WriteDeviceCount) -// { -// WriteDeviceCount--; -// free(WriteDevices[WriteDeviceCount]); -// } - -// if (WriteDevices) -// free(WriteDevices); - - WriteDevices = NULL; - WriteDeviceCount = 0; - - // Add virtual device ARDOP so ALSA plugins can be used if needed - - WriteDevices = realloc(WriteDevices,(WriteDeviceCount + 1) * sizeof(WriteDevices)); - - // Get Device List from ALSA - - snd_ctl_card_info_alloca(&info); - snd_pcm_info_alloca(&pcminfo); - snd_pcm_hw_params_alloca(&pars); - snd_pcm_format_mask_alloca(&fmask); - - char hwdev[80]; - unsigned min, max, ratemin, ratemax; - int card, err, dev, nsubd; - snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; - - card = -1; - - if (snd_card_next(&card) < 0) - { - Debugprintf("No Devices"); - return 0; - } - - while (card >= 0) - { - sprintf(hwdev, "hw:%d", card); - err = snd_ctl_open(&handle, hwdev, 0); - err = snd_ctl_card_info(handle, info); - - Debugprintf("Card %d, ID `%s', name `%s'", card, snd_ctl_card_info_get_id(info), - snd_ctl_card_info_get_name(info)); - - - dev = -1; - - if(snd_ctl_pcm_next_device(handle, &dev) < 0) - { - // Card has no devices - - snd_ctl_close(handle); - - WriteDevices = realloc(WriteDevices,(WriteDeviceCount + 1) * sizeof(WriteDevices)); - WriteDevices[WriteDeviceCount++] = strupr(strdup("DummyDevice")); - - goto nextcard; - } - - while (dev >= 0) - { - snd_pcm_info_set_device(pcminfo, dev); - snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, stream); - - err = snd_ctl_pcm_info(handle, pcminfo); - - - if (err == -ENOENT) - goto nextdevice; - - nsubd = snd_pcm_info_get_subdevices_count(pcminfo); - - Debugprintf(" Device hw:%d,%d ID `%s', name `%s', %d subdevices (%d available)", - card, dev, snd_pcm_info_get_id(pcminfo), snd_pcm_info_get_name(pcminfo), - nsubd, snd_pcm_info_get_subdevices_avail(pcminfo)); - - sprintf(hwdev, "hw:%d,%d", card, dev); - - err = snd_pcm_open(&pcm, hwdev, stream, SND_PCM_NONBLOCK); - - if (err) - { - Debugprintf("Error %d opening output device", err); - goto nextdevice; - } - - // Get parameters for this device - - err = snd_pcm_hw_params_any(pcm, pars); - - snd_pcm_hw_params_get_channels_min(pars, &min); - snd_pcm_hw_params_get_channels_max(pars, &max); - - snd_pcm_hw_params_get_rate_min(pars, &ratemin, NULL); - snd_pcm_hw_params_get_rate_max(pars, &ratemax, NULL); - - if( min == max ) - if( min == 1 ) - Debugprintf(" 1 channel, sampling rate %u..%u Hz", ratemin, ratemax); - else - Debugprintf(" %d channels, sampling rate %u..%u Hz", min, ratemin, ratemax); - else - Debugprintf(" %u..%u channels, sampling rate %u..%u Hz", min, max, ratemin, ratemax); - - // Add device to list - - sprintf(NameString, "hw:%d,%d %s(%s)", card, dev, - snd_pcm_info_get_name(pcminfo), snd_ctl_card_info_get_name(info)); - - WriteDevices = realloc(WriteDevices,(WriteDeviceCount + 1) * sizeof(WriteDevices)); - WriteDevices[WriteDeviceCount++] = strupr(strdup(NameString)); - - snd_pcm_close(pcm); - pcm= NULL; - -nextdevice: - if (snd_ctl_pcm_next_device(handle, &dev) < 0) - break; - } - snd_ctl_close(handle); - -nextcard: - - Debugprintf(""); - - if (snd_card_next(&card) < 0) // No more cards - break; - } - - return WriteDeviceCount; -} - -int GetNextOutputDevice(char * dest, int max, int n) -{ - if (n >= WriteDeviceCount) - return 0; - - strcpy(dest, WriteDevices[n]); - return strlen(dest); -} - - -int GetInputDeviceCollection() -{ - // Get all the suitable devices and put in a list for GetNext to return - - snd_ctl_t *handle= NULL; - snd_pcm_t *pcm= NULL; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - snd_pcm_hw_params_t *pars; - snd_pcm_format_mask_t *fmask; - char NameString[256]; - - Debugprintf("Capture Devices\n"); - - ReadDevices = NULL; - ReadDeviceCount = 0; - - ReadDevices = realloc(ReadDevices,(ReadDeviceCount + 1) * sizeof(ReadDevices)); - - // Get Device List from ALSA - - snd_ctl_card_info_alloca(&info); - snd_pcm_info_alloca(&pcminfo); - snd_pcm_hw_params_alloca(&pars); - snd_pcm_format_mask_alloca(&fmask); - - char hwdev[80]; - unsigned min, max, ratemin, ratemax; - int card, err, dev, nsubd; - snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE; - - card = -1; - - if(snd_card_next(&card) < 0) - { - Debugprintf("No Devices"); - return 0; - } - - while(card >= 0) - { - sprintf(hwdev, "hw:%d", card); - err = snd_ctl_open(&handle, hwdev, 0); - err = snd_ctl_card_info(handle, info); - -// Debugprintf("Card %d, ID `%s', name `%s'", card, snd_ctl_card_info_get_id(info), -// snd_ctl_card_info_get_name(info)); - - dev = -1; - - if (snd_ctl_pcm_next_device(handle, &dev) < 0) // No Devicdes - { - snd_ctl_close(handle); - - ReadDevices = realloc(ReadDevices,(ReadDeviceCount + 1) * sizeof(ReadDevices)); - ReadDevices[ReadDeviceCount++] = strupr(strdup("DummyDevice")); - - Debugprintf("%d %s", ReadDeviceCount, "DummyDevice"); - goto nextcard; - } - - while(dev >= 0) - { - snd_pcm_info_set_device(pcminfo, dev); - snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, stream); - err= snd_ctl_pcm_info(handle, pcminfo); - - if (err == -ENOENT) - goto nextdevice; - - nsubd= snd_pcm_info_get_subdevices_count(pcminfo); -// Debugprintf(" Device hw:%d,%d ID `%s', name `%s', %d subdevices (%d available)", -// card, dev, snd_pcm_info_get_id(pcminfo), snd_pcm_info_get_name(pcminfo), -// nsubd, snd_pcm_info_get_subdevices_avail(pcminfo)); - - sprintf(hwdev, "hw:%d,%d", card, dev); -/* - err = snd_pcm_open(&pcm, hwdev, stream, SND_PCM_NONBLOCK); - - if (err) - { - Debugprintf("Error %d opening input device", err); - goto nextdevice; - } - - err = snd_pcm_hw_params_any(pcm, pars); - - snd_pcm_hw_params_get_channels_min(pars, &min); - snd_pcm_hw_params_get_channels_max(pars, &max); - snd_pcm_hw_params_get_rate_min(pars, &ratemin, NULL); - snd_pcm_hw_params_get_rate_max(pars, &ratemax, NULL); - - if( min == max ) - if( min == 1 ) - Debugprintf(" 1 channel, sampling rate %u..%u Hz", ratemin, ratemax); - else - Debugprintf(" %d channels, sampling rate %u..%u Hz", min, ratemin, ratemax); - else - Debugprintf(" %u..%u channels, sampling rate %u..%u Hz", min, max, ratemin, ratemax); -*/ - sprintf(NameString, "hw:%d,%d %s(%s)", card, dev, - snd_pcm_info_get_name(pcminfo), snd_ctl_card_info_get_name(info)); - - Debugprintf("%d %s", ReadDeviceCount, NameString); - - ReadDevices = realloc(ReadDevices,(ReadDeviceCount + 1) * sizeof(ReadDevices)); - ReadDevices[ReadDeviceCount++] = strupr(strdup(NameString)); - -nextdevice: - if (snd_ctl_pcm_next_device(handle, &dev) < 0) - break; - } - snd_ctl_close(handle); -nextcard: - - Debugprintf(""); - if (snd_card_next(&card) < 0 ) - break; - } - return ReadDeviceCount; -} - -int GetNextInputDevice(char * dest, int max, int n) -{ - if (n >= ReadDeviceCount) - return 0; - - strcpy(dest, ReadDevices[n]); - return strlen(dest); -} - -#endif - - -// We need a local restart tnc as we need to add params and start a python progrm on Linux - -BOOL KillOldTNC(char * Path); - -static BOOL RestartTNC(struct TNCINFO * TNC) -{ - if (TNC->ProgramPath == NULL || TNC->DontRestart) - return 0; - - if (_memicmp(TNC->ProgramPath, "REMOTE:", 7) == 0) - { - int n; - - // Try to start TNC on a remote host - - SOCKET sock = socket(AF_INET,SOCK_DGRAM,0); - struct sockaddr_in destaddr; - - Debugprintf("trying to restart TNC %s", TNC->ProgramPath); - - if (sock == INVALID_SOCKET) - return 0; - - destaddr.sin_family = AF_INET; - destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - destaddr.sin_port = htons(8500); - - if (destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - struct hostent * HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - return 0; // Resolve failed - - memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - - n = sendto(sock, TNC->ProgramPath, (int)strlen(TNC->ProgramPath), 0, (struct sockaddr *)&destaddr, sizeof(destaddr)); - - Debugprintf("Restart TNC - sendto returned %d", n); - - Sleep(100); - closesocket(sock); - - return 1; // Cant tell if it worked, but assume ok - } - - // Not Remote - - // Add parameters to command string - -#ifndef WIN32 - { - char * arg_list[64]; - char rxVal[16]; - char txVal[16]; - char tunePlus[16]; - char tuneMinus[16]; - char portVal[16]; - char txLevelVal[16]; - char RigPort[16]; - int n = 0; - - pid_t child_pid; - - struct FreeDataINFO * FDI = TNC->FreeDataInfo; - int capindex = -1, playindex = -1; - int i; - - if (ReadDeviceCount == 0) - { - GetOutputDeviceCollection(); - GetInputDeviceCollection(); - } - - // - - for (i = 0; i < ReadDeviceCount; i++) - { - printf("%s %s\n", &ReadDevices[i][0], TNC->FreeDataInfo->Capture); - if (strstr(&ReadDevices[i][0], TNC->FreeDataInfo->Capture)) - { - capindex = i; - break; - } - } - - - for (i = 0; i < WriteDeviceCount; i++) - { - printf("%s %s\n", &WriteDevices[i][0], TNC->FreeDataInfo->Playback); - - if (strstr(&WriteDevices[i][0], TNC->FreeDataInfo->Playback)) - { - playindex = i; - break; - } - } - - - capindex=playindex=3; - - printf("%d %d \n", capindex, playindex); - - signal(SIGCHLD, SIG_IGN); // Silently (and portably) reap children. - - arg_list[n++] = "python3"; - arg_list[n++] = TNC->ProgramPath; - arg_list[n++] = "--mycall"; - arg_list[n++] = FDI->ourCall; - arg_list[n++] = "--ssid"; - arg_list[n++] = FDI->SSIDList; - arg_list[n++] = "--mygrid"; - arg_list[n++] = LOC; - arg_list[n++] = "--rx"; - sprintf(rxVal, "%d", capindex); - arg_list[n++] = rxVal; - arg_list[n++] = "--tx"; - sprintf(txVal, "%d", playindex); - arg_list[n++] = txVal; - arg_list[n++] = "--port"; - sprintf(portVal, "%d", TNC->TCPPort); - arg_list[n++] = portVal; - arg_list[n++] = "--radiocontrol"; - arg_list[n++] = FDI->hamlibHost ? "rigctld" : "disabled"; - arg_list[n++] = "--tuning_range_fmin"; - sprintf(tuneMinus, "%3.1f", FDI->TuningRange * -1.0); - arg_list[n++] = tuneMinus; - arg_list[n++] = "--tuning_range_fmax"; - sprintf(tunePlus, "%3.1f", FDI->TuningRange * 1.0); - arg_list[n++] = tunePlus; - arg_list[n++] = "--tx-audio-level"; - sprintf(txLevelVal, "%d", FDI->TXLevel); - arg_list[n++] = txLevelVal; - - if (FDI->hamlibHost) - { - arg_list[n++] = "--rigctld_ip"; - arg_list[n++] = FDI->hamlibHost; - arg_list[n++] = "--rigctld_port"; - sprintf(RigPort, "%d", FDI->hamlibPort); - arg_list[n++] = RigPort; - } - - if (FDI->LimitBandWidth) - arg_list[n++] = "--500hz"; - - if (FDI->Explorer) - arg_list[n++] = "--explorer"; - - arg_list[n++] = 0; - - n = 0; - - // Fork and Exec TNC - - printf("Trying to start %s\n", TNC->ProgramPath); - - /* Duplicate this process. */ - - child_pid = fork (); - - if (child_pid == -1) - { - printf ("StartTNC fork() Failed\n"); - return 0; - } - - if (child_pid == 0) - { - execvp (arg_list[0], arg_list); - - /* The execvp function returns only if an error occurs. */ - - printf ("Failed to start TNC\n"); - exit(0); // Kill the new process - } - printf("Started TNC\n"); - sleep(5000); - - return TRUE; - } -#else - - { - int n = 0; - - STARTUPINFO SInfo; // pointer to STARTUPINFO - PROCESS_INFORMATION PInfo; // pointer to PROCESS_INFORMATION - char workingDirectory[256]; - char commandLine[512]; - char Params[512]; - - int i = strlen(TNC->ProgramPath); - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - Debugprintf("RestartTNC Called for %s", TNC->ProgramPath); - - - strcpy(workingDirectory, TNC->ProgramPath); - - while (i--) - { - if (workingDirectory[i] == '\\' || workingDirectory[i] == '/') - { - workingDirectory[i] = 0; - break; - } - } - - buildParamString(TNC, Params); - - while (KillOldTNC(TNC->ProgramPath) && n++ < 100) - { - Sleep(100); - } - - sprintf(commandLine, "\"%s\" %s", TNC->ProgramPath, Params); - - if (CreateProcess(NULL, commandLine, NULL, NULL, FALSE,0, NULL, workingDirectory, &SInfo, &PInfo)) - { - Debugprintf("Restart TNC OK"); - TNC->PID = PInfo.dwProcessId; - return TRUE; - } - else - { - Debugprintf("Restart TNC Failed %d ", GetLastError()); - return FALSE; - } - } -#endif - return 0; -} diff --git a/FreeDATA-HPLaptop.c b/FreeDATA-HPLaptop.c deleted file mode 100644 index 526f3bc..0000000 --- a/FreeDATA-HPLaptop.c +++ /dev/null @@ -1,3490 +0,0 @@ -/* -Copyright 2001-2018 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// Interface to allow G8BPQ switch to use FreeData TNC - - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include - -#ifndef WIN32 -#ifndef MACBPQ -#include -#endif -#endif - -#include "CHeaders.h" -#include "bpq32.h" -#include "tncinfo.h" - -#define SD_BOTH 0x02 - -int KillTNC(struct TNCINFO * TNC); -int RestartTNC(struct TNCINFO * TNC); - -int (WINAPI FAR *GetModuleFileNameExPtr)(); -int (WINAPI FAR *EnumProcessesPtr)(); -static int Socket_Data(int sock, int error, int eventcode); -VOID MoveWindows(struct TNCINFO * TNC); -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen); -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); -VOID SendInitScript(struct TNCINFO * TNC); -int ProcessEscape(UCHAR * TXMsg); -static void SendPoll(struct TNCINFO * TNC); -void SendMode(struct TNCINFO * TNC); -static int ConnecttoFreeData(int port); -void ConnectTNCPort(struct TNCINFO * TNC); -int FreeDataSendCommand(struct TNCINFO * TNC, char * data); -static void SendPing(struct TNCINFO * TNC, char * Call); -static void SendCQ(struct TNCINFO * TNC); -char * stristr (char *ch1, char *ch2); -int zEncode(unsigned char * in, unsigned char * out, int len, unsigned char * Banned); -static void SendDataMsg(struct TNCINFO * TNC, char * Call, char * Msg, int Len); -static int SendAsRaw(struct TNCINFO * TNC, char * Call, char * myCall, char * Msg, int Len); -static int SendAsFile(struct TNCINFO * TNC, char * Call, char * Msg, int Len); -char * byte_base64_encode(char *str, int len); -void xdecodeblock( unsigned char in[4], unsigned char out[3] ); -void FlushData(struct TNCINFO * TNC); -void CountRestarts(struct TNCINFO * TNC); -void StopTNC(struct TNCINFO * TNC); - -static char ClassName[]="FREEDATASTATUS"; -static char WindowTitle[] = "FreeData Modem"; -static int RigControlRow = 205; - -#ifdef LINBPQ -#include -#else -#include -#endif - -extern char * PortConfig[33]; -extern int SemHeldByAPI; - -static RECT Rect; - -struct TNCINFO * TNCInfo[41]; // Records are Malloc'd - -static int ProcessLine(char * buf, int Port); - -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - -#define MAXRXSIZE 512000 // Sets max size for file transfer (less base64 overhead - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC = TNCInfo[Port]; - char errbuf[256]; - - strcpy(errbuf, buf); - - ptr = strtok(buf, " \t\n\r"); - - if (ptr == NULL) return (TRUE); - - if (*ptr =='#') return (TRUE); // comment - - if (*ptr ==';') return (TRUE); // comment - - - if (_stricmp(buf, "ADDR")) - return FALSE; // Must start with ADDR - - ptr = strtok(NULL, " \t\n\r"); - - BPQport = Port; - p_ipad = ptr; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->FreeDataInfo = zalloc(sizeof(struct FreeDataINFO)); - -// TNC->FreeDataInfo->useBaseCall = 1; // Default - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - if (p_ipad == NULL) - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - WINMORport = atoi(p_port); - - TNC->TCPPort = WINMORport; - - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(WINMORport); - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(WINMORport+1); - - TNC->HostName = malloc(strlen(p_ipad)+1); - - if (TNC->HostName == NULL) return TRUE; - - strcpy(TNC->HostName,p_ipad); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - } - - if (ptr) - { - if (_memicmp(ptr, "PATH", 4) == 0) - { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - } - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "CAPTURE", 7) == 0) - { - TNC->FreeDataInfo->Capture = _strdup(&buf[8]); - strlop(TNC->FreeDataInfo->Capture, 13); - } - else if (_memicmp(buf, "PLAYBACK", 8) == 0) - { - TNC->FreeDataInfo->Playback = _strdup(&buf[9]); - strlop(TNC->FreeDataInfo->Playback, 13); - } - - else if (_memicmp(buf, "LOGDIR ", 7) == 0) - TNC->LogPath = _strdup(&buf[7]); - - else if (_memicmp(buf, "HAMLIBHOST", 10) == 0) - { - TNC->FreeDataInfo->hamlibHost = _strdup(&buf[11]); - strlop(TNC->FreeDataInfo->hamlibHost, 13); - } - - else if (_memicmp(buf, "HAMLIBPORT", 10) == 0) - TNC->FreeDataInfo->hamlibPort = atoi(&buf[11]); - - else if (_memicmp(buf, "USEBASECALL", 11) == 0) - TNC->FreeDataInfo->useBaseCall = atoi(&buf[12]); - - else if (_memicmp(buf, "RXDIRECTORY", 11) == 0) - { - TNC->FreeDataInfo->RXDir = _strdup(&buf[12]); - strlop(TNC->FreeDataInfo->RXDir, 13); - } - - else if (standardParams(TNC, buf) == FALSE) - strcat(TNC->InitScript, buf); - - } - - return (TRUE); -} - -char * Config; -static char * ptr1, * ptr2; - -int FreeDataGetLine(char * buf) -{ -loop: - - if (ptr2 == NULL) - return 0; - - memcpy(buf, ptr1, ptr2 - ptr1 + 2); - buf[ptr2 - ptr1 + 2] = 0; - ptr1 = ptr2 + 2; - ptr2 = strchr(ptr1, 13); - - if (buf[0] < 0x20) goto loop; - if (buf[0] == '#') goto loop; - if (buf[0] == ';') goto loop; - - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - buf[strlen(buf)] = 13; - - return 1; -} - -BOOL FreeDataReadConfigFile(int Port, int ProcLine()) -{ - char buf[256],errbuf[256]; - - Config = PortConfig[Port]; - - if (Config) - { - // Using config from bpq32.cfg - - if (strlen(Config) == 0) - { - return TRUE; - } - - ptr1 = Config; - ptr2 = strchr(ptr1, 13); - - if (!ProcLine(buf, Port)) - { - WritetoConsoleLocal("\n"); - WritetoConsoleLocal("Bad config record "); - WritetoConsoleLocal(errbuf); - } - } - else - { - sprintf(buf," ** Error - No Configuration info in bpq32.cfg"); - WritetoConsoleLocal(buf); - } - - return (TRUE); -} - - - -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - - - -#define MAXBPQPORTS 32 - -static time_t ltime; - - - -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen) -{ - if (TNC->hDevice) - { - // FreeData mode. Queue to Hostmode driver - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = EncLen; - memcpy(&buffptr->Data[0], Encoded, EncLen); - - C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); - TNC->Streams[Stream].FramesQueued++; - - return; - } -} - - -VOID FreeDataChangeMYC(struct TNCINFO * TNC, char * Call) -{ - UCHAR TXMsg[100]; - int datalen; - - if (strcmp(Call, TNC->CurrentMYC) == 0) - return; // No Change - - strcpy(TNC->CurrentMYC, Call); - - datalen = sprintf(TXMsg, "MYCALL %s\r", Call); -// FreeDataSendCommand(TNC, TXMsg); -} - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int datalen; - PMSGWITHLEN buffptr; -// char txbuff[500]; - unsigned int txlen = 0; - UCHAR * TXMsg; - - size_t Param; - int Stream = 0; - HKEY hKey=0; - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct ScanEntry * Scan; - - if (TNC == NULL) - return 0; // Port not defined - - switch (fn) - { - case 7: - - // 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances - - SendPoll(TNC); - - // Check for buffered data to send - - if (TNC->FreeDataInfo->toSendTimeout) - { - TNC->FreeDataInfo->toSendTimeout--; - if (TNC->FreeDataInfo->toSendTimeout <= 0) - FlushData(TNC); - } - - return 0; - - case 1: // poll - -// FreeDataCheckRX(TNC); - - if (TNC->DAEMONCONNECTED == FALSE && TNC->DAEMONCONNECTING == FALSE) - { - // See if time to reconnect - - time(<ime); - if (ltime - TNC->lasttime > 9 ) - { - TNC->lasttime = ltime; - ConnecttoFreeData(port); - } - } - - - while (TNC->PortRecord->UI_Q) - { - int datalen; - char * Buffer; - char FECMsg[512]; - char Call[12] = " "; - struct _MESSAGE * buffptr; - int CallLen; - char * ptr = FECMsg; - - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - -/* if (TNC->CONNECTED == 0 || - TNC->Streams[0].Connecting || - TNC->Streams[0].Connected) - { - // discard if TNC not connected or sesison active - - ReleaseBuffer(buffptr); - continue; - } -*/ - datalen = buffptr->LENGTH - MSGHDDRLEN; - Buffer = &buffptr->DEST[0]; // Raw Frame - Buffer[datalen] = 0; - - // Frame has ax.25 format header. Convert to Text - - CallLen = ConvFromAX25(Buffer + 7, Call); // Origin - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - *ptr++ = '!'; - - CallLen = ConvFromAX25(Buffer, Call); // Dest - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - Buffer += 14; // TO Digis - datalen -= 14; - - while ((Buffer[-1] & 1) == 0) - { - *ptr++ = ','; - CallLen = ConvFromAX25(Buffer, Call); - memcpy(ptr, Call, CallLen); - ptr += CallLen; - Buffer += 7; // End of addr - datalen -= 7; - } - - *ptr++ = '_'; - *ptr++ = 'U'; // UI Frame - *ptr++ = 0; // delimit calls - - if (Buffer[0] == 3) // UI - { - Buffer += 2; - datalen -= 2; - } - -// FreeDataSendSingleData(TNC, FECMsg, Buffer, datalen); - - ReleaseBuffer(buffptr); - } - - - if (TNC->DiscPending) - { - TNC->DiscPending--; - - if (TNC->DiscPending == 0) - { - // Too long in Disc Pending - Kill and Restart TNC - } - } - - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - { - // Send the DISCONNECT - - FreeDataDisconnect(TNC); - strcpy(TNC->WEB_TNCSTATE, "Disconnecting"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - } - } - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && STREAM->Attached == 0) - { - // New Attach - - int calllen; - char Msg[80]; - - Debugprintf("FreeData New Attach Stream %d", Stream); - - STREAM->Attached = TRUE; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, STREAM->MyCall); - TNC->Streams[Stream].MyCall[calllen] = 0; - - - FreeDataChangeMYC(TNC, TNC->Streams[0].MyCall); - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Stop Scanning - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command(-1, Msg); - } - - if (STREAM->Attached) - CheckForDetach(TNC, Stream, STREAM, TidyClose, ForcedClose, CloseComplete); - - } - - // See if any frames for this port - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->BPQtoPACTOR_Q) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)Q_REM(&STREAM->BPQtoPACTOR_Q); - UCHAR * data = &buffptr->Data[0]; - STREAM->FramesQueued--; - txlen = (int)buffptr->Len; - - SendAsFile(TNC, TNC->FreeDataInfo->farCall, data, txlen); - } - - if (STREAM->PACTORtoBPQ_Q != 0) - { - buffptr = (PMSGWITHLEN)Q_REM(&STREAM->PACTORtoBPQ_Q); - - datalen = (int)buffptr->Len; - - buff->PORT = Stream; // Compatibility with Kam Driver - buff->PID = 0xf0; - memcpy(&buff->L2DATA, &buffptr->Data[0], datalen); // Data goes to + 7, but we have an extra byte - datalen += sizeof(void *) + 4; - - PutLengthinBuffer(buff, datalen); - - ReleaseBuffer(buffptr); - - return (1); - } - - if (STREAM->ReportDISC) // May need a delay so treat as a counter - { - STREAM->ReportDISC--; - if (STREAM->ReportDISC == 0) - { - buff->PORT = Stream; -// STREAM->Connected = 0; -// STREAM->Attached = 0; - return -1; - } - } - } - return (0); - - case 2: // send - - Stream = buff->PORT; - - if (!TNC->TNCCONNECTED) - { - // Send Error Response - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = 36; - memcpy(&buffptr->Data[0], "No Connection to TNC\r", 36); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return 0; // Don't try if not connected - } - - STREAM = &TNC->Streams[Stream]; - - if (TNC->SwallowSignon) - { - TNC->SwallowSignon = FALSE; // Discard *** connected - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - TXMsg = &buff->L2DATA[0]; - TXMsg[txlen] = 0; - - if (STREAM->Connected) - { - STREAM->PacketsSent++; - - SendDataMsg(TNC, TNC->FreeDataInfo->farCall, buff->L2DATA, txlen); - return 1; - } - - if (_memicmp(&buff->L2DATA[0], "D\r", 2) == 0 || _memicmp(&buff->L2DATA[0], "BYE\r", 4) == 0) - { - STREAM->ReportDISC = TRUE; // Tell Node - return 0; - } - - - // See if Local command (eg RADIO) - - if (_memicmp(&buff->L2DATA[0], "RADIO ", 6) == 0) - { - sprintf(&buff->L2DATA[0], "%d %s", TNC->Port, &buff->L2DATA[6]); - - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK->CIRCUITINDEX, &buff->L2DATA[0])) - { - } - else - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return 1; // No buffers, so ignore - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", &buff->L2DATA[0]); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return 1; - } - - if (_memicmp(&buff->L2DATA[0], "OVERRIDEBUSY", 12) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - TNC->OverrideBusy = TRUE; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} OK\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - if (_memicmp(&buff->L2DATA[0], "PING ", 5) == 0) - { - char * Call = &buff->L2DATA[5]; - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - strlop(Call, 13); - strlop(Call, ' '); - SendPing(TNC, _strupr(Call)); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Ping Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "CQ", 2) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - SendCQ(TNC); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} CQ Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - // See if a Connect Command. - - if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect - { - char Connect[80]; - char loppedCall[10]; - char toCall[10]; - - char * ptr = strchr(&buff->L2DATA[2], 13); - - if (ptr) - *ptr = 0; - - // FreeDATA doesn't have the concept of a connection, so need to simulate it between the nodes - _strupr(&buff->L2DATA[2]); - - if (strlen(&buff->L2DATA[2]) > 9) - buff->L2DATA[11] = 0; - - strcpy(TNC->FreeDataInfo->toCall, &buff->L2DATA[2]); - strcpy(loppedCall, TNC->FreeDataInfo->toCall); - if (TNC->FreeDataInfo->useBaseCall) - strlop(loppedCall, '-'); - strcpy(TNC->FreeDataInfo->farCall, loppedCall); - - // MYCALL and Target call are end to end concepts - the TNC cam can only use one call, set at TNC start. and no SSID's - // Messages are sent at TNC level to the tnc call, so we send our tnc call to the other end - - - txlen = sprintf(Connect, "C %s %s %s ", &buff->L2DATA[2], STREAM->MyCall, TNC->FreeDataInfo->ourCall); - - // See if Busy -/* - if (InterlockedCheckBusy(TNC)) - { - // Channel Busy. Unless override set, wait - - if (TNC->OverrideBusy == 0) - { - // Save Command, and wait up to 10 secs - - sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - TNC->ConnectCmd = _strdup(Connect); - TNC->BusyDelay = TNC->BusyWait * 10; // BusyWait secs - return 0; - } - } -*/ - TNC->OverrideBusy = FALSE; - - memset(STREAM->RemoteCall, 0, 10); - strcpy(STREAM->RemoteCall, &buff->L2DATA[2]); - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - -// FreeDataSendCommand(TNC, Connect); - FreeDataConnect(TNC, STREAM->RemoteCall); - STREAM->Connecting = TRUE; - return 0; - - } - - // Normal data. Send to TNC - - // The TNC doesn't have any commands, so send error message - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Not connected\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - // strlop(buff->L2DATA, 13); - // txlen = SendDataMsg(TNC, TNC->, buff->L2DATA); - // FreeDataSendData(TNC, TXMsg, txlen); - - return 0; - - case 3: - - // CHECK IF OK TO SEND (And check TNC Status) - - Stream = (int)(size_t)buff; - - // FreeData TNC can buffer unlimited data - - if (TNC->Streams[Stream].Attached == 0) - return (TNC->TNCCONNECTED != 0) << 8 | 1; - - return ((TNC->TNCCONNECTED != 0) << 8 | TNC->Streams[Stream].Disconnecting << 15); // OK - - - case 4: // reinit7 - - return 0; - - case 5: // Close - - StopTNC(TNC); - return 0; - - case 6: // Scan Stop Interface - - Param = (size_t)buff; - - if (Param == 2) // Check Permission (Shouldn't happen) - { - Debugprintf("Scan Check Permission called on FreeDATA"); - return 1; // OK to change - } - - if (Param == 1) // Request Permission - { - if (!TNC->CONNECTED) - return 0; // No connection so no interlock - - if (TNC->ConnectPending == 0 && TNC->PTTState == 0) - { - TNC->FreeDataInfo->CONOK = 0; - TNC->GavePermission = TRUE; - return 0; // OK to Change - } - - if (TNC->ConnectPending) - TNC->ConnectPending--; // Time out if set too long - - return TRUE; - } - - if (Param == 3) // Release Permission - { - if (TNC->GavePermission) - { - TNC->GavePermission = FALSE; - if (TNC->ARDOPCurrentMode[0] != 'S') // Skip - TNC->FreeDataInfo->CONOK = 1; - - } - return 0; - } - - // Param is Address of a struct ScanEntry - - Scan = (struct ScanEntry *)buff; - return 0; - } - return 0; -} - -VOID FreeDataReleaseTNC(struct TNCINFO * TNC) -{ - // Set mycall back to Node or Port Call, and Start Scanner - - UCHAR TXMsg[1000]; - - FreeDataChangeMYC(TNC, TNC->NodeCall); - - // Start Scanner - - sprintf(TXMsg, "%d SCANSTART 15", TNC->Port); - - Rig_Command(-1, TXMsg); - - ReleaseOtherPorts(TNC); - -} - -VOID FreeDataSuspendPort(struct TNCINFO * TNC) -{ - TNC->FreeDataInfo->CONOK = 0; -} - -VOID FreeDataReleasePort(struct TNCINFO * TNC) -{ - TNC->FreeDataInfo->CONOK = 1; -} - - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, "" - "" - "VARA Status" - "

FreeData Status" - "

", - TNC->Port); - - - Len += sprintf(&Buff[Len], ""); - - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); -// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
Proto State%s
Traffic%s
TNC Restarts
"); - - Len += sprintf(&Buff[Len], "", TNC->WebBuffer); - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - -#ifndef LINBPQ - -#define BGCOLOUR RGB(236,233,216) -static HBRUSH RedBrush = NULL; -HBRUSH GreenBrush; -HBRUSH BlueBrush; -static HBRUSH bgBrush = NULL; - -extern HWND ClientWnd, FrameWnd; -extern int OffsetH, OffsetW; - -extern HMENU hMainFrameMenu; -extern HMENU hBaseMenu; -extern HANDLE hInstance; - -extern HKEY REGTREE; - - -/* -static LRESULT CALLBACK PacWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - MINMAXINFO * mmi; - PAINTSTRUCT ps; - HDC hdc; - - int i; - struct TNCINFO * TNC; - - HKEY hKey; - char Key[80]; - int retCode, disp; - - for (i=0; i<41; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC->hDlg == hWnd) - break; - } - - if (TNC == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - switch (message) { - - case WM_CREATE: - - break; - - case WM_PAINT: - - hdc = BeginPaint(hWnd, &ps); - -// SelectObject(ps.hdc, RedBrush); - SelectObject(ps.hdc, GreenBrush); -// SelectObject(ps.hdc, GetStockObject(GRAY_BRUSH)); - - EndPaint(hWnd, &ps); - break; - - case WM_GETMINMAXINFO: - - if (TNC->ClientHeight) - { - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = TNC->ClientWidth; - mmi->ptMaxSize.y = TNC->ClientHeight; - mmi->ptMaxTrackSize.x = TNC->ClientWidth; - mmi->ptMaxTrackSize.y = TNC->ClientHeight; - } - - break; - - - case WM_MDIACTIVATE: - { - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - - if (TNC->hMenu) - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)TNC->hMenu, "Actions"); - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - -// SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) TNC->hMenu, (LPARAM) TNC->hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - // call DrawMenuBar after the menu items are set - DrawMenuBar(FrameWnd); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - } - - - - case WM_INITMENUPOPUP: - - if (wParam == (WPARAM)TNC->hMenu) - { - if (TNC->ProgramPath) - { - if (strstr(TNC->ProgramPath, " TNC") || strstr(TNC->ProgramPath, "ARDOP") || strstr(TNC->ProgramPath, "VARA")) - { - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_ENABLED); - - break; - } - } - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_GRAYED); - } - - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - case WINMOR_KILL: - - KillTNC(TNC); - break; - - case WINMOR_RESTART: - - KillTNC(TNC); - RestartTNC(TNC); - break; - - case WINMOR_RESTARTAFTERFAILURE: - - TNC->RestartAfterFailure = !TNC->RestartAfterFailure; - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", TNC->Port); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - RegSetValueEx(hKey,"TNC->RestartAfterFailure",0,REG_DWORD,(BYTE *)&TNC->RestartAfterFailure, 4); - RegCloseKey(hKey); - } - break; - - case ARDOP_ABORT: - - if (TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SIZING: - case WM_SIZE: - - MoveWindows(TNC); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - - case SC_RESTORE: - - TNC->Minimized = FALSE; - break; - - case SC_MINIMIZE: - - TNC->Minimized = TRUE; - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - - case WM_CTLCOLORSTATIC: - { - HDC hdcStatic = (HDC)wParam; - SetTextColor(hdcStatic, RGB(0, 0, 0)); - SetBkMode(hdcStatic, TRANSPARENT); - return (LONG)bgBrush; - } - - case WM_DESTROY: - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); -} -*/ - -#endif - - - -VOID * FreeDataExtInit(EXTPORTDATA * PortEntry) -{ - int port; - char Msg[255]; - char * ptr; - struct TNCINFO * TNC; - char * TempScript; - u_long param = 1; - int line; - - port = PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); - WritetoConsole(Msg); - - return ExtProc; - } - -#ifndef LINBPQ - - if (bgBrush == NULL) - { - bgBrush = CreateSolidBrush(BGCOLOUR); - RedBrush = CreateSolidBrush(RGB(255,0,0)); - GreenBrush = CreateSolidBrush(RGB(0,255,0)); - BlueBrush = CreateSolidBrush(RGB(0,0,255)); - } - -#endif - - Consoleprintf("FreeData Host %s %d", TNC->HostName, TNC->TCPPort); - - TNC->Port = port; - TNC->Hardware = H_FREEDATA; - - TNC->ARDOPDataBuffer = malloc(MAXRXSIZE); - TNC->ARDOPBuffer = malloc(8192); - - TNC->PortRecord = PortEntry; - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - memcpy(TNC->NodeCall, MYNODECALL, 10); - else - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - memcpy(TNC->FreeDataInfo->ourCall, TNC->NodeCall, 10); - strlop(TNC->FreeDataInfo->ourCall, ' '); - if (TNC->FreeDataInfo->useBaseCall) - strlop(TNC->FreeDataInfo->ourCall, '-'); - - if (TNC->FreeDataInfo->hamlibHost == 0) - TNC->FreeDataInfo->hamlibHost = _strdup("127.0.0.1"); - - if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) - TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - - if (TNC->PacketChannels > 1) - TNC->PacketChannels = 1; - - PortEntry->MAXHOSTMODESESSIONS = TNC->PacketChannels + 1; - - PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only - PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream - - PortEntry->PORTCONTROL.UICAPABLE = TRUE; - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 236; - - TNC->SuspendPortProc = FreeDataSuspendPort; - TNC->ReleasePortProc = FreeDataReleasePort; - -// PortEntry->PORTCONTROL.PORTSTARTCODE = KAMStartPort; -// PortEntry->PORTCONTROL.PORTSTOPCODE = KAMStopPort; - - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - // Set Essential Params and MYCALL - - // Put overridable ones on front, essential ones on end - - TempScript = zalloc(1000); - - // cant think of any yet - - if (TNC->InitScript) - { - strcat(TempScript, TNC->InitScript); - free(TNC->InitScript); - } - - TNC->InitScript = TempScript; - - // Set MYCALL - - sprintf(Msg, "MYCALL %s\r", TNC->NodeCall); - strcat(TNC->InitScript, Msg); - - strcpy(TNC->CurrentMYC, TNC->NodeCall); - - if (TNC->WL2K == NULL) - if (PortEntry->PORTCONTROL.WL2KInfo.RMSCall[0]) // Alrerady decoded - TNC->WL2K = &PortEntry->PORTCONTROL.WL2KInfo; - - PortEntry->PORTCONTROL.TNC = TNC; - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 520; - TNC->WebWinY = 500; - TNC->WebBuffer = zalloc(5000); - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - TNC->WEB_CHANSTATE = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_PROTOSTATE = zalloc(100); - TNC->WEB_RESTARTTIME = zalloc(100); - TNC->WEB_RESTARTS = zalloc(100); - - TNC->WEB_MODE = zalloc(20); - TNC->WEB_TRAFFIC = zalloc(100); - - -#ifndef LINBPQ - - line = 6; - - if (TNC->TXFreq) - { - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow + 22, PacWndProc, 500, 450, ForcedClose); - - InitCommonControls(); // loads common control's DLL - - CreateWindowEx(0, "STATIC", "TX Tune", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNE = CreateWindowEx(0, TRACKBAR_CLASS, "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNEVAL = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE, 320,line,30,20, TNC->hDlg, NULL, hInstance, NULL); - - SendMessage(TNC->xIDC_TXTUNE, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG(-200, 200)); // min. & max. positions - - line += 22; - } - else - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 450, ForcedClose); - - CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,450,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,line,106,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,520,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,line,110,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,144,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Proto State", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_PROTOSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,line,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,116,line,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,line,20,20 , TNC->hDlg, NULL, hInstance, NULL); - CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, - 0,170,250,300, TNC->hDlg, NULL, hInstance, NULL); - - TNC->ClientHeight = 450; - TNC->ClientWidth = 500; - - TNC->hMenu = CreatePopupMenu(); - - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill TNC TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart TNC TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after failed Connection"); - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); - - MoveWindows(TNC); -#endif - - time(&TNC->lasttime); // Get initial time value - - ConnecttoFreeData(port); - TNC->FreeDataInfo->CONOK = 1; - - return ExtProc; -} - - -VOID TidyClose(struct TNCINFO * TNC, int Stream) -{ - // We don't get data acks, so can't check for bytes outstanding - - FreeDataDisconnect(TNC); -} - -VOID ForcedClose(struct TNCINFO * TNC, int Stream) -{ - FreeDataDisconnect(TNC); -} - - - -VOID CloseComplete(struct TNCINFO * TNC, int Stream) -{ - if (Stream == 0) - { - FreeDataReleaseTNC(TNC); - } -} - -VOID FreeDataAbort(struct TNCINFO * TNC) -{ - FreeDataSendCommand(TNC, "ABORT\r"); -} - -// Host Mode Stuff (we reuse some routines in SCSPactor) - -VOID FreeDataDoTermModeTimeout(struct TNCINFO * TNC) -{ - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->ReinitState == 0) - { - //Checking if in Terminal Mode - Try to set back to Term Mode - - TNC->ReinitState = 1; - return; - } - - if (TNC->ReinitState == 1) - { - // Forcing back to Term Mode - - TNC->ReinitState = 0; - return; - } - - if (TNC->ReinitState == 3) - { - return; - } -} - -static RECT Rect1 = {30, 160, 400, 195}; - -int zEncode(unsigned char * in, unsigned char * out, int len, unsigned char * Banned) -{ - // Replace forbidden chars with =xx - - unsigned char * ptr = out; - unsigned char c; - - while (len--) - { - c = *(in++); - - if (strchr(&Banned[0], c)) - { - *(out++) = '='; - *(out++) = (c >> 4) + 'A'; - *(out++) = (c & 15) + 'A'; - } - else - *(out++) = c; - } - - return (out - ptr); -} - - - -VOID FreeDataProcessTNCMessage(struct TNCINFO * TNC, char * Call, unsigned char * Msg, int Len) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * toCall, * fromCall, * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - // First Byte of Message is Type. Messages can be commands or short (<120) data packets - // Data is encoded with =xx replacing restricted chars - - Msg[Len] = 0; - - switch (Msg[0]) - { - case 'C': - - // Connect Request. C G8BPQ-10 GM8BPQ-2 (Target, Origin) - - toCall = strtok_s(&Msg[2], " ", &Context); - fromCall = strtok_s(NULL, " ", &Context); - tncCall = strtok_s(NULL, " ", &Context); - - strcpy(TNC->FreeDataInfo->farCall, tncCall); - - ConvToAX25Ex(fromCall, axcall); // Allow -T and -R SSID's for MPS - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(axcall) == FALSE) - { - Debugprintf("FreeData Call from %s rejected", fromCall); - - // Send 'd' - - Sleep(1000); - FreeDataDisconnect(TNC, "d"); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(axcall, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - Sleep(1000); - FreeDataSendCommand(TNC, "d"); - - Debugprintf("FreeDara Call from %s not in ValidCalls - rejected", Call); - return; - } - } - } - - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(toCall, Appl) == 0) - break; - } - - if (App < 32) - { - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(Call, "-T" ) || strstr(Call, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - if (!CheckAppl(TNC, AppName)) - { - Sleep(1000); - FreeDataSendCommand(TNC, "dApplication not Available"); - return; - } - } - - ProcessIncommingConnectEx(TNC, fromCall, 0, TRUE, TRUE); - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - // if connect to an application, send command - - if (AppName[0]) - { - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf(buffptr->Data, "%s\r", AppName); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - } - - TNC->ConnectPending = FALSE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, toCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - if (SESS->Frequency == 1500) - { - // try to get from WL2K record - - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - } - } - SESS->Mode = TNC->WL2KMode; - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, toCall); - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - SESS->Mode = WL2K->mode; - } - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - STREAM->Connected = TRUE; - - // Send Connect ACK - Sleep(1000); - FreeDataSendCommand(TNC, "c"); - return; - - case 'c': - - // Connect ACK - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - STREAM->Connected = TRUE; - STREAM->Connecting = FALSE; - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connected to %s\r", TNC->FreeDataInfo->toCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - - return; - - case 'D': - - // Disconnect Command - - FreeDataSendCommand(TNC, "d"); - - // Drop through to disconnect this end - - case 'd': - - // Disconnect complete (response to sending "D") - // Or connect refused in response to "C" - - if (STREAM->Connecting) - { - // Connection Refused - If there is a message, pass to appl - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - if (Msg[1]) - buffptr->Len = sprintf(buffptr->Data, "Connect Rejected - %s\r", &Msg[1]); - else - buffptr->Len = sprintf(buffptr->Data, "Connect Rejected\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - return; - } - - // Release Session - - if (STREAM->Connected) - { - // Create a traffic record - - char logmsg[120]; - time_t Duration; - - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - } - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - return; - - case 'B': - - // Was Base64, but has been expanded - just send to User - - // If len > blocksize, fragment - - Len--; - Msg++; // Remove Type - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Msg, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Msg, 256); - Len -= 256; - Msg += 256; - STREAM->BytesRXed += 256; - - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Msg, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Msg, Len); - STREAM->BytesRXed += Len; - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - return; - - case 'I': - - // Encoded Response - - // Undo = transparency - - ptr = Msg + 1; - - while (ptr = strchr(ptr, '=')) - { - // Next two chars are a hex value - - a = ptr[1] - 'A'; - b = ptr[2] - 'A'; - memmove(ptr, ptr + 2, Len); - ptr[0] = (a << 4) + b; - ptr++; - } - - buffptr = GetBuff(); - buffptr->Len = sprintf(buffptr->Data, "%s", &Msg[1]); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - return; - - case 'f': - - // FreeDATA File Transfer - - // Seems to be f null fn null data - //f.;Makefile.;.;123123123.; - { - char * FN; - time_t CRC; - int FileLen; - char Filename[256]; - FILE * fp1; - unsigned char * ptr; - char Text[64]; - int textLen; - - - if (TNC->FreeDataInfo->RXDir == NULL) - { - Debugprintf("FreeDATA RXDIRECTORY not set - file transfer ignored"); - return; - } - - FN = _strdup(&Msg[3]); - ptr = &Msg[4] + strlen(FN); - - ptr = ptr + strlen(ptr) + 2; - CRC = atoi(ptr); - ptr = ptr + strlen(ptr) + 2; - - FileLen = Len - (ptr - Msg); - - sprintf(Filename, "%s\\%s", TNC->FreeDataInfo->RXDir, FN); - - fp1 = fopen(Filename, "wb"); - - if (fp1) - { - fwrite(ptr, 1, FileLen, fp1); - fclose(fp1); - textLen = sprintf(Text, "File %s received from %s \r", FN, Call); - WritetoTrace(TNC, Text, textLen); - } - else - Debugprintf("FreeDATA - File %s create failed %s", Filename); - - - free(FN); - return; - - } - - - } - - if (STREAM->Attached == 0) - return; - - - buffptr = GetBuff(); - - if (buffptr == 0) - { - return; // No buffers, so ignore - } - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", Msg); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - -} - - -VOID FreeDataProcessNewConnect(struct TNCINFO * TNC, char * fromCall, char * toCall) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - strcpy(TNC->FreeDataInfo->farCall, fromCall); - - ConvToAX25Ex(fromCall, axcall); // Allow -T and -R SSID's for MPS - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(axcall) == FALSE) - { - Debugprintf("FreeData Call from %s rejected", fromCall); - - // Send 'd' - - Sleep(1000); - FreeDataDisconnect(TNC); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(axcall, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - Sleep(1000); - FreeDataDisconnect(TNC); - - Debugprintf("FreeData Call from %s not in ValidCalls - rejected", fromCall); - return; - } - } - } - /* - - // At the moment we dont support applcalls - - - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(toCall, Appl) == 0) - break; - } - - if (App < 32) - { - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(Call, "-T" ) || strstr(Call, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - if (!CheckAppl(TNC, AppName)) - { - Sleep(1000); - FreeDataSendCommand(TNC, "dApplication not Available"); - return; - } - } - */ - - ProcessIncommingConnectEx(TNC, fromCall, 0, TRUE, TRUE); - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - // if connect to an application, send command - - if (AppName[0]) - { - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf(buffptr->Data, "%s\r", AppName); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - } - - TNC->ConnectPending = FALSE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, toCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - if (SESS->Frequency == 1500) - { - // try to get from WL2K record - - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - } - } - SESS->Mode = TNC->WL2KMode; - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, toCall); - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - SESS->Mode = WL2K->mode; - } - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - STREAM->Connected = TRUE; - - return; - -} - -VOID FreeDataProcessConnectAck(struct TNCINFO * TNC, char * Call, unsigned char * Msg, int Len) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * toCall, * fromCall, * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - STREAM->Connected = TRUE; - STREAM->Connecting = FALSE; - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connected to %s\r", TNC->FreeDataInfo->toCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - - return; - -} -extern char LOC[7]; -/* -Line 104: if received_json["type"] == 'PING' and received_json["command"] == "PING": -Line 111: if received_json["type"] == 'ARQ' and received_json["command"] == "sendFile": -Line 142: if received_json["type"] == 'ARQ' and received_json["command"] == "sendMessage": -Line 173: if received_json["type"] == 'ARQ' and received_json["command"] == "stopTransmission": -Line 182: if received_json["type"] == 'GET' and received_json["command"] == 'STATION_INFO': -Line 195: if received_json["type"] == 'GET' and received_json["command"] == 'TNC_STATE': -Line 244: if received_json["type"] == 'GET' and received_json["command"] == 'RX_BUFFER': -Line 258: if received_json["type"] == 'GET' and received_json["command"] == 'RX_MSG_BUFFER': -Line 272: if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_BUFFER': -Line 275: if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_MSG_BUFFER': -*/ - -//{\"type\" : \"ARQ\", \"command\" : \"sendMessage\", \"dxcallsign\" : \"G8BPQ\", \"mode\" : \"10\", \"n_frames\" : \"1\", \"data\" : \"Hello Hello\" , \"checksum\" : \"123\", \"timestamp\" : 1642580748576} - - - -static unsigned char BANNED[] = {'"', '=', ':', '{', '}', '[', ']', '/', 13, 0}; // I think only need to escape = ": CR Null - - -static void SendDataMsg(struct TNCINFO * TNC, char * Call, char * Msg, int Len) -{ - // We can't base64 encode chunks. so buffer as original data and encode on send - - SendAsFile(TNC, TNC->FreeDataInfo->farCall, Msg, Len); - WritetoTrace(TNC, Msg, Len); - - return; -} - - - -static int SendAsRaw(struct TNCINFO * TNC, char * Call, char * myCall, char * Msg, int Len) -{ - char Message[16284]; - char * Base64; - -/* -{ - "type": "arq", - "command": "send_raw", - "uuid": "sjdfksndfkjsnd-123-sdfvlks", -"parameter": - [ - { - "dxcallsign": "DJ2LS", - "mycallsign": "DN2LS-2", - "mode": "255", - "n_frames": "1", - "data": "" - } - ] -} -*/ - - // TNC now only supports send_raw, with base64 encoded data - - char Template[] = "{\"type\": \"arq\", \"command\": \"send_raw\", \"parameter\":" - "[{\"dxcallsign\": \"%s\", \"mycallsign\": \"%s\", \"mode\": \"255\", \"n_frames\": \"1\", \"data\": \"%s\"}]}\n"; - - Base64 = byte_base64_encode(Msg, Len); - - Len = sprintf(Message, Template, Call, myCall, Base64); - - free(Base64); - return send(TNC->TCPDataSock, Message, Len, 0); -} - -void FlushData(struct TNCINFO * TNC) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Info = TNC->FreeDataInfo; - int Len = Info->toSendCount; - - // We need to flag as data (B) then base64 encode it - - memmove(&Info->toSendData[1], Info->toSendData, Len); - Info->toSendData[0] = 'B'; - Len++; - - SendAsRaw(TNC, Info->farCall, Info->ourCall, Info->toSendData, Len); - - Info->toSendCount = 0; - Info->toSendTimeout = 0; - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - -} - -static int SendAsFile(struct TNCINFO * TNC, char * Call, char * Msg, int Len) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Info = TNC->FreeDataInfo; - - // Add to buffer - - if ((Info->toSendCount + Len) > 8192) // Reasonable Limit - { - // Send the buffered bit - - FlushData(TNC); - } - - memcpy(&Info->toSendData[Info->toSendCount], Msg, Len); - Info->toSendCount += Len; - Info->toSendTimeout = 10; // About a second - - STREAM->BytesTXed += Len; - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - return Len; -} - -static int SendTNCCommand(struct TNCINFO * TNC, char * Type, char * Command) -{ - char Message[256]; - int Len; - - Len = sprintf(Message, "{\"type\" : \"%s\", \"command\" : \"%s\"}\n", Type, Command); - return send(TNC->TCPDataSock, Message, Len, 0); -} - -static void SendPoll(struct TNCINFO * TNC) -{ - char DataMsgPoll[] = "{\"type\" : \"GET\", \"command\" : \"RX_MSG_BUFFER\"}\n"; -// char DaemonPoll[] = "{\"type\" : \"GET\", \"command\" : \"DAEMON_STATE\"}\n"; - char TNCPoll[] = "{\"type\" : \"GET\", \"command\" : \"TNC_STATE\", \"timestamp\" : 0}\n"; - - // Poll daemon rapidly until tnc is connected, then every 5 secs - - if ((TNC->PollDelay++ > 50))// || !TNC->TNCCONNECTED) && TNC->DAEMONCONNECTED) - { -// ret = send(TNC->TCPSock, (char *)&DaemonPoll, strlen(DaemonPoll), 0); - TNC->PollDelay = 0; - - } - - if (TNC->TNCCONNECTED) - { -// ret = send(TNC->TCPDataSock, (char *)&TNCPoll, strlen(TNCPoll), 0); - -// if (TNC->PollDelay & 1) -// ret = SendTNCCommand(TNC, "GET", "RX_BUFFER"); -// else if (TNC->PollDelay & 2) -// ret = SendTNCCommand(TNC, "GET", "RX_MSG_BUFFER"); -// else -// ret = send(TNC->TCPDataSock, (char *)&TNCPoll, strlen(TNCPoll), 0); - - - } - return; -} - -static void SendPing(struct TNCINFO * TNC, char * Call) -{ - char Ping[] = "{\"type\" : \"ping\", \"command\" : \"ping\", \"dxcallsign\" : \"%s\", \"timestamp\" : %d}\n"; - char Message[256]; - int Len, ret; - - Len = sprintf(Message, Ping, Call, time(NULL)); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - -static void SendCQ(struct TNCINFO * TNC) -{ - char CQ[] = "{\"type\" : \"BROADCAST\", \"command\" : \"cqcqcq\", \"timestamp\" : %d}\n"; - char Message[256]; - int Len, ret; - - Len = sprintf(Message, CQ, time(NULL)); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - - -unsigned short int compute_crc(unsigned char *buf,int len); - - -int FreeDataWriteCommBlock(struct TNCINFO * TNC) -{ - if (TNC->hDevice) - return WriteCOMBlock(TNC->hDevice, TNC->TXBuffer, TNC->TXLen); - - return 0; -} - -char * getObjectFromArray(char * Msg) -{ - // This gets the next object from an array ({} = object, [] = array - // We look for the end of the object same number of { and }, teminate after } and return pointer to next object - // So we have terminated Msg, and returned next object in array - - // Only call if Msg is the next object in array - - - char * ptr = Msg; - char c; - - int Open = 0; - int Close = 0; - - while (c = *(ptr++)) - { - if (c == '{') Open ++; else if (c == '}') Close ++; - - if (Open == Close) - { - *(ptr++) = 0; - return ptr; - } - } - return 0; -} -/* - ["DATACHANNEL;RECEIVEDOPENER","ARQ;RECEIVING","ARQ;RECEIVING;SUCCESS"] [{"DXCALLSIGN":"GM8BPQ -{"DXCALLSIGN":"GM8BPQ","DXGRID":"","TIMESTAMP":1642847440,"RXDATA":[{"dt":"f","fn":"config.json", -"ft":"application\/json","d":"data:application\/json;base64, -ewogICAgInRuY19ob3N0IiA6ICIxMjcuMC4wLjEiLAogICAgInRuY19wb3J0IiA6ICIzMDAwIiwKICAgICJkYWVtb25faG9zdCIgOiAiMTI3LjAuMC4xIiwKICAgICJkYWVtb25fcG9ydCIgOiAiMzAwMSIsCiAgICAibXljYWxsIiA6ICJBQTBBQSIsCiAgICAibXlncmlkIiA6ICJBQTExZWEiICAgIAp9" -,"crc":"123123123"}]} -*/ -void ProcessFileObject(struct TNCINFO * TNC, char * This) -{ - char * Call; - char * LOC; - char * FN; - char * Type; - char * ptr, * ptr2; - int Len, NewLen; - - Call = strchr(This, ':'); - Call += 2; - This = strlop(Call, '"'); - - LOC = strchr(This, ':'); - LOC += 2; - This = strlop(LOC, '"'); - - FN = strstr(This, "fn"); - FN += 5; - This = strlop(FN, '"'); - - Type = strstr(This, "base64"); - Type += 7; - This = strlop(Type, '"'); - - // Decode Base64 - - Len = strlen(Type); - - Debugprintf("RX %d %s %d", TNC->Port, FN, Len); - - ptr = ptr2 = Type; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - NewLen = (int)(ptr2 - Type); - - if (*(ptr-1) == '=') - NewLen--; - - if (*(ptr-2) == '=') - NewLen--; - - Type[NewLen] = 0; - - Type --; - - Type[0] = 'B'; ; // Base64 Info - - FreeDataProcessTNCMessage(TNC, Call, Type, NewLen + 1); - - -} - -void ProcessMessageObject(struct TNCINFO * TNC, char * This) -{ - // This gets Call and Message from a RX_MSG_BUFFER array element . It doesn't need care that it is json/ - // as the format is such that keys are unique - - // {"DXCALLSIGN":"GM8BPQ","DXGRID":"","TIMESTAMP":1642581230,"RXDATA":[{"dt":"m","d":"Hello","crc":"123"}]} - - char * Call; - char * LOC; - char * Type; - char * Msg; - - Call = strchr(This, ':'); - Call += 2; - This = strlop(Call, '"'); - - LOC = strchr(This, ':'); - LOC += 2; - This = strlop(LOC, '"'); - - Type = strstr(This, "\"dt\""); - Type += 6; - This = strlop(Type, '"'); - - Msg = strchr(This, ':'); - Msg += 2; - This = strlop(Msg, '"'); - - FreeDataProcessTNCMessage(TNC, Call, Msg, strlen(Msg)); -} - -void processJSONINFO(struct TNCINFO * TNC, char * Info, char * Call, double snr) -{ - char * LOC = ""; - char * ptr, * Context; - - // Info is an array. Normally only one element, but should check - - ptr = strtok_s(&Info[1], ",]", &Context); - - while (ptr && ptr[1]) - { - if (strstr(ptr, "BEACON;RECEIVING")) - { - char CQ[64]; - int Len; - - Len = sprintf(CQ, "Beacon received from %s SNR %3.1f\r", Call, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (Call) - UpdateMH(TNC, Call, '!', 'I'); - } - if (strstr(ptr, "PING;RECEIVING")) - { - // Add to MH - - if (Call) - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "CQ;RECEIVING")) - { - char CQ[64]; - int Len; - - Len = sprintf(CQ, "CQ received from %s SNR %3.1f\r", Call, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "PING;RECEIVEDACK")) - { - char Msg[128]; - int Len; - - Len = sprintf(Msg, "Ping Response from %s SNR %3.1f\r", Call, snr); - FreeDataProcessTNCMessage(TNC, Call, Msg, Len); - - // Add to MH - - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "TRANSMITTING;FAILED")) - { - // Failed to send a message - if it was a connect request tell appl - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - if (STREAM->Connecting) - { - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connect Failed\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - } - } - ptr = strtok_s(NULL, ",]", &Context); - } -} - - - - - - -char * getJSONValue(char * Msg, char * Key) -{ - char * ptr, *ptr2, *value = 0; - int vallen, keylen = strlen(Key); - char c; - - // We Null Terminate the value, so we must look for keys in reverse order - - ptr = strstr(Msg, Key); - - if (ptr) - { - ptr += (keylen + 1); - - if (*(ptr) == '[') - { - // Array - - int Open = 0; - int Close = 0; - - ptr2 = ptr; - - while (c = *(ptr++)) - { - if (c == '[') - Open ++; - else if (c == ']') - Close ++; - - if (Open == Close) - { - vallen = ptr - ptr2; - value = ptr2; - value[vallen] = 0; - return value; - } - } - } - else if (*(ptr) == '\"') - { - // String - - ptr2 = ptr; - ptr = strchr(ptr + 1, '\"'); - if (ptr) - { - ptr++; - vallen = ptr - ptr2; - value = ptr2; - value[vallen] = 0; - } - } - } - return value; -} - - -char stopTNC[] = "{\"type\" : \"SET\", \"command\": \"STOPTNC\" , \"parameter\": \"---\" }\r"; - - -void ProcessDAEMONJSON(struct TNCINFO * TNC, char * Msg, int Len) -{ - char * ptr; - char * capture, * playback; - - - if (memcmp(Msg, "{\"command\":\"daemon_state\"", 25) == 0) - { -/* - {"COMMAND":"DAEMON_STATE","DAEMON_STATE":[{"STATUS":"stopped"}], - "PYTHON_VERSION":"3.9", - "HAMLIB_VERSION":"4.0", - "INPUT_DEVICES":[{"ID":5,"NAME":"pulse"},{"ID":9,"NAME":"default"}], - "OUTPUT_DEVICES":[{"ID":0,"NAME":"bcm2835 Headphones: - (hw:0,0)"},{"ID":1,"NAME":"sysdefault"},{"ID":2,"NAME":"lavrate"},{"ID":3,"NAME":"samplerate"},{"ID":4,"NAME":"speexrate"},{"ID":5,"NAME":"pulse"},{"ID":6,"NAME":"upmix"},{"ID":7,"NAME":"vdownmix"},{"ID":8,"NAME":"dmix"},{"ID":9,"NAME":"default"}], - "SERIAL_DEVICES":[{"PORT":"\/dev\/ttyAMA0","DESCRIPTION":"ttyAMA0 [1dff]"}], - "CPU":"39.6", - "RAM":"38.6", - "VERSION":"0.1-prototype"} -*/ - - Msg += 25; - - playback = getJSONValue(Msg, "\"output_devices\""); - capture = getJSONValue(Msg, "\"input_devices\""); - - if (TNC->CaptureDevices) - free(TNC->CaptureDevices); - - TNC->CaptureDevices = _strdup(capture); - - if (TNC->PlaybackDevices) - free(TNC->PlaybackDevices); - - TNC->PlaybackDevices = _strdup(playback); - - ptr = getJSONValue(Msg, "\"daemon_state\""); - - if (strstr(ptr, "stopped")) - { - TNC->FreeDataInfo->TNCRunning = 0; - // if we have Capture and Playback devices, then start the TNC, else look in message for them - - if (TNC->CaptureDevices) - { - if (TNC->FreeDataInfo->startingTNC == 0) - { - // Find Capture and Playback indices - - struct FreeDataINFO * Info = TNC->FreeDataInfo; - char * devptr = stristr(TNC->CaptureDevices, Info->Capture); - int capindex = -1, playindex = -1; - char startTNC[] = "{\"type\":\"set\",\"command\":\"start_tnc\"," - "\"parameter\":[{\"mycall\":\"%s\",\"mygrid\":\"%s\",\"rx_audio\":\"%d\"," - "\"tx_audio\":\"%d\",\"devicename\":\"RIG_MODEL_NETRIGCTL\",\"deviceport\":\"/dev/ttyAMA0\"," - "\"serialspeed\":\"19200\"," - "\"pttprotocol\":\"RTS\",\"pttport\":\"/dev/ttyAMA0\",\"data_bits\":\"8\"," - "\"stop_bits\":\"1\",\"handshake\":\"None\", \"radiocontrol\":\"disabled\"," - "\"rigctld_ip\":\"%s\",\"rigctld_port\":\"%d\"," - "\"enable_scatter\":\"0\",\"enable_fft\":\"0\",\"low_bandwith_mode\":\"0\"}]}\n"; - - - char Command[512]; - int Len; - - if (devptr) - { - while (*(--devptr) != '{'); // find start of subparam - capindex = atoi(&devptr[6]); - } - - devptr = stristr(TNC->PlaybackDevices, Info->Playback); - - if (devptr) - { - while (*(--devptr) != '{'); // find start of subparam - playindex = atoi(&devptr[6]); - } - - if (capindex > -1 && playindex > -1) - { - Len = sprintf(Command, startTNC, TNC->FreeDataInfo->ourCall, LOC, capindex, playindex, - TNC->FreeDataInfo->hamlibHost, TNC->FreeDataInfo->hamlibPort); - send(TNC->TCPSock, Command, Len, 0); -// TNC->FreeDataInfo->startingTNC = 5; - } - } - } - else - { - ptr = getJSONValue(Msg, "\"version\""); - - } - return; - } - TNC->FreeDataInfo->TNCRunning = 1; - - if (TNC->TNCCONNECTED == FALSE && TNC->TNCCONNECTING == FALSE) - ConnectTNCPort(TNC); - - return; - - } - - Debugprintf(Msg); -} - -void StopTNC(struct TNCINFO * TNC) -{ - char stopTNC[] = "{\"type\" : \"set\", \"command\": \"stop_tnc\" , \"parameter\": \"---\"}"; - - if (TNC->TNCCONNECTED) - { - send(TNC->TCPSock, stopTNC, strlen(stopTNC), 0); - closesocket(TNC->TCPDataSock); - } -} - - -void ProcessTNCJSON(struct TNCINFO * TNC, char * Msg, int Len) -{ - char * ptr; - - if (memcmp(Msg, "{\"ptt\":", 7) == 0) - { - if (strstr(Msg, "True")) - { -// TNC->Busy = TNC->BusyHold * 10; // BusyHold delay - - if (TNC->PTTMode) - Rig_PTT(TNC, TRUE); - } - else - { - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); - } - return; - } - - if (memcmp(Msg, "{\"command\":\"tnc_state\"", 22) == 0) - { -/* -{"COMMAND":"TNC_STATE","TIMESTAMP":1642429227972,"PTT_STATE":"False","TNC_STATE":"IDLE","ARQ_STATE":"False", -"AUDIO_RMS":"0","SNR":"0","FREQUENCY":"145000000","MODE":"FM","BANDWITH":"15000", -"FFT":"[47.7, 28.9, 19.8, 26.4, 22.9, 19.9, 20.0, 20.1, 21.8, 24.0, 21.4, 14.9, 20.6, 17.9, 19.9, 18.4, 20.8, -22.2, 17.8, 23.7, 17.5, 15.6, 21.7, 17.5, 20.4, 21.7, 23.4, 18.2, 21.6, 17.0, 18.7, 18.2, 19.8, 18.6, 20.2, -.. -12.0, 11.9, 12.9, 13.5, 14.3, 14.6, 16.5, 15.4, 14.9, 13.7, 15.6, 12.3]", -"SCATTER":[],"RX_BUFFER_LENGTH":"0","RX_MSG_BUFFER_LENGTH":"0","ARQ_BYTES_PER_MINUTE":"0","ARQ_BYTES_PER_MINUTE_BURST":"0","ARQ_COMPRESSION_FACTOR":"0","ARQ_TRANSMISSION_PERCENT":"0","TOTAL_BYTES":"0","INFO":[],"BEACON_STATE":"False","STATIONS":[],"EOF":"EOF"}{"type" : "GET", "command" : "TNC_STATE", "timestamp" : 1642429228121} - -"arq_session":"True" -\"arq_session_state\":\"disconnected\" -*/ - char * LOC = 0; - char * Stations; - char * myCall = 0; - char * farCall = 0; - double snr; - int arqstate = 0; - - Msg += 23; - - ptr = strstr(Msg, "snr"); - - if (ptr) - snr = atof(ptr + 6); - - Stations = getJSONValue(Msg, "\"stations\""); - - if (Stations) - { - ptr = Stations + strlen(Stations) + 1; - LOC = getJSONValue(ptr, "\"dxgrid\""); - farCall = getJSONValue(ptr, "\"dxcallsign\""); - myCall = getJSONValue(ptr, "\"mycallsign\""); - - if (myCall && farCall) - { - myCall++; - strlop(myCall, '"'); - farCall++; - strlop(farCall, '"'); - } - } - - // Look for changes in arq_session_state - - ptr = strstr(Msg, "\"arq_session_state\""); - - if (ptr) - { - struct STREAMINFO * STREAM = &TNC->Streams[0]; - ptr += 21; - - if (memcmp(ptr, "disconnected", 10) == 0) - { - arqstate = 1; - - // if connected this is a new disconnect - - if (STREAM->Connected) - { - // Create a traffic record - - char logmsg[120]; - time_t Duration; - - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - } - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - } - else if (memcmp(ptr, "connecting", 10) == 0) - arqstate = 2; - else if (memcmp(ptr, "connected", 9) == 0) - { - // if connection is idle this is an incoming connect - - arqstate = 3; - - if (STREAM->Connecting == FALSE && STREAM->Connected == FALSE) - { - FreeDataProcessNewConnect(TNC, farCall, myCall); - } - - // if connecting it is a connect ack - - else if (STREAM->Connecting) - { - FreeDataProcessConnectAck(TNC, farCall, Msg, Len); - } - } - - else if (memcmp(ptr, "disconnecting", 12) == 0) - arqstate = 4; - else if (memcmp(ptr, "failed", 5) == 0) - { - PMSGWITHLEN buffptr; - arqstate = 5; - - if (STREAM->Connecting) - { - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connect Failed\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - } - } - - Debugprintf("%d arq_session_state %d", TNC->Port, arqstate); - } - - - ptr = getJSONValue(Msg, "\"info\""); - - if (strcmp(ptr, "[]") != 0) - { - - processJSONINFO(TNC, ptr, farCall, snr); - Debugprintf("%d %s %s", TNC->Port, ptr, farCall); - } - - return; - } - -// {"COMMAND":"RX_BUFFER","DATA-ARRAY":[],"EOF":"EOF"} -/* {"COMMAND":"RX_BUFFER","DATA-ARRAY":[{"DXCALLSIGN":"GM8BPQ","DXGRID":"","TIMESTAMP":1642579504, -"RXDATA":[{"dt":"f","fn":"main.js","ft":"text\/javascript" -,"d":"data:text\/javascript;base64,Y29uc3Qge.....9KTsK","crc":"123123123"}]}],"EOF":"EOF"} - - - -{"arq":"received","uuid":"a1346319-6eb0-42aa-b5a0-c9493c8ccdca","timestamp":1645812393,"dxcallsign":"G8BPQ-2","dxgrid":"","data":"QyBHOEJQUS0yIEc4QlBRLTIgRzhCUFEtMiA="} -{"ptt":"True"} - - -*/ - if (memcmp(Msg, "{\"arq\":\"received\"", 17) == 0) - { - int NewLen; - char * ptr, *ptr2, *Type; - char * Call = 0; - char * myCall = 0; - - Msg += 17; - - ptr = getJSONValue(Msg, "\"data\""); - Type = ++ptr; - - // Decode Base64 - - // FreeData replacs / with \/ so need to undo - - ptr2 = strstr(Type, "\\/"); - - while (ptr2) - { - memmove(ptr2, ptr2 + 1, strlen(ptr2)); - ptr2 = strstr(ptr2, "\\/"); - } - - Len = strlen(Type) - 1; - - // Debugprintf("RX %d %s %d", TNC->Port, FN, Len); - - ptr = ptr2 = Type; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - NewLen = (int)(ptr2 - Type); - - if (*(ptr-1) == '=') - NewLen--; - - if (*(ptr-2) == '=') - NewLen--; - - Type[NewLen] = 0; - - myCall = getJSONValue(Msg, "\"mycallsign\""); - Call = getJSONValue(Msg, "\"dxcallsign\""); - - if (Call) - { - Call++; - strlop(Call, '"'); - } - - if (myCall) - { - myCall++; - strlop(myCall, '"'); - } - - - FreeDataProcessTNCMessage(TNC, Call, Type, NewLen); - - return; - } - - if (memcmp(Msg, "{\"COMMAND\":\"RX_MSG_BUFFER\"", 26) == 0) - { - char * Next, * This; - - Msg += 26; - ptr = getJSONValue(Msg, "\"EOF\""); - ptr = getJSONValue(Msg, "\"DATA-ARRAY\""); - - This = ptr; - - if (This[1] == '{') // Array of objects - { - This++; - do { - Next = getObjectFromArray(This); - ProcessMessageObject(TNC, This); - This = Next; - } while (Next && Next[0] == '{'); - - // Delete from TNC - - SendTNCCommand(TNC, "SET", "DEL_RX_MSG_BUFFER"); - } - - - return; - } - Debugprintf(Msg); -} - -int FreeDataConnect(struct TNCINFO * TNC, char * Call) -{ - char Connect[] = "{\"type\" : \"arq\", \"command\": \"connect\" , \"dxcallsign\": \"%s\"}\n"; - char Msg[128]; - int Len; - - Len = sprintf(Msg, Connect, Call); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - -int FreeDataDisconnect(struct TNCINFO * TNC) -{ - char Disconnect[] = "{\"type\" : \"arq\", \"command\": \"disconnect\"}\n"; - char Msg[128]; - int Len; - -// return FreeDataSendCommand(TNC, "D"); - - Len = sprintf(Msg, Disconnect); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - -int FreeDataSendCommand(struct TNCINFO * TNC, char * Msg) -{ - // Commands are simulated as Messages to the remote BPQ. The TNC itself does not handle any commands - - // First Byte of MSG is a Type - Command or Data. MSG has a limited character set Use =xx for Now. - - // Current Types - C = Connect, D = Disconnect, I = info - - SendAsRaw(TNC, TNC->FreeDataInfo->farCall, TNC->FreeDataInfo->ourCall, Msg, strlen(Msg)); - return 0; -} - -void FreeDataProcessDaemonMsg(struct TNCINFO * TNC) -{ - int InputLen, MsgLen; - char * ptr; - int OpenBraces; - int CloseBraces; - char c; - - - // shouldn't get several messages per packet, as each should need an ack - // May get message split over packets - - if (TNC->InputLen > 8000) // Shouldnt have packets longer than this - TNC->InputLen=0; - - InputLen=recv(TNC->TCPSock, &TNC->ARDOPBuffer[TNC->InputLen], 8191 - TNC->InputLen, 0); - - if (InputLen == 8191) - c = 0; - - - if (InputLen == 0 || InputLen == SOCKET_ERROR) - { - // Does this mean closed? - - closesocket(TNC->TCPSock); - - TNC->TCPSock = 0; - - TNC->DAEMONCONNECTED = FALSE; - TNC->Streams[0].ReportDISC = TRUE; - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - return; - } - - TNC->InputLen += InputLen; - -loop: - TNC->ARDOPBuffer[TNC->InputLen] = 0; // So we cat use string functions - - // Message should be json. We know the format, so don't need a general parser, but need to know if complete. - // I think counting { and } and stopping if equal should work; - - - if (TNC->ARDOPBuffer[0] != '{') - { - TNC->InputLen = 0; - return; - } - - ptr = &TNC->ARDOPBuffer[0]; - - OpenBraces = 0; - CloseBraces = 0; - - while (c = *(ptr++)) - { - if (c == '{') - OpenBraces ++; - else if (c == '}') - CloseBraces ++; - - if (OpenBraces == CloseBraces) - { - MsgLen = ptr - (char * )TNC->ARDOPBuffer; - - ProcessDAEMONJSON(TNC, TNC->ARDOPBuffer, MsgLen); - - if (TNC->InputLen == 0 || *ptr == 0) - { - TNC->InputLen = 0; - return; - } - - // More in buffer - - memmove(TNC->ARDOPBuffer, ptr, TNC->InputLen - MsgLen); - - TNC->InputLen -= MsgLen; - goto loop; - } - - } - // Message Incomplete - wait for rest; -} - - - - - - -void FreeDataProcessTNCMsg(struct TNCINFO * TNC) -{ - int DataInputLen, MsgLen; - char * ptr, * endptr; - - // May get message split over packets or multiple messages per packet - - // A complete file transfer arrives as one message, so can bw very long - - - if (TNC->DataInputLen > MAXRXSIZE) // Shouldnt have packets longer than this - TNC->DataInputLen=0; - - DataInputLen = recv(TNC->TCPDataSock, &TNC->ARDOPDataBuffer[TNC->DataInputLen], MAXRXSIZE - TNC->DataInputLen, 0); - - if (DataInputLen == 0 || DataInputLen == SOCKET_ERROR) - { - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - closesocket(TNC->TCPDataSock); - - TNC->TCPDataSock = 0; - - TNC->TNCCONNECTED = FALSE; - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - return; - } - - TNC->DataInputLen += DataInputLen; - - TNC->ARDOPDataBuffer[TNC->DataInputLen] = 0; // So we cat use string functions - - // Message should be json. We know the format, so don't need a general parser, but need to know if complete. - // I think counting { and } and stopping if equal should work; - -// Debugprintf(TNC->ARDOPDataBuffer); - - //I think now messages end with LF - -loop: - - endptr = strchr(TNC->ARDOPDataBuffer, 10); - - if (endptr == 0) - return; - - *(endptr) = 0; - - if (TNC->ARDOPDataBuffer[0] != '{') - { - TNC->DataInputLen = 0; - return; - } - - ptr = &TNC->ARDOPDataBuffer[0]; - - MsgLen = endptr - ptr; - - ProcessTNCJSON(TNC, ptr, MsgLen); - - // MsgLen doesnt include lf - - MsgLen++; - - if (TNC->DataInputLen == MsgLen) - { - TNC->DataInputLen = 0; - return; - } - - // More in buffer - - ptr += MsgLen; - TNC->DataInputLen -= MsgLen; - - memmove(TNC->ARDOPDataBuffer, ptr, TNC->DataInputLen + 1); - - goto loop; - - // Message Incomplete - wait for rest; -} - - - -VOID FreeDataThread(void * portptr); - -int ConnecttoFreeData(int port) -{ - _beginthread(FreeDataThread, 0, (void *)(size_t)port); - - return 0; -} - -static SOCKADDR_IN sinx; -static SOCKADDR_IN rxaddr; - - -VOID FreeDataThread(void * portptr) -{ - // FreeData TNC has two sessions, not sure why! - - // Messages are JSON encapulated - // Opens deamon socket. TNC socket is only available once Start TNC command sent - // Looks for data on socket(s) - - int port = (int)(size_t)portptr; - char Msg[255]; - int err, i, ret; - u_long param=1; - BOOL bcopt=TRUE; - struct hostent * HostEnt; - struct TNCINFO * TNC = TNCInfo[port]; - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - - if (TNC->HostName == NULL) - return; - - TNC->BusyFlags = 0; - - TNC->DAEMONCONNECTING = TRUE; - - Sleep(3000); // Allow init to complete - -// printf("Starting FreeDATA Thread\n"); - -// if on Windows and Localhost see if TNC is running - -#ifdef WIN32 - - if (strcmp(TNC->HostName, "127.0.0.1") == 0) - { - // can only check if running on local host - - TNC->PID = GetListeningPortsPID(TNC->destaddr.sin_port); - - if (TNC->PID == 0) - goto TNCNotRunning; - - // Get the File Name in case we want to restart it. - - if (TNC->ProgramPath == NULL) - { - if (GetModuleFileNameExPtr) - { - HANDLE hProc; - char ExeName[256] = ""; - - hProc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, TNC->PID); - - if (hProc) - { - GetModuleFileNameExPtr(hProc, 0, ExeName, 255); - CloseHandle(hProc); - - TNC->ProgramPath = _strdup(ExeName); - } - } - } - goto TNCRunning; - } - -#endif - -TNCNotRunning: - - // Not running or can't check, restart if we have a path - -/* if (TNC->ProgramPath) - { - Consoleprintf("Trying to (re)start TNC %s", TNC->ProgramPath); - - if (RestartTNC(TNC)) - CountRestarts(TNC); - - Sleep(TNC->AutoStartDelay); - } -*/ -TNCRunning: - - if (TNC->Alerted == FALSE) - { - sprintf(TNC->WEB_COMMSSTATE, "Connecting to Daemon"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - - TNC->destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - TNC->Datadestaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - - if (TNC->destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - { - TNC->DAEMONCONNECTING = FALSE; - sprintf(Msg, "Resolve Failed for FreeData Host - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - return; // Resolve failed - } - memcpy(&TNC->destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - memcpy(&TNC->Datadestaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - -// closesocket(TNC->TCPDataSock); -// closesocket(TNC->TCPSock); - - TNC->TCPDataSock=socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for FreeData TNC socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->DAEMONCONNECTING = FALSE; - return; - } - - TNC->TCPSock = socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for FreeData Data Daemon socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->DAEMONCONNECTING = FALSE; - closesocket(TNC->TCPDataSock); - - return; - } - - setsockopt(TNC->TCPSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(TNC->TCPSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - // Connect Daemon Port - - if (connect(TNC->TCPSock,(LPSOCKADDR) &TNC->Datadestaddr,sizeof(TNC->Datadestaddr)) == 0) - { - // - // Connected successful - // - } - else - { - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - i=sprintf(Msg, "Connect Failed for FreeData Daemon socket - error code = %d\r\n", err); - WritetoConsole(Msg); - sprintf(TNC->WEB_COMMSSTATE, "Connection to Daemon failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->Alerted = TRUE; - } - - closesocket(TNC->TCPSock); - TNC->TCPSock = 0; - TNC->DAEMONCONNECTING = FALSE; - - RestartTNC(TNC); - return; - } - - Sleep(1000); - - TNC->LastFreq = 0; - - TNC->DAEMONCONNECTING = FALSE; - TNC->DAEMONCONNECTED = TRUE; - TNC->BusyFlags = 0; - TNC->InputLen = 0; - TNC->Alerted = FALSE; - - TNC->Alerted = TRUE; - - sprintf(TNC->WEB_COMMSSTATE, "Connected to FreeData Daemon"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - sprintf(Msg, "Connected to FreeData Daemon Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - - #ifndef LINBPQ -// FreeSemaphore(&Semaphore); - Sleep(1000); // Give VARA time to update Window title -// EnumWindows(EnumVARAWindowsProc, (LPARAM)TNC); -// GetSemaphore(&Semaphore, 52); -#endif - - while (TNC->DAEMONCONNECTED || TNC->TNCCONNECTED) - { - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - if (TNC->DAEMONCONNECTED) - FD_SET(TNC->TCPSock,&readfs); - - if (TNC->TCPSock) - FD_SET(TNC->TCPSock,&errorfs); - - if (TNC->TNCCONNECTED) - FD_SET(TNC->TCPDataSock,&readfs); - -// FD_ZERO(&writefs); - -// if (TNC->BPQtoWINMOR_Q) FD_SET(TNC->TCPSock,&writefs); // Need notification of busy clearing - - if (TNC->TNCCONNECTING || TNC->TNCCONNECTED) FD_SET(TNC->TCPDataSock,&errorfs); - - timeout.tv_sec = 90; - timeout.tv_usec = 0; // We should get messages more frequently that this - - ret = select((int)TNC->TCPSock + 1, &readfs, NULL, &errorfs, &timeout); - - if (ret == SOCKET_ERROR) - { - Debugprintf("FreeData Select failed %d ", WSAGetLastError()); - goto Lost; - } - if (ret > 0) - { - // See what happened - - if (FD_ISSET(TNC->TCPDataSock, &readfs)) - { - GetSemaphore(&Semaphore, 52); - FreeDataProcessTNCMsg(TNC); - FreeSemaphore(&Semaphore); - } - - if (FD_ISSET(TNC->TCPSock, &readfs)) - { - GetSemaphore(&Semaphore, 52); - FreeDataProcessDaemonMsg(TNC); - FreeSemaphore(&Semaphore); - } - - if (FD_ISSET(TNC->TCPDataSock, &errorfs)) - { -Lost: - sprintf(Msg, "FreeData Daemon Connection lost for Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to Daemon lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->TNCCONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - closesocket(TNC->TCPDataSock); - TNC->TCPDataSock = 0; - } - - if (FD_ISSET(TNC->TCPSock, &errorfs)) - { - sprintf(Msg, "FreeData Daemon Connection lost for Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to Daemon lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->DAEMONCONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - closesocket(TNC->TCPSock); - TNC->TCPSock = 0; - } - continue; - } - else - { - } - } - - if (TNC->TCPDataSock) - { - shutdown(TNC->TCPDataSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPDataSock); - } - - if (TNC->TCPSock) - { - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPSock); - } - - sprintf(Msg, "FreeData Thread Terminated Port %d\r\n", TNC->Port); - WritetoConsole(Msg); -} - -void ConnectTNCPort(struct TNCINFO * TNC) -{ - char Msg[255]; - int err; - int bcopt = TRUE; - - TNC->TNCCONNECTING = TRUE; - - TNC->TCPDataSock = socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - sprintf(Msg, "Socket Failed for FreeData TNC socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->TNCCONNECTING = FALSE; - return; - } - - setsockopt(TNC->TCPDataSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(TNC->TCPDataSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - if (connect(TNC->TCPDataSock,(LPSOCKADDR) &TNC->destaddr,sizeof(TNC->destaddr)) == 0) - { - // Connected successful - - sprintf(TNC->WEB_COMMSSTATE, "Connected to FreeData TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->TNCCONNECTING = FALSE; - TNC->TNCCONNECTED = TRUE; - TNC->Alerted = FALSE; - return; - } - - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - sprintf(Msg, "Connect Failed for FreeData TNC socket - error code = %d Port %d\n", - err, htons(TNC->destaddr.sin_port)); - - WritetoConsole(Msg); - TNC->Alerted = TRUE; - TNC->TNCCONNECTING = FALSE; - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - - closesocket(TNC->TCPDataSock); - - TNC->TCPDataSock = 0; - TNC->TNCCONNECTING = FALSE; - return; -} - diff --git a/FreeDATA.c.bak b/FreeDATA.c.bak deleted file mode 100644 index a7b5b1d..0000000 --- a/FreeDATA.c.bak +++ /dev/null @@ -1,4631 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// Interface to allow G8BPQ switch to use FreeData TNC - - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include - -#ifndef WIN32 -#ifndef MACBPQ -#include -#endif -#endif - -#include "CHeaders.h" -#include "bpq32.h" -#include "tncinfo.h" - -#define SD_BOTH 0x02 - -#define FREEDATABUFLEN 16384 // TCP buffer size - -int KillTNC(struct TNCINFO * TNC); -static int RestartTNC(struct TNCINFO * TNC); - -int (WINAPI FAR *GetModuleFileNameExPtr)(); -extern int (WINAPI FAR *EnumProcessesPtr)(); -static int Socket_Data(int sock, int error, int eventcode); -VOID MoveWindows(struct TNCINFO * TNC); -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen); -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); -VOID SendInitScript(struct TNCINFO * TNC); -int ProcessEscape(UCHAR * TXMsg); -static void SendPoll(struct TNCINFO * TNC); -void SendMode(struct TNCINFO * TNC); -static int ConnecttoFreeData(int port); -void ConnectTNCPort(struct TNCINFO * TNC); -int FreeDataSendCommand(struct TNCINFO * TNC, char * data); -static void SendPing(struct TNCINFO * TNC, char * Call); -static void SendCQ(struct TNCINFO * TNC); -char * stristr (char *ch1, char *ch2); -int zEncode(unsigned char * in, unsigned char * out, int len, unsigned char * Banned); -static void SendDataMsg(struct TNCINFO * TNC, char * Call, char * Msg, int Len); -static int SendAsRaw(struct TNCINFO * TNC, char * Call, char * myCall, char * Msg, int Len); -static int SendAsFile(struct TNCINFO * TNC, char * Call, char * Msg, int Len); -char * byte_base64_encode(char *str, int len); -void xdecodeblock( unsigned char in[4], unsigned char out[3] ); -void FlushData(struct TNCINFO * TNC); -void CountRestarts(struct TNCINFO * TNC); -void StopTNC(struct TNCINFO * TNC); -int FreeDataConnect(struct TNCINFO * TNC, char * Call); -int FreeDataDisconnect(struct TNCINFO * TNC); -int FreeGetData(struct TNCINFO * TNC); -static void SendBeacon(struct TNCINFO * TNC, int Interval); -void buildParamString(struct TNCINFO * TNC, char * line); - -static char ClassName[]="FREEDATASTATUS"; -static char WindowTitle[] = "FreeData Modem"; -static int RigControlRow = 205; - -#ifndef WIN32 -#include -#define MAXPNAMELEN 32 -#else -#include -#endif - -extern char * PortConfig[33]; -extern int SemHeldByAPI; - -static RECT Rect; - -extern struct TNCINFO * TNCInfo[41]; // Records are Malloc'd - -static int ProcessLine(char * buf, int Port); - -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - -#define MAXRXSIZE 512000 // Sets max size for file transfer (less base64 overhead - -int CaptureCount = 0; -int PlaybackCount = 0; - -int CaptureIndex = -1; // Card number -int PlayBackIndex = -1; - - - -char CaptureNames[16][MAXPNAMELEN + 2] = { "" }; -char PlaybackNames[16][MAXPNAMELEN + 2] = { "" }; - - -#ifdef WIN32 - -#include - -#pragma comment(lib, "winmm.lib") - -WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 12000, 24000, 2, 16, 0 }; - -WAVEOUTCAPS pwoc; -WAVEINCAPS pwic; - - -char * CaptureDevices = NULL; -char * PlaybackDevices = NULL; - -HWAVEOUT hWaveOut = 0; -HWAVEIN hWaveIn = 0; - -#endif - - -char * gen_uuid() -{ - char v[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - int i; - - //3fb17ebc-bc38-4939-bc8b-74f2443281d4 - //8 dash 4 dash 4 dash 4 dash 12 - - static char buf[37] = {0}; - - //gen random for all spaces because lazy - for (i = 0; i < 36; ++i) - { - buf[i] = v[rand()%16]; - } - - //put dashes in place - buf[8] = '-'; - buf[13] = '-'; - buf[18] = '-'; - buf[23] = '-'; - - //needs end byte - buf[36] = '\0'; - - return buf; -} - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC = TNCInfo[Port]; - char errbuf[256]; - - strcpy(errbuf, buf); - - ptr = strtok(buf, " \t\n\r"); - - if (ptr == NULL) return (TRUE); - - if (*ptr =='#') return (TRUE); // comment - - if (*ptr ==';') return (TRUE); // comment - - - if (_stricmp(buf, "ADDR")) - return FALSE; // Must start with ADDR - - ptr = strtok(NULL, " \t\n\r"); - - BPQport = Port; - p_ipad = ptr; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->FreeDataInfo = zalloc(sizeof(struct FreeDataINFO)); - -// TNC->FreeDataInfo->useBaseCall = 1; // Default - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - if (p_ipad == NULL) - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - WINMORport = atoi(p_port); - - TNC->TCPPort = WINMORport; - - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(WINMORport); - - TNC->HostName = malloc(strlen(p_ipad)+1); - - if (TNC->HostName == NULL) return TRUE; - - strcpy(TNC->HostName,p_ipad); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - } - - if (ptr) - { - if (_memicmp(ptr, "PATH", 4) == 0) - { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - } - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "CAPTURE", 7) == 0) - { - TNC->FreeDataInfo->Capture = _strupr(_strdup(&buf[8])); - strlop(TNC->FreeDataInfo->Capture, 13); - } - else if (_memicmp(buf, "PLAYBACK", 8) == 0) - { - TNC->FreeDataInfo->Playback = _strupr(_strdup(&buf[9])); - strlop(TNC->FreeDataInfo->Playback, 13); - } - - else if (_memicmp(buf, "LOGDIR ", 7) == 0) - TNC->LogPath = _strdup(&buf[7]); - - else if (_memicmp(buf, "HAMLIBHOST", 10) == 0) - { - TNC->FreeDataInfo->hamlibHost = _strdup(&buf[11]); - strlop(TNC->FreeDataInfo->hamlibHost, 13); - } - - else if (_memicmp(buf, "TuningRange", 11) == 0) - TNC->FreeDataInfo->TuningRange = atoi(&buf[12]); - - else if (_memicmp(buf, "TXLevel", 6) == 0) - TNC->FreeDataInfo->TXLevel = atoi(&buf[7]); - - else if (_memicmp(buf, "Explorer", 8) == 0) - TNC->FreeDataInfo->Explorer = atoi(&buf[9]); - - - else if (_memicmp(buf, "LimitBandWidth", 14) == 0) - TNC->FreeDataInfo->LimitBandWidth = atoi(&buf[15]); - - else if (_memicmp(buf, "HAMLIBPORT", 10) == 0) - TNC->FreeDataInfo->hamlibPort = atoi(&buf[11]); - - else if (_memicmp(buf, "USEBASECALL", 11) == 0) - TNC->FreeDataInfo->useBaseCall = atoi(&buf[12]); - - else if (_memicmp(buf, "RXDIRECTORY", 11) == 0) - { - TNC->FreeDataInfo->RXDir = _strdup(&buf[12]); - strlop(TNC->FreeDataInfo->RXDir, 13); - } - - else if (standardParams(TNC, buf) == FALSE) - strcat(TNC->InitScript, buf); - - } - - return (TRUE); -} - -char * Config; -static char * ptr1, * ptr2; - -int FreeDataGetLine(char * buf) -{ -loop: - - if (ptr2 == NULL) - return 0; - - memcpy(buf, ptr1, ptr2 - ptr1 + 2); - buf[ptr2 - ptr1 + 2] = 0; - ptr1 = ptr2 + 2; - ptr2 = strchr(ptr1, 13); - - if (buf[0] < 0x20) goto loop; - if (buf[0] == '#') goto loop; - if (buf[0] == ';') goto loop; - - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; - buf[strlen(buf)] = 13; - - return 1; -} - -BOOL FreeDataReadConfigFile(int Port, int ProcLine()) -{ - char buf[256],errbuf[256]; - - Config = PortConfig[Port]; - - if (Config) - { - // Using config from bpq32.cfg - - if (strlen(Config) == 0) - { - return TRUE; - } - - ptr1 = Config; - ptr2 = strchr(ptr1, 13); - - if (!ProcLine(buf, Port)) - { - WritetoConsoleLocal("\n"); - WritetoConsoleLocal("Bad config record "); - WritetoConsoleLocal(errbuf); - } - } - else - { - sprintf(buf," ** Error - No Configuration info in bpq32.cfg"); - WritetoConsoleLocal(buf); - } - - return (TRUE); -} - - - -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - - - -#define MAXBPQPORTS 32 - -static time_t ltime; - - - -static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen) -{ - if (TNC->hDevice) - { - // FreeData mode. Queue to Hostmode driver - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = EncLen; - memcpy(&buffptr->Data[0], Encoded, EncLen); - - C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); - TNC->Streams[Stream].FramesQueued++; - - return; - } -} - - -VOID FreeDataChangeMYC(struct TNCINFO * TNC, char * Call) -{ - UCHAR TXMsg[100]; - int datalen; - - if (strcmp(Call, TNC->CurrentMYC) == 0) - return; // No Change - - strcpy(TNC->CurrentMYC, Call); - - datalen = sprintf(TXMsg, "MYCALL %s\r", Call); -// FreeDataSendCommand(TNC, TXMsg); -} - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int datalen; - PMSGWITHLEN buffptr; -// char txbuff[500]; - unsigned int txlen = 0; - UCHAR * TXMsg; - - size_t Param; - int Stream = 0; - HKEY hKey=0; - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct ScanEntry * Scan; - - if (TNC == NULL) - return 0; // Port not defined - - switch (fn) - { - case 7: - - // 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances - - SendPoll(TNC); - - // Check for buffered data to send - - if (TNC->FreeDataInfo->toSendTimeout) - { - TNC->FreeDataInfo->toSendTimeout--; - if (TNC->FreeDataInfo->toSendTimeout <= 0) - FlushData(TNC); - } - - return 0; - - case 1: // poll - -// FreeDataCheckRX(TNC); - - if (TNC->TNCCONNECTED == FALSE && TNC->TNCCONNECTING == FALSE) - { - // See if time to reconnect - - time(<ime); - if (ltime - TNC->lasttime > 19 ) - { - TNC->lasttime = ltime; - ConnecttoFreeData(port); - } - } - - - while (TNC->PortRecord->UI_Q) - { - int datalen; - char * Buffer; - char FECMsg[512]; - char Call[12] = " "; - struct _MESSAGE * buffptr; - int CallLen; - char * ptr = FECMsg; - - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - -/* if (TNC->CONNECTED == 0 || - TNC->Streams[0].Connecting || - TNC->Streams[0].Connected) - { - // discard if TNC not connected or sesison active - - ReleaseBuffer(buffptr); - continue; - } -*/ - datalen = buffptr->LENGTH - MSGHDDRLEN; - Buffer = &buffptr->DEST[0]; // Raw Frame - Buffer[datalen] = 0; - - // Frame has ax.25 format header. Convert to Text - - CallLen = ConvFromAX25(Buffer + 7, Call); // Origin - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - *ptr++ = '!'; - - CallLen = ConvFromAX25(Buffer, Call); // Dest - memcpy(ptr, Call, CallLen); - ptr += CallLen; - - Buffer += 14; // TO Digis - datalen -= 14; - - while ((Buffer[-1] & 1) == 0) - { - *ptr++ = ','; - CallLen = ConvFromAX25(Buffer, Call); - memcpy(ptr, Call, CallLen); - ptr += CallLen; - Buffer += 7; // End of addr - datalen -= 7; - } - - *ptr++ = '_'; - *ptr++ = 'U'; // UI Frame - *ptr++ = 0; // delimit calls - - if (Buffer[0] == 3) // UI - { - Buffer += 2; - datalen -= 2; - } - -// FreeDataSendSingleData(TNC, FECMsg, Buffer, datalen); - - ReleaseBuffer(buffptr); - } - - - if (TNC->DiscPending) - { - TNC->DiscPending--; - - if (TNC->DiscPending == 0) - { - // Too long in Disc Pending - Kill and Restart TNC - } - } - - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - { - // Send the DISCONNECT - - FreeDataDisconnect(TNC); - strcpy(TNC->WEB_TNCSTATE, "Disconnecting"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - } - } - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && STREAM->Attached == 0) - { - // New Attach - - int calllen; - char Msg[80]; - - Debugprintf("FreeData New Attach Stream %d", Stream); - - STREAM->Attached = TRUE; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, STREAM->MyCall); - TNC->Streams[Stream].MyCall[calllen] = 0; - - - FreeDataChangeMYC(TNC, TNC->Streams[0].MyCall); - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Stop Scanning - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command(-1, Msg); - } - - if (STREAM->Attached) - CheckForDetach(TNC, Stream, STREAM, TidyClose, ForcedClose, CloseComplete); - - } - - // See if any frames for this port - - for (Stream = 0; Stream <= 2; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->BPQtoPACTOR_Q) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)Q_REM(&STREAM->BPQtoPACTOR_Q); - UCHAR * data = &buffptr->Data[0]; - STREAM->FramesQueued--; - txlen = (int)buffptr->Len; - - SendAsFile(TNC, TNC->FreeDataInfo->farCall, data, txlen); - } - - if (STREAM->PACTORtoBPQ_Q != 0) - { - buffptr = (PMSGWITHLEN)Q_REM(&STREAM->PACTORtoBPQ_Q); - - datalen = (int)buffptr->Len; - - buff->PORT = Stream; // Compatibility with Kam Driver - buff->PID = 0xf0; - memcpy(&buff->L2DATA, &buffptr->Data[0], datalen); // Data goes to + 7, but we have an extra byte - datalen += sizeof(void *) + 4; - - PutLengthinBuffer(buff, datalen); - - ReleaseBuffer(buffptr); - - return (1); - } - - if (STREAM->ReportDISC) // May need a delay so treat as a counter - { - STREAM->ReportDISC--; - if (STREAM->ReportDISC == 0) - { - buff->PORT = Stream; -// STREAM->Connected = 0; -// STREAM->Attached = 0; - return -1; - } - } - } - return (0); - - case 2: // send - - Stream = buff->PORT; - - if (!TNC->TNCCONNECTED) - { - // Send Error Response - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = 36; - memcpy(&buffptr->Data[0], "No Connection to TNC\r", 36); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return 0; // Don't try if not connected - } - - STREAM = &TNC->Streams[Stream]; - - if (TNC->SwallowSignon) - { - TNC->SwallowSignon = FALSE; // Discard *** connected - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - TXMsg = &buff->L2DATA[0]; - TXMsg[txlen] = 0; - - if (STREAM->Connected) - { - STREAM->PacketsSent++; - - SendDataMsg(TNC, TNC->FreeDataInfo->farCall, buff->L2DATA, txlen); - return 1; - } - - if (TNC->FreeDataInfo->Chat) - { - // Chat Mode - Send to other end - - char reply[512] = "m"; - char * p; - int Len; - - if (_stricmp(TXMsg, "/ex\r") == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - TNC->FreeDataInfo->Chat = 0; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Chat with %s ended. \r", TNC->FreeDataInfo->ChatCall); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - // Send as chat message - - //m�;send_message�;123�;64730c5c-d32c-47b4-9b11-c958fd07a185�;hhhhhhhhhhhhhhhhhh - //�;�;plain/text�; - - strlop(TXMsg, 13); - - strcpy(&reply[2], ";send_message"); - strcpy(&reply[16], ";123"); - reply[21] = ';'; - strcpy(&reply[22], gen_uuid()); - sprintf(&reply[59], ";%s\n", TXMsg); - - p = strchr(&reply[59], 0); - - p[1] = ';'; - strcpy(&p[3], ";plain/text"); - p[15] = ';'; - - Len = &p[16] - reply; - - SendAsRaw(TNC, TNC->FreeDataInfo->ChatCall, "", reply, Len); - - return 0; - } - - - - if (_memicmp(&buff->L2DATA[0], "D\r", 2) == 0 || _memicmp(&buff->L2DATA[0], "BYE\r", 4) == 0) - { - STREAM->ReportDISC = TRUE; // Tell Node - TNC->FreeDataInfo->Chat = 0; - return 0; - } - - - // See if Local command (eg RADIO) - - if (_memicmp(&buff->L2DATA[0], "RADIO ", 6) == 0) - { - sprintf(&buff->L2DATA[0], "%d %s", TNC->Port, &buff->L2DATA[6]); - - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK->CIRCUITINDEX, &buff->L2DATA[0])) - { - } - else - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return 1; // No buffers, so ignore - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", &buff->L2DATA[0]); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return 1; - } - - if (_memicmp(&buff->L2DATA[0], "OVERRIDEBUSY", 12) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - TNC->OverrideBusy = TRUE; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} OK\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - if (_memicmp(&buff->L2DATA[0], "PING ", 5) == 0) - { - char * Call = &buff->L2DATA[5]; - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - strlop(Call, 13); - strlop(Call, ' '); - SendPing(TNC, _strupr(Call)); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Ping Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "CQ", 2) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - SendCQ(TNC); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} CQ Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - - if (_memicmp(&buff->L2DATA[0], "CQ", 2) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - SendCQ(TNC); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} CQ Sent\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "TXLEVEL ", 8) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - int Level = atoi(&buff->L2DATA[8]); - char TXL[] = "{\"type\" : \"set\", \"command\" : \"tx_audio_level\", \"value\": \"%d\"}\n"; - char Message[256]; - int Len, ret; - - Len = sprintf(Message, TXL, Level); - Debugprintf(Message); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} TXLevel Set\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return 0; - } - - if (_memicmp(&buff->L2DATA[0], "SENDTEST", 8) == 0) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - char TXF[] = "{\"type\" : \"set\", \"command\" : \"send_test_frame\"}\n"; - char Message[256]; - int Len, ret; - - Len = sprintf(Message, TXF); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Test Frame Requested\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return 0; - } - - if (_memicmp(&buff->L2DATA[0], "CHAT ", 5) == 0) - { - char * Call = &buff->L2DATA[5]; - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - strlop(Call, 13); - strlop(Call, ' '); - - TNC->FreeDataInfo->Chat = 1; - memcpy(TNC->FreeDataInfo->ChatCall, _strupr(Call), 10); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Chat with %s. Enter /ex to exit\r", Call); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - - if (_memicmp(&TXMsg[0], "BEACON ", 7) == 0) - { - int Interval = atoi(&TXMsg[7]); - - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - SendBeacon(TNC, Interval); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Ok\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - return 0; - } - - - - - // See if a Connect Command. - - if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect - { - char Connect[80]; - char loppedCall[10]; - char toCall[10]; - - char * ptr = strchr(&buff->L2DATA[2], 13); - - if (ptr) - *ptr = 0; - - // FreeDATA doesn't have the concept of a connection, so need to simulate it between the nodes - _strupr(&buff->L2DATA[2]); - - if (strlen(&buff->L2DATA[2]) > 9) - buff->L2DATA[11] = 0; - - strcpy(TNC->FreeDataInfo->toCall, &buff->L2DATA[2]); - strcpy(loppedCall, TNC->FreeDataInfo->toCall); - if (TNC->FreeDataInfo->useBaseCall) - strlop(loppedCall, '-'); - strcpy(TNC->FreeDataInfo->farCall, loppedCall); - - // MYCALL and Target call are end to end concepts - the TNC cam can only use one call, set at TNC start. and no SSID's - // Messages are sent at TNC level to the tnc call, so we send our tnc call to the other end - - - txlen = sprintf(Connect, "C %s %s %s ", &buff->L2DATA[2], STREAM->MyCall, TNC->FreeDataInfo->ourCall); - - // See if Busy -/* - if (InterlockedCheckBusy(TNC)) - { - // Channel Busy. Unless override set, wait - - if (TNC->OverrideBusy == 0) - { - // Save Command, and wait up to 10 secs - - sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - TNC->ConnectCmd = _strdup(Connect); - TNC->BusyDelay = TNC->BusyWait * 10; // BusyWait secs - return 0; - } - } -*/ - TNC->OverrideBusy = FALSE; - - memset(STREAM->RemoteCall, 0, 10); - strcpy(STREAM->RemoteCall, &buff->L2DATA[2]); - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - -// FreeDataSendCommand(TNC, Connect); - FreeDataConnect(TNC, STREAM->RemoteCall); - STREAM->Connecting = TRUE; - return 0; - - } - - // Normal data. Send to TNC - - // The TNC doesn't have any commands, so send error message - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "FreeData} Not connected\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - - // strlop(buff->L2DATA, 13); - // txlen = SendDataMsg(TNC, TNC->, buff->L2DATA); - // FreeDataSendData(TNC, TXMsg, txlen); - - return 0; - - case 3: - - // CHECK IF OK TO SEND (And check TNC Status) - - Stream = (int)(size_t)buff; - - // FreeData TNC can buffer unlimited data - - if (TNC->Streams[Stream].Attached == 0) - return (TNC->TNCCONNECTED != 0) << 8 | 1; - - return ((TNC->TNCCONNECTED != 0) << 8 | TNC->Streams[Stream].Disconnecting << 15); // OK - - case 5: // Close - - StopTNC(TNC); - - // Drop through - - case 4: // reinit7 - - if (TNC->TCPDataSock) - { - shutdown(TNC->TCPDataSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPDataSock); - } - - if (TNC->WeStartedTNC) - KillTNC(TNC); - - - return 0; - - case 6: // Scan Stop Interface - - Param = (size_t)buff; - - if (Param == 2) // Check Permission (Shouldn't happen) - { - Debugprintf("Scan Check Permission called on FreeDATA"); - return 1; // OK to change - } - - if (Param == 1) // Request Permission - { - if (!TNC->CONNECTED) - return 0; // No connection so no interlock - - if (TNC->ConnectPending == 0 && TNC->PTTState == 0) - { - TNC->FreeDataInfo->CONOK = 0; - TNC->GavePermission = TRUE; - return 0; // OK to Change - } - - if (TNC->ConnectPending) - TNC->ConnectPending--; // Time out if set too long - - return TRUE; - } - - if (Param == 3) // Release Permission - { - if (TNC->GavePermission) - { - TNC->GavePermission = FALSE; - if (TNC->ARDOPCurrentMode[0] != 'S') // Skip - TNC->FreeDataInfo->CONOK = 1; - - } - return 0; - } - - // Param is Address of a struct ScanEntry - - Scan = (struct ScanEntry *)buff; - return 0; - } - return 0; -} - -VOID FreeDataReleaseTNC(struct TNCINFO * TNC) -{ - // Set mycall back to Node or Port Call, and Start Scanner - - UCHAR TXMsg[1000]; - - FreeDataChangeMYC(TNC, TNC->NodeCall); - - // Start Scanner - - sprintf(TXMsg, "%d SCANSTART 15", TNC->Port); - - Rig_Command(-1, TXMsg); - - ReleaseOtherPorts(TNC); - -} - -VOID FreeDataSuspendPort(struct TNCINFO * TNC) -{ - TNC->FreeDataInfo->CONOK = 0; -} - -VOID FreeDataReleasePort(struct TNCINFO * TNC) -{ - TNC->FreeDataInfo->CONOK = 1; -} - - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, "" - "" - "FreDATA Status" - "

FreeData Status" - "

", - TNC->Port); - - - Len += sprintf(&Buff[Len], ""); - - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); -// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
Proto State%s
Traffic%s
TNC Restarts
"); - - Len += sprintf(&Buff[Len], "", TNC->WebBuffer); - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - -#ifndef LINBPQ - -#define BGCOLOUR RGB(236,233,216) -static HBRUSH RedBrush = NULL; -HBRUSH GreenBrush; -HBRUSH BlueBrush; -static HBRUSH bgBrush = NULL; - -extern HWND ClientWnd, FrameWnd; -extern int OffsetH, OffsetW; - -extern HMENU hMainFrameMenu; -extern HMENU hBaseMenu; -extern HANDLE hInstance; - -extern HKEY REGTREE; - - -/* -static LRESULT CALLBACK PacWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - MINMAXINFO * mmi; - PAINTSTRUCT ps; - HDC hdc; - - int i; - struct TNCINFO * TNC; - - HKEY hKey; - char Key[80]; - int retCode, disp; - - for (i=0; i<41; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC->hDlg == hWnd) - break; - } - - if (TNC == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - switch (message) { - - case WM_CREATE: - - break; - - case WM_PAINT: - - hdc = BeginPaint(hWnd, &ps); - -// SelectObject(ps.hdc, RedBrush); - SelectObject(ps.hdc, GreenBrush); -// SelectObject(ps.hdc, GetStockObject(GRAY_BRUSH)); - - EndPaint(hWnd, &ps); - break; - - case WM_GETMINMAXINFO: - - if (TNC->ClientHeight) - { - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = TNC->ClientWidth; - mmi->ptMaxSize.y = TNC->ClientHeight; - mmi->ptMaxTrackSize.x = TNC->ClientWidth; - mmi->ptMaxTrackSize.y = TNC->ClientHeight; - } - - break; - - - case WM_MDIACTIVATE: - { - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - - if (TNC->hMenu) - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)TNC->hMenu, "Actions"); - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - -// SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) TNC->hMenu, (LPARAM) TNC->hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - // call DrawMenuBar after the menu items are set - DrawMenuBar(FrameWnd); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - } - - - - case WM_INITMENUPOPUP: - - if (wParam == (WPARAM)TNC->hMenu) - { - if (TNC->ProgramPath) - { - if (strstr(TNC->ProgramPath, " TNC") || strstr(TNC->ProgramPath, "ARDOP") || strstr(TNC->ProgramPath, "VARA")) - { - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_ENABLED); - - break; - } - } - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_GRAYED); - } - - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - case WINMOR_KILL: - - KillTNC(TNC); - break; - - case WINMOR_RESTART: - - KillTNC(TNC); - RestartTNC(TNC); - break; - - case WINMOR_RESTARTAFTERFAILURE: - - TNC->RestartAfterFailure = !TNC->RestartAfterFailure; - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", TNC->Port); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - RegSetValueEx(hKey,"TNC->RestartAfterFailure",0,REG_DWORD,(BYTE *)&TNC->RestartAfterFailure, 4); - RegCloseKey(hKey); - } - break; - - case ARDOP_ABORT: - - if (TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SIZING: - case WM_SIZE: - - MoveWindows(TNC); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - - case SC_RESTORE: - - TNC->Minimized = FALSE; - break; - - case SC_MINIMIZE: - - TNC->Minimized = TRUE; - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - - case WM_CTLCOLORSTATIC: - { - HDC hdcStatic = (HDC)wParam; - SetTextColor(hdcStatic, RGB(0, 0, 0)); - SetBkMode(hdcStatic, TRANSPARENT); - return (LONG)bgBrush; - } - - case WM_DESTROY: - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); -} -*/ - -#endif - - - -VOID * FreeDataExtInit(EXTPORTDATA * PortEntry) -{ - int port; - char Msg[255]; - char * ptr; - struct TNCINFO * TNC; - char * TempScript; - u_long param = 1; - int line; - int i; - - srand(time(NULL)); - - port = PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); - WritetoConsole(Msg); - - return ExtProc; - } - - if (TNC->FreeDataInfo->TuningRange == 0) - TNC->FreeDataInfo->TuningRange = 50; - - if (TNC->FreeDataInfo->TXLevel == 0) - TNC->FreeDataInfo->TXLevel = 50; - - if (TNC->AutoStartDelay == 0) - TNC->AutoStartDelay = 2000; - -#ifndef LINBPQ - - if (bgBrush == NULL) - { - bgBrush = CreateSolidBrush(BGCOLOUR); - RedBrush = CreateSolidBrush(RGB(255,0,0)); - GreenBrush = CreateSolidBrush(RGB(0,255,0)); - BlueBrush = CreateSolidBrush(RGB(0,0,255)); - } - -#endif - - Consoleprintf("FreeData Host %s %d", TNC->HostName, TNC->TCPPort); - - TNC->Port = port; - TNC->Hardware = H_FREEDATA; - - TNC->WeStartedTNC = 1; - - TNC->ARDOPDataBuffer = malloc(MAXRXSIZE); - TNC->ARDOPBuffer = malloc(FREEDATABUFLEN); - - TNC->PortRecord = PortEntry; - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - memcpy(TNC->NodeCall, MYNODECALL, 10); - else - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - memcpy(TNC->FreeDataInfo->ourCall, TNC->NodeCall, 10); - strlop(TNC->FreeDataInfo->ourCall, ' '); - if (TNC->FreeDataInfo->useBaseCall) - strlop(TNC->FreeDataInfo->ourCall, '-'); - - if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) - TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - - if (TNC->PacketChannels > 1) - TNC->PacketChannels = 1; - - PortEntry->MAXHOSTMODESESSIONS = TNC->PacketChannels + 1; - - PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only - PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream - - PortEntry->PORTCONTROL.UICAPABLE = TRUE; - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 236; - - TNC->SuspendPortProc = FreeDataSuspendPort; - TNC->ReleasePortProc = FreeDataReleasePort; - -// PortEntry->PORTCONTROL.PORTSTARTCODE = KAMStartPort; -// PortEntry->PORTCONTROL.PORTSTOPCODE = KAMStopPort; - - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - // Set Essential Params and MYCALL - - // Put overridable ones on front, essential ones on end - - TempScript = zalloc(1000); - - // cant think of any yet - - if (TNC->InitScript) - { - strcat(TempScript, TNC->InitScript); - free(TNC->InitScript); - } - - TNC->InitScript = TempScript; - - // Set MYCALL - - sprintf(Msg, "MYCALL %s\r", TNC->NodeCall); - strcat(TNC->InitScript, Msg); - - strcpy(TNC->CurrentMYC, TNC->NodeCall); - - if (TNC->WL2K == NULL) - if (PortEntry->PORTCONTROL.WL2KInfo.RMSCall[0]) // Already decoded - TNC->WL2K = &PortEntry->PORTCONTROL.WL2KInfo; - - PortEntry->PORTCONTROL.TNC = TNC; - - // Build SSID List - - if (TNC->LISTENCALLS) - { - strcpy(TNC->FreeDataInfo->SSIDList, TNC->LISTENCALLS); - } - else - { - APPLCALLS * APPL; - char Appl[11] = ""; - char * List = TNC->FreeDataInfo->SSIDList; - char * SSIDptr; - int SSID; - int Listptr; - - // list is a set of numbers separated by spaces eg 0 2 10 - - SSIDptr = strchr(TNC->NodeCall, '-'); - if (SSIDptr) - SSID = atoi(SSIDptr + 1); - else - SSID = 0; - - Listptr = sprintf(List, "%d", SSID); - - for (i = 0; i < 32; i++) - { - APPL=&APPLCALLTABLE[i]; - - if (APPL->APPLCALL_TEXT[0] > ' ') - { - char * ptr; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - - SSIDptr = strchr(Appl, '-'); - if (SSIDptr) - SSID = atoi(SSIDptr + 1); - else - SSID = 0; - - Listptr += sprintf(&List[Listptr], " %d", SSID); - } - } - List[Listptr] = 0; - } - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 520; - TNC->WebWinY = 500; - TNC->WebBuffer = zalloc(5000); - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - TNC->WEB_CHANSTATE = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_PROTOSTATE = zalloc(100); - TNC->WEB_RESTARTTIME = zalloc(100); - TNC->WEB_RESTARTS = zalloc(100); - - TNC->WEB_MODE = zalloc(20); - TNC->WEB_TRAFFIC = zalloc(100); - -#ifndef LINBPQ - - line = 6; - - if (TNC->TXFreq) - { - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow + 22, PacWndProc, 500, 450, ForcedClose); - - InitCommonControls(); // loads common control's DLL - - CreateWindowEx(0, "STATIC", "TX Tune", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNE = CreateWindowEx(0, TRACKBAR_CLASS, "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNEVAL = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE, 320,line,30,20, TNC->hDlg, NULL, hInstance, NULL); - - SendMessage(TNC->xIDC_TXTUNE, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG(-200, 200)); // min. & max. positions - - line += 22; - } - else - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 450, ForcedClose); - - CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,450,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,line,106,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,520,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,line,110,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,144,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Proto State", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_PROTOSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,line,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,116,line,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,line,20,20 , TNC->hDlg, NULL, hInstance, NULL); - CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, - 0,170,250,300, TNC->hDlg, NULL, hInstance, NULL); - - TNC->ClientHeight = 450; - TNC->ClientWidth = 500; - - TNC->hMenu = CreatePopupMenu(); - - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill Freedata TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart Freedata TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after failed Connection"); - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); - - MoveWindows(TNC); -#endif - - // Convert sound card name to index - -#ifdef WIN32 - - if (CaptureDevices == NULL) // DOn't do it again if more that one port - { - CaptureCount = waveInGetNumDevs(); - - CaptureDevices = malloc((MAXPNAMELEN + 2) * CaptureCount); - CaptureDevices[0] = 0; - - printf("Capture Devices"); - - for (i = 0; i < CaptureCount; i++) - { - waveInOpen(&hWaveIn, i, &wfx, 0, 0, CALLBACK_NULL); //WAVE_MAPPER - waveInGetDevCaps((UINT_PTR)hWaveIn, &pwic, sizeof(WAVEINCAPS)); - - if (CaptureDevices) - strcat(CaptureDevices, ","); - strcat(CaptureDevices, pwic.szPname); - Debugprintf("%d %s", i + 1, pwic.szPname); - memcpy(&CaptureNames[i][0], pwic.szPname, MAXPNAMELEN); - _strupr(&CaptureNames[i][0]); - } - - PlaybackCount = waveOutGetNumDevs(); - - PlaybackDevices = malloc((MAXPNAMELEN + 2) * PlaybackCount); - PlaybackDevices[0] = 0; - - Debugprintf("Playback Devices"); - - for (i = 0; i < PlaybackCount; i++) - { - waveOutOpen(&hWaveOut, i, &wfx, 0, 0, CALLBACK_NULL); //WAVE_MAPPER - waveOutGetDevCaps((UINT_PTR)hWaveOut, &pwoc, sizeof(WAVEOUTCAPS)); - - if (PlaybackDevices[0]) - strcat(PlaybackDevices, ","); - strcat(PlaybackDevices, pwoc.szPname); - Debugprintf("%i %s", i + 1, pwoc.szPname); - memcpy(&PlaybackNames[i][0], pwoc.szPname, MAXPNAMELEN); - _strupr(&PlaybackNames[i][0]); - waveOutClose(hWaveOut); - } - } - -#endif - - time(&TNC->lasttime); // Get initial time value - - ConnecttoFreeData(port); - TNC->FreeDataInfo->CONOK = 1; - - return ExtProc; -} - - -VOID TidyClose(struct TNCINFO * TNC, int Stream) -{ - // We don't get data acks, so can't check for bytes outstanding - - FreeDataDisconnect(TNC); -} - -VOID ForcedClose(struct TNCINFO * TNC, int Stream) -{ - FreeDataDisconnect(TNC); -} - - - -VOID CloseComplete(struct TNCINFO * TNC, int Stream) -{ - if (Stream == 0) - { - FreeDataReleaseTNC(TNC); - } -} - -VOID FreeDataAbort(struct TNCINFO * TNC) -{ - FreeDataSendCommand(TNC, "ABORT\r"); -} - -// Host Mode Stuff (we reuse some routines in SCSPactor) - -VOID FreeDataDoTermModeTimeout(struct TNCINFO * TNC) -{ - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->ReinitState == 0) - { - //Checking if in Terminal Mode - Try to set back to Term Mode - - TNC->ReinitState = 1; - return; - } - - if (TNC->ReinitState == 1) - { - // Forcing back to Term Mode - - TNC->ReinitState = 0; - return; - } - - if (TNC->ReinitState == 3) - { - return; - } -} - -static RECT Rect1 = {30, 160, 400, 195}; - -int zEncode(unsigned char * in, unsigned char * out, int len, unsigned char * Banned) -{ - // Replace forbidden chars with =xx - - unsigned char * ptr = out; - unsigned char c; - - while (len--) - { - c = *(in++); - - if (strchr(&Banned[0], c)) - { - *(out++) = '='; - *(out++) = (c >> 4) + 'A'; - *(out++) = (c & 15) + 'A'; - } - else - *(out++) = c; - } - - return (out - ptr); -} - - - -VOID FreeDataProcessTNCMessage(struct TNCINFO * TNC, char * Call, unsigned char * Msg, int Len) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * toCall, * fromCall, * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - // First Byte of Message is Type. Messages can be commands or short (<120) data packets - // Data is encoded with =xx replacing restricted chars - - Msg[Len] = 0; - - switch (Msg[0]) - { - case 'C': - - // Connect Request. C G8BPQ-10 GM8BPQ-2 (Target, Origin) - - toCall = strtok_s(&Msg[2], " ", &Context); - fromCall = strtok_s(NULL, " ", &Context); - tncCall = strtok_s(NULL, " ", &Context); - - strcpy(TNC->FreeDataInfo->farCall, tncCall); - - ConvToAX25Ex(fromCall, axcall); // Allow -T and -R SSID's for MPS - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(axcall) == FALSE) - { - Debugprintf("FreeData Call from %s rejected", fromCall); - - // Send 'd' - - Sleep(1000); - FreeDataDisconnect(TNC); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(axcall, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - Sleep(1000); - FreeDataSendCommand(TNC, "d"); - - Debugprintf("FreeDara Call from %s not in ValidCalls - rejected", Call); - return; - } - } - } - - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(toCall, Appl) == 0) - break; - } - - if (App < 32) - { - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(Call, "-T" ) || strstr(Call, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - if (!CheckAppl(TNC, AppName)) - { - Sleep(1000); - FreeDataSendCommand(TNC, "dApplication not Available"); - return; - } - } - - ProcessIncommingConnectEx(TNC, fromCall, 0, TRUE, TRUE); - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - // if connect to an application, send command - - if (AppName[0]) - { - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf(buffptr->Data, "%s\r", AppName); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - } - - TNC->ConnectPending = FALSE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, toCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - if (SESS->Frequency == 1500) - { - // try to get from WL2K record - - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - } - } - SESS->Mode = TNC->WL2KMode; - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, toCall); - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - SESS->Mode = WL2K->mode; - } - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - STREAM->Connected = TRUE; - - // Send Connect ACK - Sleep(1000); - FreeDataSendCommand(TNC, "c"); - return; - - case 'c': - - // Connect ACK - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - STREAM->Connected = TRUE; - STREAM->Connecting = FALSE; - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connected to %s\r", TNC->FreeDataInfo->toCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - - return; - - case 'D': - - // Disconnect Command - - FreeDataSendCommand(TNC, "d"); - - // Drop through to disconnect this end - - case 'd': - - // Disconnect complete (response to sending "D") - // Or connect refused in response to "C" - - if (STREAM->Connecting) - { - // Connection Refused - If there is a message, pass to appl - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - if (Msg[1]) - buffptr->Len = sprintf(buffptr->Data, "Connect Rejected - %s\r", &Msg[1]); - else - buffptr->Len = sprintf(buffptr->Data, "Connect Rejected\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - return; - } - - // Release Session - - if (STREAM->Connected) - { - // Create a traffic record - - char logmsg[120]; - time_t Duration; - - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - } - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - return; - - case 'B': - - // Was Base64, but has been expanded - just send to User - - // If len > blocksize, fragment - - Len--; - Msg++; // Remove Type - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Msg, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Msg, 256); - Len -= 256; - Msg += 256; - STREAM->BytesRXed += 256; - - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Msg, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Msg, Len); - STREAM->BytesRXed += Len; - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - return; - - case 'I': - - // Encoded Response - - // Undo = transparency - - ptr = Msg + 1; - - while (ptr = strchr(ptr, '=')) - { - // Next two chars are a hex value - - a = ptr[1] - 'A'; - b = ptr[2] - 'A'; - memmove(ptr, ptr + 2, Len); - ptr[0] = (a << 4) + b; - ptr++; - } - - buffptr = GetBuff(); - buffptr->Len = sprintf(buffptr->Data, "%s", &Msg[1]); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - return; - - case 'f': - - // FreeDATA File Transfer - - // Seems to be f null fn null data - //f.;Makefile.;.;123123123.; - { - char * FN; - time_t CRC; - int FileLen; - char Filename[256]; - FILE * fp1; - unsigned char * ptr; - char Text[64]; - int textLen; - - - if (TNC->FreeDataInfo->RXDir == NULL) - { - Debugprintf("FreeDATA RXDIRECTORY not set - file transfer ignored"); - return; - } - - FN = _strdup(&Msg[3]); - ptr = &Msg[4] + strlen(FN); - - ptr = ptr + strlen(ptr) + 2; - CRC = atoi(ptr); - ptr = ptr + strlen(ptr) + 2; - - FileLen = Len - (ptr - Msg); - - sprintf(Filename, "%s\\%s", TNC->FreeDataInfo->RXDir, FN); - - fp1 = fopen(Filename, "wb"); - - if (fp1) - { - fwrite(ptr, 1, FileLen, fp1); - fclose(fp1); - textLen = sprintf(Text, "File %s received from %s \r", FN, Call); - WritetoTrace(TNC, Text, textLen); - } - else - Debugprintf("FreeDATA - File %s create failed %s", Filename); - - - free(FN); - return; - - } - - - } - - if (STREAM->Attached == 0) - return; - - - buffptr = GetBuff(); - - if (buffptr == 0) - { - return; // No buffers, so ignore - } - - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", Msg); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - -} - - -VOID FreeDataProcessNewConnect(struct TNCINFO * TNC, char * fromCall, char * toCall) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - strcpy(TNC->FreeDataInfo->farCall, fromCall); - - ConvToAX25Ex(fromCall, axcall); // Allow -T and -R SSID's for MPS - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(axcall) == FALSE) - { - Debugprintf("FreeData Call from %s rejected", fromCall); - - // Send 'd' - - Sleep(1000); - FreeDataDisconnect(TNC); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(axcall, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - Sleep(1000); - FreeDataDisconnect(TNC); - - Debugprintf("FreeData Call from %s not in ValidCalls - rejected", fromCall); - return; - } - } - } - - // The TNC responds to any SSID so we can use incomming call as Appl Call - // No we can't - it responds but reports the configured call not the called call -/* - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(toCall, Appl) == 0) - break; - } - - if (App < 32) - { - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(fromCall, "-T" ) || strstr(fromCall, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - if (!CheckAppl(TNC, AppName)) - { - Sleep(1000); - FreeDataSendCommand(TNC, "dApplication not Available"); - return; - } - } - -*/ - - ProcessIncommingConnectEx(TNC, fromCall, 0, TRUE, TRUE); - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - // if connect to an application, send command - - if (AppName[0]) - { - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len = sprintf(buffptr->Data, "%s\r", AppName); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - } - - TNC->ConnectPending = FALSE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, toCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - if (SESS->Frequency == 1500) - { - // try to get from WL2K record - - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - } - } - SESS->Mode = TNC->WL2KMode; - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, toCall); - if (WL2K) - { - SESS->Frequency = WL2K->Freq; - SESS->Mode = WL2K->mode; - } - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - STREAM->Connected = TRUE; - - return; - -} - -VOID FreeDataProcessConnectAck(struct TNCINFO * TNC, char * Call, unsigned char * Msg, int Len) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Modem = TNC->FreeDataInfo; - char * toCall, * fromCall, * tncCall, *Context; - char * ptr; - char a, b; - unsigned char axcall[7]; - char AppName[13] = ""; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - TRANSPORTENTRY * SESS; - - - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s", STREAM->MyCall, STREAM->RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - STREAM->Connected = TRUE; - STREAM->Connecting = FALSE; - - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connected to %s\r", TNC->FreeDataInfo->toCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - - return; - -} -extern char LOC[7]; -/* -Line 104: if received_json["type"] == 'PING' and received_json["command"] == "PING": -Line 111: if received_json["type"] == 'ARQ' and received_json["command"] == "sendFile": -Line 142: if received_json["type"] == 'ARQ' and received_json["command"] == "sendMessage": -Line 173: if received_json["type"] == 'ARQ' and received_json["command"] == "stopTransmission": -Line 182: if received_json["type"] == 'GET' and received_json["command"] == 'STATION_INFO': -Line 195: if received_json["type"] == 'GET' and received_json["command"] == 'TNC_STATE': -Line 244: if received_json["type"] == 'GET' and received_json["command"] == 'RX_BUFFER': -Line 258: if received_json["type"] == 'GET' and received_json["command"] == 'RX_MSG_BUFFER': -Line 272: if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_BUFFER': -Line 275: if received_json["type"] == 'SET' and received_json["command"] == 'DEL_RX_MSG_BUFFER': -*/ - -//{\"type\" : \"ARQ\", \"command\" : \"sendMessage\", \"dxcallsign\" : \"G8BPQ\", \"mode\" : \"10\", \"n_frames\" : \"1\", \"data\" : \"Hello Hello\" , \"checksum\" : \"123\", \"timestamp\" : 1642580748576} - - - -static unsigned char BANNED[] = {'"', '=', ':', '{', '}', '[', ']', '/', 13, 0}; // I think only need to escape = ": CR Null - - -static void SendDataMsg(struct TNCINFO * TNC, char * Call, char * Msg, int Len) -{ - // We can't base64 encode chunks. so buffer as original data and encode on send - - SendAsFile(TNC, TNC->FreeDataInfo->farCall, Msg, Len); - WritetoTrace(TNC, Msg, Len); - - return; -} - - - -static int SendAsRaw(struct TNCINFO * TNC, char * Call, char * myCall, char * Msg, int Len) -{ - char Message[16284]; - char * Base64; - - // TNC now only supports send_raw, with base64 encoded data - - char Template[] = "{\"type\" : \"arq\", \"command\" : \"send_raw\", \"uuid\" : \"%s\",\"parameter\":" - "[{\"dxcallsign\" : \"%s\", \"mode\": \"255\", \"n_frames\" : \"1\", \"data\" : \"%s\"}]}\n"; - - - Base64 = byte_base64_encode(Msg, Len); - - Len = sprintf(Message, Template, gen_uuid(), Call, Base64); - - free(Base64); - return send(TNC->TCPDataSock, Message, Len, 0); -} - -void FlushData(struct TNCINFO * TNC) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Info = TNC->FreeDataInfo; - int Len = Info->toSendCount; - - // We need to flag as data (B) then base64 encode it - - memmove(&Info->toSendData[1], Info->toSendData, Len); - Info->toSendData[0] = 'B'; - Len++; - - SendAsRaw(TNC, Info->farCall, Info->ourCall, Info->toSendData, Len); - - Info->toSendCount = 0; - Info->toSendTimeout = 0; - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - -} - -static int SendAsFile(struct TNCINFO * TNC, char * Call, char * Msg, int Len) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct FreeDataINFO * Info = TNC->FreeDataInfo; - - // Add to buffer - - if ((Info->toSendCount + Len) > 8192) // Reasonable Limit - { - // Send the buffered bit - - FlushData(TNC); - } - - memcpy(&Info->toSendData[Info->toSendCount], Msg, Len); - Info->toSendCount += Len; - Info->toSendTimeout = 10; // About a second - - STREAM->BytesTXed += Len; - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - return Len; -} - -static int SendTNCCommand(struct TNCINFO * TNC, char * Type, char * Command) -{ - char Message[256]; - int Len; - - Len = sprintf(Message, "{\"type\" : \"%s\", \"command\" : \"%s\"}\n", Type, Command); - return send(TNC->TCPDataSock, Message, Len, 0); -} - -static void SendPoll(struct TNCINFO * TNC) -{ - return; -} - -static void SendPing(struct TNCINFO * TNC, char * Call) -{ - char Ping[] = "{\"type\" : \"ping\", \"command\" : \"ping\", \"dxcallsign\" : \"%s\", \"timestamp\" : %d}\n"; - char Message[256]; - int Len, ret; - - Len = sprintf(Message, Ping, Call, time(NULL)); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - -static void SendCQ(struct TNCINFO * TNC) -{ - char CQ[] = "{\"type\" : \"broadcast\", \"command\" : \"cqcqcq\"}\n"; - - char Message[256]; - int Len, ret; - - Len = sprintf(Message, CQ); - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - -static void SendBeacon(struct TNCINFO * TNC, int Interval) -{ - char Template1[] = "{\"type\" : \"broadcast\", \"command\" : \"start_beacon\", \"parameter\" : \"%d\"}\n"; - char Template2[] = "{\"type\" : \"broadcast\", \"command\" : \"stop_beacon\"}\n"; - - char Message[256]; - int Len, ret; - - if (Interval > 0) - Len = sprintf(Message, Template1, Interval); - else - Len = sprintf(Message, Template2); - - ret = send(TNC->TCPDataSock, (char *)&Message, Len, 0); -} - - -unsigned short int compute_crc(unsigned char *buf,int len); - - -int FreeDataWriteCommBlock(struct TNCINFO * TNC) -{ - if (TNC->hDevice) - return WriteCOMBlock(TNC->hDevice, TNC->TXBuffer, TNC->TXLen); - - return 0; -} - -char * getObjectFromArray(char * Msg) -{ - // This gets the next object from an array ({} = object, [] = array - // We look for the end of the object same number of { and }, teminate after } and return pointer to next object - // So we have terminated Msg, and returned next object in array - - // Only call if Msg is the next object in array - - - char * ptr = Msg; - char c; - - int Open = 0; - int Close = 0; - - while (c = *(ptr++)) - { - if (c == '{') Open ++; else if (c == '}') Close ++; - - if (Open == Close) - { - *(ptr++) = 0; - return ptr; - } - } - return 0; -} -/* - ["DATACHANNEL;RECEIVEDOPENER","ARQ;RECEIVING","ARQ;RECEIVING;SUCCESS"] [{"DXCALLSIGN":"GM8BPQ -{"DXCALLSIGN":"GM8BPQ","DXGRID":"","TIMESTAMP":1642847440,"RXDATA":[{"dt":"f","fn":"config.json", -"ft":"application\/json","d":"data:application\/json;base64, -ewogICAgInRuY19ob3N0IiA6ICIxMjcuMC4wLjEiLAogICAgInRuY19wb3J0IiA6ICIzMDAwIiwKICAgICJkYWVtb25faG9zdCIgOiAiMTI3LjAuMC4xIiwKICAgICJkYWVtb25fcG9ydCIgOiAiMzAwMSIsCiAgICAibXljYWxsIiA6ICJBQTBBQSIsCiAgICAibXlncmlkIiA6ICJBQTExZWEiICAgIAp9" -,"crc":"123123123"}]} -*/ -void ProcessFileObject(struct TNCINFO * TNC, char * This) -{ - char * Call; - char * LOC; - char * FN; - char * Type; - char * ptr, * ptr2; - int Len, NewLen; - - Call = strchr(This, ':'); - Call += 2; - This = strlop(Call, '"'); - - LOC = strchr(This, ':'); - LOC += 2; - This = strlop(LOC, '"'); - - FN = strstr(This, "fn"); - FN += 5; - This = strlop(FN, '"'); - - Type = strstr(This, "base64"); - Type += 7; - This = strlop(Type, '"'); - - // Decode Base64 - - Len = strlen(Type); - - Debugprintf("RX %d %s %d", TNC->Port, FN, Len); - - ptr = ptr2 = Type; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - NewLen = (int)(ptr2 - Type); - - if (*(ptr-1) == '=') - NewLen--; - - if (*(ptr-2) == '=') - NewLen--; - - Type[NewLen] = 0; - - Type --; - - Type[0] = 'B'; ; // Base64 Info - - FreeDataProcessTNCMessage(TNC, Call, Type, NewLen + 1); - - -} - -void ProcessMessageObject(struct TNCINFO * TNC, char * This) -{ - // This gets Message from a RX_MSG_BUFFER array element. - - char * Call; - char * LOC; - char * Type; - char * Msg; - int Len; - char * ptr, * ptr2; - - char * ID; - char * TYPE; - char * SEQ; - char * UUID; - char * TEXT; - char * NOIDEA; - char * FORMAT; - char * FILENAME; - int fileLen; - - int n; - - - Call = strstr(This, "dxcallsign"); - Call += 13; - This = strlop(Call, '"'); - - LOC = strchr(This, ':'); - LOC += 2; - This = strlop(LOC, '"'); - - Msg = strstr(This, "\"data\""); - Msg += 8; - This = strlop(Msg, '"'); - - // Decode Base64 - - // FreeData replaces / with \/ so need to undo - - ptr2 = strstr(Msg, "\\/"); - - while (ptr2) - { - memmove(ptr2, ptr2 + 1, strlen(ptr2)); - ptr2 = strstr(ptr2, "\\/"); - } - - Len = strlen(Msg); - - ptr = ptr2 = Msg; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - Len = (int)(ptr2 - Msg); - - if (*(ptr-1) == '=') - Len--; - - if (*(ptr-2) == '=') - Len--; - - Msg[Len] = 0; - -//m�;send_message�;123�;64730c5c-d32c-47b4-9b11-c958fd07a185�;hhhhhhhhhhhhhhhhhh -//�;�;plain/text�; - -//m;send_message;123;64730c5c-d32c-47b4-9b11-c958fd07a185;hhhhhhhhhhhhhhhhhh -//;;plain/text; - - // Message elements seem to be delimited by null ; - // Guessing labels - - ID = Msg; - - if (ID[0] == 'B') - { - // BPQ Message - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - - if (STREAM->Attached) - { - if (STREAM->Connected == 1 && STREAM->Connecting == 0) - { - char * Line = &ID[1]; - Len -= 1; - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Line, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, 256); - Len -= 256; - Line += 256; - STREAM->BytesRXed += 256; - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Line, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, Len); - STREAM->BytesRXed += Len; - - } - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - } - return; - } - - n = strlen(ID) + 2; - Msg += n; - Len -= n; - - if (ID[0] == 'm') - { - // ?? Chat ?? comes from a send raw ?? - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - TYPE = Msg; - n = strlen(TYPE) + 2; - Msg += n; - Len -= n; - - SEQ = Msg; - n = strlen(SEQ) + 2; - Msg += n; - Len -= n; - - UUID = Msg; - n = strlen(UUID) + 2; - Msg += n; - Len -= n; - - TEXT = Msg; - n = strlen(TEXT) + 2; - Msg += n; - Len -= n; - - NOIDEA = Msg; - n = strlen(NOIDEA) + 2; - Msg += n; - Len -= n; - - FORMAT = Msg; - n = strlen(FORMAT) + 2; - Msg += n; - Len -= n; - - // if Atached, send to user - - if (STREAM->Attached) - { - if (STREAM->Connected == 0 && STREAM->Connecting == 0) - { - // Just attached - send as Chat Message - - char Line[560]; - char * rest; - - // Send line by line - - rest = strlop(TEXT, 10); // FreeData chat uses LF - - while (TEXT && TEXT[0]) - { - Len = strlen(TEXT); - if (Len > 512) - TEXT[512] = 0; - - Len = sprintf(Line, "Chat From %-10s%s\r", Call, TEXT); - - while (Len > 256) - { - buffptr = GetBuff(); - buffptr->Len = 256; - memcpy(buffptr->Data, Line, 256); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, 256); - Len -= 256; - TEXT += 256; - STREAM->BytesRXed += 256; - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, Line, Len); - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - WritetoTrace(TNC, Line, Len); - STREAM->BytesRXed += Len; - - TEXT = rest; - rest = strlop(TEXT, 10); // FreeData chat ues LF - } - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed - TNC->FreeDataInfo->toSendCount, STREAM->BytesRXed, TNC->FreeDataInfo->toSendCount); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - } - } - else - { - // Send Not Available Message -//m�;send_message�;123�;64730c5c-d32c-47b4-9b11-c958fd07a185�;hhhhhhhhhhhhhhhhhh -//�;�;plain/text�; - - char reply[512] = "m"; - char * p; - - strcat(TEXT, "\r"); - WritetoTrace(TNC, TEXT, strlen(TEXT)); - - strcpy(&reply[2], ";send_message"); - strcpy(&reply[16], ";123"); - reply[21] = ';'; - strcpy(&reply[22], gen_uuid()); - sprintf(&reply[59], ";Message received but user not on line\n"); - - p = strchr(&reply[59], 0); - - p[1] = ';'; - strcpy(&p[3], ";plain/text"); - p[15] = ';'; - - Len = &p[16] - reply; - - SendAsRaw(TNC, Call, TNC->FreeDataInfo->ourCall, reply, Len); - } - return; - - } - else if (ID[0] == 'f') - { - // File Tranfer - - char Filename[256]; - FILE * fp1; - char Text[64]; - int textLen; - - - FILENAME = Msg; - n = strlen(FILENAME) + 2; - Msg += n; - Len -= n; - - TYPE = Msg; - n = strlen(TYPE) + 2; - Msg += n; - Len -= n; - - SEQ = Msg; // ?? Maybe = 123123123 - n = strlen(SEQ) + 2; - Msg += n; - Len -= n; - - TEXT = Msg; // The file - fileLen = Len; - - if (TNC->FreeDataInfo->RXDir == NULL) - { - Debugprintf("FreeDATA RXDIRECTORY not set - file transfer ignored"); - return; - } - - sprintf(Filename, "%s\\%s", TNC->FreeDataInfo->RXDir, FILENAME); - - fp1 = fopen(Filename, "wb"); - - if (fp1) - { - fwrite(TEXT, 1, fileLen, fp1); - fclose(fp1); - textLen = sprintf(Text, "File %s received from %s \r", FILENAME, Call); - WritetoTrace(TNC, Text, textLen); - } - else - Debugprintf("FreeDATA - File %s create failed %s", Filename); - - return; - } - else if (ID[0] == 'm') - { - - } - - - - - - - - - - -// FreeDataProcessTNCMessage(TNC, Call, Msg, strlen(Msg)); -} - -void processJSONINFO(struct TNCINFO * TNC, char * Info, char * Call, double snr) -{ - char * LOC = ""; - char * ptr, * Context; - - // Info is an array. Normally only one element, but should check - - ptr = strtok_s(&Info[1], ",]", &Context); - - while (ptr && ptr[1]) - { - if (strstr(ptr, "BEACON;RECEIVING")) - { - char CQ[64]; - int Len; - - Len = sprintf(CQ, "Beacon received from %s SNR %3.1f\r", Call, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (Call) - UpdateMH(TNC, Call, '!', 'I'); - } - if (strstr(ptr, "PING;RECEIVING")) - { - // Add to MH - - if (Call) - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "CQ;RECEIVING")) - { - char CQ[64]; - int Len; - - Len = sprintf(CQ, "CQ received from %s SNR %3.1f\r", Call, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "PING;RECEIVEDACK")) - { - char Msg[128]; - int Len; - - Len = sprintf(Msg, "Ping Response from %s SNR %3.1f\r", Call, snr); - FreeDataProcessTNCMessage(TNC, Call, Msg, Len); - - // Add to MH - - UpdateMH(TNC, Call, '!', 'I'); - } - else if (strstr(ptr, "TRANSMITTING;FAILED")) - { - // Failed to send a message - if it was a connect request tell appl - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - PMSGWITHLEN buffptr; - - if (STREAM->Connecting) - { - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connect Failed\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - } - } - ptr = strtok_s(NULL, ",]", &Context); - } -} - - - - - - -char * getJSONValue(char * Msg, char * Key) -{ - char * ptr, *ptr2, *value = 0; - int vallen, keylen = strlen(Key); - char c; - - // We Null Terminate the value, so we must look for keys in reverse order - - ptr = strstr(Msg, Key); - - if (ptr) - { - ptr += (keylen + 1); - - if (*(ptr) == '[') - { - // Array - - int Open = 0; - int Close = 0; - - ptr2 = ptr; - - while (c = *(ptr++)) - { - if (c == '[') - Open ++; - else if (c == ']') - Close ++; - - if (Open == Close) - { - vallen = ptr - ptr2; - value = ptr2; - value[vallen] = 0; - return value; - } - } - } - else if (*(ptr) == '\"') - { - // String - - ptr2 = ptr; - ptr = strchr(ptr + 1, '\"'); - if (ptr) - { - ptr++; - vallen = ptr - ptr2; - value = ptr2; - value[vallen] = 0; - } - } - } - return value; -} - - -char stopTNC[] = "{\"type\" : \"SET\", \"command\": \"STOPTNC\" , \"parameter\": \"---\" }\r"; - - -void StopTNC(struct TNCINFO * TNC) -{ - if (TNC->TCPDataSock) - closesocket(TNC->TCPDataSock); -} - - -void ProcessTNCJSON(struct TNCINFO * TNC, char * Msg, int Len) -{ - char * ptr; - - if (memcmp(Msg, "{\"ptt\":", 7) == 0) - { - if (strstr(Msg, "True")) - { -// TNC->Busy = TNC->BusyHold * 10; // BusyHold delay - - if (TNC->PTTMode) - Rig_PTT(TNC, TRUE); - } - else - { - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); - } - return; - } - - if (memcmp(Msg, "{\"command_response\"", 19) == 0) - { - Debugprintf("%d %s", TNC->Port, Msg); - return; - } - - - if (memcmp(Msg, "{\"command\":\"tnc_state\"", 22) == 0) - { -/* -{"command":"tnc_state","ptt_state":"False","tnc_state":"IDLE","arq_state":"False","arq_session":"False", -"arq_session_state":"disconnected","audio_rms":"0","snr":"0","frequency":"None","speed_level":"1", -"mode":"None","bandwidth":"None","fft":"[0]","channel_busy":"False","scatter":[],"rx_buffer_length":"0", -"rx_msg_buffer_length":"0","arq_bytes_per_minute":"0","arq_bytes_per_minute_burst":"0","arq_compression_factor":"0", -"arq_transmission_percent":"0","total_bytes":"0","beacon_state":"False", -"stations":[],"mycallsign":"GM8BPQ-6","dxcallsign":"AA0AA","dxgrid":""} -*/ - char * LOC = 0; - char * Stations; - char * myCall = 0; - char * farCall = 0; - double snr; - int arqstate = 0; - int rx_buffer_length = 0; - int rx_msg_buffer_length = 0; - - Msg += 23; - - ptr = strstr(Msg, "rx_buffer_length"); - - if (ptr) - rx_buffer_length = atoi(&ptr[19]); - - ptr = strstr(Msg, "rx_msg_buffer_length"); - - if (ptr) - rx_msg_buffer_length = atoi(&ptr[23]); - - ptr = strstr(Msg, "snr"); - - if (ptr) - snr = atof(ptr + 6); - - Stations = getJSONValue(Msg, "\"stations\""); - - if (Stations) - { - ptr = Stations + strlen(Stations) + 1; - LOC = getJSONValue(ptr, "\"dxgrid\""); - farCall = getJSONValue(ptr, "\"dxcallsign\""); - myCall = getJSONValue(ptr, "\"mycallsign\""); - - if (myCall && farCall) - { - myCall++; - strlop(myCall, '"'); - farCall++; - strlop(farCall, '"'); - } - } - - // Look for changes in arq_session_state - - ptr = strstr(Msg, "\"arq_session_state\""); - - if (ptr) - { - struct STREAMINFO * STREAM = &TNC->Streams[0]; - ptr += 21; - - if (memcmp(ptr, "disconnected", 10) == 0) - { - if (TNC->FreeDataInfo->arqstate != 1) - { - TNC->FreeDataInfo->arqstate = 1; - Debugprintf("%d arq_session_state %s", TNC->Port, "disconnected"); - } - - // if connected this is a new disconnect - - if (STREAM->Connected) - { - // Create a traffic record - - char logmsg[120]; - time_t Duration; - - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - } - } - else if (memcmp(ptr, "connecting", 10) == 0) - { - if (TNC->FreeDataInfo->arqstate != 2) - { - TNC->FreeDataInfo->arqstate = 2; - Debugprintf("%d arq_session_state %s", TNC->Port, "connecting"); - } - } - else if (memcmp(ptr, "connected", 9) == 0) - { - // if connection is idle this is an incoming connect - - if (TNC->FreeDataInfo->arqstate != 3) - { - TNC->FreeDataInfo->arqstate = 3; - Debugprintf("%d arq_session_state %s", TNC->Port, "connected"); - } - - if (STREAM->Connecting == FALSE && STREAM->Connected == FALSE) - { - FreeDataProcessNewConnect(TNC, farCall, myCall); - } - - // if connecting it is a connect ack - - else if (STREAM->Connecting) - { - FreeDataProcessConnectAck(TNC, farCall, Msg, Len); - } - } - - else if (memcmp(ptr, "disconnecting", 12) == 0) - { - if (TNC->FreeDataInfo->arqstate != 4) - { - TNC->FreeDataInfo->arqstate = 4; - Debugprintf("%d arq_session_state %s", TNC->Port, "disconnecting"); - } - } - else if (memcmp(ptr, "failed", 5) == 0) - { - PMSGWITHLEN buffptr; - - if (TNC->FreeDataInfo->arqstate != 5) - { - TNC->FreeDataInfo->arqstate = 5; - Debugprintf("%d arq_session_state %s", TNC->Port, "failed"); - } - - if (STREAM->Connecting) - { - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - STREAM->Connecting = FALSE; - buffptr = (PMSGWITHLEN)GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connect Failed\r"); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - STREAM->FramesQueued++; - } - } - } - - if (rx_buffer_length || rx_msg_buffer_length) - FreeGetData(TNC); - - ptr = getJSONValue(Msg, "\"info\""); - - if (ptr == NULL) - return; - - if (strcmp(ptr, "[]") != 0) - { - - processJSONINFO(TNC, ptr, farCall, snr); - Debugprintf("%d %s %s", TNC->Port, ptr, farCall); - } - - return; - } - - if (memcmp(Msg, "{\"freedata\":\"tnc-message\"", 25) == 0) - { - char * mycall = strstr(Msg, "mycall"); - char * dxcall = strstr(Msg, "dxcall"); - char * dxgrid = strstr(Msg, "dxgrid"); - char * snrptr = strstr(Msg, "snr"); - float snr = 0; - char CQ[64]; - int Len; - - Msg += 26; - - if (mycall && dxcall && dxgrid) - { - mycall += 13; - strlop(mycall, '"'); - - dxcall += 13; - strlop(dxcall, '"'); - - dxgrid += 9; - strlop(dxgrid, '"'); - } - - - if (dxcall && strstr(dxcall, "-0")) - strlop(dxcall, '-'); - - if (snrptr) - snr = atof(&snrptr[6]); - - if (memcmp(Msg, "\"beacon\":\"received\"", 18) == 0) - { - if (mycall && dxcall && dxgrid) - { - Len = sprintf(CQ, "Beacon received from %s SNR %3.1f", dxcall, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (dxcall) - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - if (memcmp(Msg, "\"cq\":\"received\"", 14) == 0) - { - if (mycall && dxcall && dxgrid) - { - Len = sprintf(CQ, "CQ received from %s", dxcall); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (dxcall) - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - if (memcmp(Msg, "\"ping\":\"received\"", 16) == 0) - { - if (mycall && dxcall && dxgrid) - { - Len = sprintf(CQ, "PING received from %s SNR %3.1f", dxcall, snr); - WritetoTrace(TNC, CQ, Len); - - // Add to MH - - if (dxcall) - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - if (memcmp(Msg, "\"ping\":\"acknowledge\"", 16) == 0) - { - if (mycall && dxcall && dxgrid) - { - char Msg[128]; - - Len = sprintf(Msg, "Ping Response from %s SNR %3.1f\r", dxcall, snr); - FreeDataProcessTNCMessage(TNC, dxcall, Msg, Len); - - UpdateMH(TNC, dxcall, '!', 'I'); - - return; - } - } - - - - - - - Debugprintf("%d %s", TNC->Port, Msg); - return; - } - - if (memcmp(Msg, "{\"command\":\"rx_buffer\"", 22) == 0) - { - char * Next, * This; - - // Delete from TNC - - SendTNCCommand(TNC, "set", "del_rx_buffer"); Msg += 22; - - ptr = getJSONValue(Msg, "\"eof\""); - ptr = getJSONValue(Msg, "\"data-array\""); - - This = ptr; - - if (This[1] == '{') // Array of objects - { - This++; - do - { - Next = getObjectFromArray(This); - ProcessMessageObject(TNC, This); - This = Next; - - } while (Next && Next[0] == '{'); - } - - return; - } - - Debugprintf("%d %s", TNC->Port, Msg); - - -// {"COMMAND":"RX_BUFFER","DATA-ARRAY":[],"EOF":"EOF"} -/* {"COMMAND":"RX_BUFFER","DATA-ARRAY":[{"DXCALLSIGN":"GM8BPQ","DXGRID":"","TIMESTAMP":1642579504, -"RXDATA":[{"dt":"f","fn":"main.js","ft":"text\/javascript" -,"d":"data:text\/javascript;base64,Y29uc3Qge.....9KTsK","crc":"123123123"}]}],"EOF":"EOF"} - - - -{"arq":"received","uuid":"a1346319-6eb0-42aa-b5a0-c9493c8ccdca","timestamp":1645812393,"dxcallsign":"G8BPQ-2","dxgrid":"","data":"QyBHOEJQUS0yIEc4QlBRLTIgRzhCUFEtMiA="} -{"ptt":"True"} - - -*/ - if (memcmp(Msg, "{\"arq\":\"received\"", 17) == 0) - { - int NewLen; - char * ptr, *ptr2, *Type; - char * Call = 0; - char * myCall = 0; - - Msg += 17; - - ptr = getJSONValue(Msg, "\"data\""); - Type = ++ptr; - - // Decode Base64 - - // FreeData replaces / with \/ so need to undo - - ptr2 = strstr(Type, "\\/"); - - while (ptr2) - { - memmove(ptr2, ptr2 + 1, strlen(ptr2)); - ptr2 = strstr(ptr2, "\\/"); - } - - Len = strlen(Type) - 1; - - // Debugprintf("RX %d %s %d", TNC->Port, FN, Len); - - ptr = ptr2 = Type; - - while (Len > 0) - { - xdecodeblock(ptr, ptr2); - ptr += 4; - ptr2 += 3; - Len -= 4; - } - - NewLen = (int)(ptr2 - Type); - - if (*(ptr-1) == '=') - NewLen--; - - if (*(ptr-2) == '=') - NewLen--; - - Type[NewLen] = 0; - - myCall = getJSONValue(Msg, "\"mycallsign\""); - Call = getJSONValue(Msg, "\"dxcallsign\""); - - if (Call) - { - Call++; - strlop(Call, '"'); - } - - if (myCall) - { - myCall++; - strlop(myCall, '"'); - } - - - FreeDataProcessTNCMessage(TNC, Call, Type, NewLen); - - return; - } - - if (memcmp(Msg, "{\"COMMAND\":\"RX_MSG_BUFFER\"", 26) == 0) - { - char * Next, * This; - - Msg += 26; - ptr = getJSONValue(Msg, "\"EOF\""); - ptr = getJSONValue(Msg, "\"DATA-ARRAY\""); - - This = ptr; - - if (This[1] == '{') // Array of objects - { - This++; - do { - Next = getObjectFromArray(This); - ProcessMessageObject(TNC, This); - This = Next; - } while (Next && Next[0] == '{'); - - // Delete from TNC - - SendTNCCommand(TNC, "SET", "DEL_RX_MSG_BUFFER"); - } - - - return; - } -} - -int FreeDataConnect(struct TNCINFO * TNC, char * Call) -{ - char Connect[] = "{\"type\" : \"arq\", \"command\": \"connect\" , \"dxcallsign\": \"%s\"}\n"; - char Msg[128]; - int Len; - - Len = sprintf(Msg, Connect, Call); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - -int FreeDataDisconnect(struct TNCINFO * TNC) -{ - char Disconnect[] = "{\"type\" : \"arq\", \"command\": \"disconnect\"}\n"; - char Msg[128]; - int Len; - -// return FreeDataSendCommand(TNC, "D"); - - Len = sprintf(Msg, Disconnect); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - - -int FreeGetData(struct TNCINFO * TNC) -{ - char GetData[] = "{\"type\" : \"get\", \"command\": \"rx_buffer\"}\n"; - char Msg[128]; - int Len; - - Len = sprintf(Msg, GetData); - - return send(TNC->TCPDataSock, Msg, Len, 0); -} - -int FreeDataSendCommand(struct TNCINFO * TNC, char * Msg) -{ - // Commands are simulated as Messages to the remote BPQ. The TNC itself does not handle any commands - - // First Byte of MSG is a Type - Command or Data. MSG has a limited character set Use =xx for Now. - - // Current Types - C = Connect, D = Disconnect, I = info - - SendAsRaw(TNC, TNC->FreeDataInfo->farCall, TNC->FreeDataInfo->ourCall, Msg, strlen(Msg)); - return 0; -} - -void FreeDataProcessTNCMsg(struct TNCINFO * TNC) -{ - int DataInputLen, MsgLen; - char * ptr, * endptr; - int maxlen; - - // May get message split over packets or multiple messages per packet - - // A complete file transfer arrives as one message, so can bw very long - - - if (TNC->DataInputLen > MAXRXSIZE) // Shouldnt have packets longer than this - TNC->DataInputLen=0; - - maxlen = MAXRXSIZE - TNC->DataInputLen; - - if (maxlen >1400) - maxlen = 1400; - - DataInputLen = recv(TNC->TCPDataSock, &TNC->ARDOPDataBuffer[TNC->DataInputLen], maxlen, 0); - - if (DataInputLen == 0 || DataInputLen == SOCKET_ERROR) - { - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - closesocket(TNC->TCPDataSock); - - TNC->TCPDataSock = 0; - - TNC->TNCCONNECTED = FALSE; - - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - STREAM->Disconnecting = FALSE; - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - return; - } - - TNC->DataInputLen += DataInputLen; - - TNC->ARDOPDataBuffer[TNC->DataInputLen] = 0; // So we can use string functions - - // Message should be json. We know the format, so don't need a general parser, but need to know if complete. - // I think counting { and } and stopping if equal should work; - -// Debugprintf(TNC->ARDOPDataBuffer); - - //I think now messages end with LF - -loop: - - endptr = strchr(TNC->ARDOPDataBuffer, 10); - - if (endptr == 0) - return; - - *(endptr) = 0; - - if (TNC->ARDOPDataBuffer[0] != '{') - { - TNC->DataInputLen = 0; - return; - } - - ptr = &TNC->ARDOPDataBuffer[0]; - - MsgLen = endptr - ptr; - - ProcessTNCJSON(TNC, ptr, MsgLen); - - // MsgLen doesnt include lf - - MsgLen++; - - if (TNC->DataInputLen == MsgLen) - { - TNC->DataInputLen = 0; - return; - } - - // More in buffer - - ptr += MsgLen; - TNC->DataInputLen -= MsgLen; - - memmove(TNC->ARDOPDataBuffer, ptr, TNC->DataInputLen + 1); - - goto loop; - - // Message Incomplete - wait for rest; -} - - - -VOID FreeDataThread(void * portptr); - -int ConnecttoFreeData(int port) -{ - _beginthread(FreeDataThread, 0, (void *)(size_t)port); - - return 0; -} - -static SOCKADDR_IN sinx; -static SOCKADDR_IN rxaddr; - - -VOID FreeDataThread(void * portptr) -{ - // Messages are JSON encapulated - // Now We run tnc directly so don't open daemon socket - // Looks for data on socket(s) - - int port = (int)(size_t)portptr; - char Msg[255]; - int err, i, ret; - u_long param=1; - BOOL bcopt=TRUE; - struct hostent * HostEnt; - struct TNCINFO * TNC = TNCInfo[port]; - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - char Params[512]; - - if (TNC->HostName == NULL) - return; - - buildParamString(TNC, Params); - - TNC->BusyFlags = 0; - - TNC->TNCCONNECTING = TRUE; - - Sleep(3000); // Allow init to complete - -// printf("Starting FreeDATA Thread\n"); - -// if on Windows and Localhost see if TNC is running - -#ifdef WIN32 - - if (strcmp(TNC->HostName, "127.0.0.1") == 0) - { - // can only check if running on local host - - TNC->PID = GetListeningPortsPID(TNC->Datadestaddr.sin_port); - - if (TNC->PID == 0) - goto TNCNotRunning; - - // Get the File Name in case we want to restart it. - - if (TNC->ProgramPath == NULL) - { - if (GetModuleFileNameExPtr) - { - HANDLE hProc; - char ExeName[256] = ""; - - hProc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, TNC->PID); - - if (hProc) - { - GetModuleFileNameExPtr(hProc, 0, ExeName, 255); - CloseHandle(hProc); - - TNC->ProgramPath = _strdup(ExeName); - } - } - } - goto TNCRunning; - } - -#endif - -TNCNotRunning: - - // Not running or can't check, restart if we have a path - - if (TNC->ProgramPath) - { - Consoleprintf("Trying to (re)start TNC %s", TNC->ProgramPath); - - if (RestartTNC(TNC)) - CountRestarts(TNC); - - Sleep(TNC->AutoStartDelay); - } - -TNCRunning: - - if (TNC->Alerted == FALSE) - { - sprintf(TNC->WEB_COMMSSTATE, "Connecting to TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - - TNC->Datadestaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - - if (TNC->Datadestaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - { - TNC->TNCCONNECTING = FALSE; - sprintf(Msg, "Resolve Failed for FreeData Host - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - return; // Resolve failed - } - memcpy(&TNC->Datadestaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - - TNC->TCPDataSock=socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for FreeData TNC socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->TNCCONNECTING = FALSE; - return; - } - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - // Connect TNC Port - - if (connect(TNC->TCPDataSock,(LPSOCKADDR) &TNC->Datadestaddr,sizeof(TNC->Datadestaddr)) == 0) - { - // - // Connected successful - // - } - else - { - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - i=sprintf(Msg, "Connect Failed for FreeData TNC socket - error code = %d\r\n", err); - WritetoConsole(Msg); - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->Alerted = TRUE; - } - - closesocket(TNC->TCPDataSock); - TNC->TCPDataSock = 0; - TNC->TNCCONNECTING = FALSE; - - RestartTNC(TNC); - return; - } - - Sleep(1000); - - TNC->LastFreq = 0; - - TNC->TNCCONNECTING = FALSE; - TNC->TNCCONNECTED = TRUE; - TNC->BusyFlags = 0; - TNC->InputLen = 0; - TNC->Alerted = FALSE; - - TNC->Alerted = TRUE; - - sprintf(TNC->WEB_COMMSSTATE, "Connected to FreeData TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - sprintf(Msg, "Connected to FreeData TNC Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - - #ifndef LINBPQ -// FreeSemaphore(&Semaphore); - Sleep(1000); // Give VARA time to update Window title -// EnumWindows(EnumVARAWindowsProc, (LPARAM)TNC); -// GetSemaphore(&Semaphore, 52); -#endif - - while (TNC->TNCCONNECTED) - { - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - if (TNC->TNCCONNECTED) - FD_SET(TNC->TCPDataSock,&readfs); - - if (TNC->TNCCONNECTING || TNC->TNCCONNECTED) FD_SET(TNC->TCPDataSock,&errorfs); - - timeout.tv_sec = 300; - timeout.tv_usec = 0; - - ret = select((int)TNC->TCPDataSock + 1, &readfs, NULL, &errorfs, &timeout); - - if (ret == SOCKET_ERROR) - { - Debugprintf("FreeData Select failed %d ", WSAGetLastError()); - goto Lost; - } - - // If nothing doing send get rx_buffer as link validation poll - - if (ret == 0) - { - char GetData[] = "{\"type\" : \"get\", \"command\": \"rx_buffer\"}\n"; - int Len; - - Len = send(TNC->TCPDataSock, GetData, strlen(GetData), 0); - - if (Len != strlen(GetData)) - goto closeThread; - } - else - { - // See what happened - - if (FD_ISSET(TNC->TCPDataSock, &readfs)) - { - GetSemaphore(&Semaphore, 52); - FreeDataProcessTNCMsg(TNC); - FreeSemaphore(&Semaphore); - } - - if (FD_ISSET(TNC->TCPDataSock, &errorfs)) - { -Lost: - sprintf(Msg, "FreeData TNC Connection lost for Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->TNCCONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - closesocket(TNC->TCPDataSock); - TNC->TCPDataSock = 0; - } - - continue; - } - } - -closeThread: - - if (TNC->TCPDataSock) - { - shutdown(TNC->TCPDataSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPDataSock); - } - - sprintf(Msg, "FreeData Thread Terminated Port %d\r\n", TNC->Port); - WritetoConsole(Msg); -} - -void ConnectTNCPort(struct TNCINFO * TNC) -{ - char Msg[255]; - int err; - int bcopt = TRUE; - - TNC->TNCCONNECTING = TRUE; - - TNC->TCPDataSock = socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - sprintf(Msg, "Socket Failed for FreeData TNC socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->TNCCONNECTING = FALSE; - return; - } - - setsockopt(TNC->TCPDataSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(TNC->TCPDataSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - if (connect(TNC->TCPDataSock,(LPSOCKADDR) &TNC->Datadestaddr,sizeof(TNC->Datadestaddr)) == 0) - { - // Connected successful - - sprintf(TNC->WEB_COMMSSTATE, "Connected to FreeData TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->TNCCONNECTING = FALSE; - TNC->TNCCONNECTED = TRUE; - TNC->Alerted = FALSE; - return; - } - - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - sprintf(Msg, "Connect Failed for FreeData TNC socket - error code = %d Port %d\n", - err, htons(TNC->Datadestaddr.sin_port)); - - WritetoConsole(Msg); - TNC->Alerted = TRUE; - TNC->TNCCONNECTING = FALSE; - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - - closesocket(TNC->TCPDataSock); - - TNC->TCPDataSock = 0; - TNC->TNCCONNECTING = FALSE; - return; -} - -void buildParamString(struct TNCINFO * TNC, char * line) -{ - // choices=[, "direct", "rigctl", "rigctld"], - - struct FreeDataINFO * FDI = TNC->FreeDataInfo; - int capindex = -1, playindex = -1; - int i; - - // Python adds sound mapper on front and counts Playback after Capture - - for (i = 0; i < CaptureCount; i++) - { - if (strstr(&CaptureNames[i][0], TNC->FreeDataInfo->Capture)) - { - capindex = i + 1; - break; - } - } - - for (i = 0; i < PlaybackCount; i++) - { - if (strstr(&PlaybackNames[i][0], TNC->FreeDataInfo->Playback)) - { - playindex = i + CaptureCount + 2; - break; - } - } - - sprintf(line, - "--mycall %s --ssid %s --mygrid %s --rx %d --tx %d --port %d --radiocontrol %s " - "--tuning_range_fmin %3.1f --tuning_range_fmax %3.1f --tx-audio-level %d", - - FDI->ourCall, FDI->SSIDList, LOC, capindex, playindex, TNC->TCPPort, FDI->hamlibHost ? "rigctld" : "disabled", - FDI->TuningRange * -1.0, FDI->TuningRange * 1.0, FDI->TXLevel); - - if (FDI->hamlibHost) - sprintf(line, "%s --rigctld_ip %s --rigctld_port %d", line, FDI->hamlibHost, FDI->hamlibPort); - - if (FDI->LimitBandWidth) - strcat(line, " --500hz"); - - if (FDI->Explorer) - strcat(line, " --explorer"); - - - // Add these to the end if needed - // --scatter - // --fft - // --fsk - // --qrv (respond to cq) - -} - -#ifndef WIN32 - -#include - -char ** WriteDevices = NULL; -int WriteDeviceCount = 0; - -char ** ReadDevices = NULL; -int ReadDeviceCount = 0; - - -int GetOutputDeviceCollection() -{ - // Get all the suitable devices and put in a list for GetNext to return - - snd_ctl_t *handle= NULL; - snd_pcm_t *pcm= NULL; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - snd_pcm_hw_params_t *pars; - snd_pcm_format_mask_t *fmask; - char NameString[256]; - - Debugprintf("Playback Devices\n"); - - // free old struct if called again - -// while (WriteDeviceCount) -// { -// WriteDeviceCount--; -// free(WriteDevices[WriteDeviceCount]); -// } - -// if (WriteDevices) -// free(WriteDevices); - - WriteDevices = NULL; - WriteDeviceCount = 0; - - // Add virtual device ARDOP so ALSA plugins can be used if needed - - WriteDevices = realloc(WriteDevices,(WriteDeviceCount + 1) * sizeof(WriteDevices)); - - // Get Device List from ALSA - - snd_ctl_card_info_alloca(&info); - snd_pcm_info_alloca(&pcminfo); - snd_pcm_hw_params_alloca(&pars); - snd_pcm_format_mask_alloca(&fmask); - - char hwdev[80]; - unsigned min, max, ratemin, ratemax; - int card, err, dev, nsubd; - snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; - - card = -1; - - if (snd_card_next(&card) < 0) - { - Debugprintf("No Devices"); - return 0; - } - - while (card >= 0) - { - sprintf(hwdev, "hw:%d", card); - err = snd_ctl_open(&handle, hwdev, 0); - err = snd_ctl_card_info(handle, info); - - Debugprintf("Card %d, ID `%s', name `%s'", card, snd_ctl_card_info_get_id(info), - snd_ctl_card_info_get_name(info)); - - - dev = -1; - - if(snd_ctl_pcm_next_device(handle, &dev) < 0) - { - // Card has no devices - - snd_ctl_close(handle); - - WriteDevices = realloc(WriteDevices,(WriteDeviceCount + 1) * sizeof(WriteDevices)); - WriteDevices[WriteDeviceCount++] = strupr(strdup("DummyDevice")); - - goto nextcard; - } - - while (dev >= 0) - { - snd_pcm_info_set_device(pcminfo, dev); - snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, stream); - - err = snd_ctl_pcm_info(handle, pcminfo); - - - if (err == -ENOENT) - goto nextdevice; - - nsubd = snd_pcm_info_get_subdevices_count(pcminfo); - - Debugprintf(" Device hw:%d,%d ID `%s', name `%s', %d subdevices (%d available)", - card, dev, snd_pcm_info_get_id(pcminfo), snd_pcm_info_get_name(pcminfo), - nsubd, snd_pcm_info_get_subdevices_avail(pcminfo)); - - sprintf(hwdev, "hw:%d,%d", card, dev); - - err = snd_pcm_open(&pcm, hwdev, stream, SND_PCM_NONBLOCK); - - if (err) - { - Debugprintf("Error %d opening output device", err); - goto nextdevice; - } - - // Get parameters for this device - - err = snd_pcm_hw_params_any(pcm, pars); - - snd_pcm_hw_params_get_channels_min(pars, &min); - snd_pcm_hw_params_get_channels_max(pars, &max); - - snd_pcm_hw_params_get_rate_min(pars, &ratemin, NULL); - snd_pcm_hw_params_get_rate_max(pars, &ratemax, NULL); - - if( min == max ) - if( min == 1 ) - Debugprintf(" 1 channel, sampling rate %u..%u Hz", ratemin, ratemax); - else - Debugprintf(" %d channels, sampling rate %u..%u Hz", min, ratemin, ratemax); - else - Debugprintf(" %u..%u channels, sampling rate %u..%u Hz", min, max, ratemin, ratemax); - - // Add device to list - - sprintf(NameString, "hw:%d,%d %s(%s)", card, dev, - snd_pcm_info_get_name(pcminfo), snd_ctl_card_info_get_name(info)); - - WriteDevices = realloc(WriteDevices,(WriteDeviceCount + 1) * sizeof(WriteDevices)); - WriteDevices[WriteDeviceCount++] = strupr(strdup(NameString)); - - snd_pcm_close(pcm); - pcm= NULL; - -nextdevice: - if (snd_ctl_pcm_next_device(handle, &dev) < 0) - break; - } - snd_ctl_close(handle); - -nextcard: - - Debugprintf(""); - - if (snd_card_next(&card) < 0) // No more cards - break; - } - - return WriteDeviceCount; -} - -int GetNextOutputDevice(char * dest, int max, int n) -{ - if (n >= WriteDeviceCount) - return 0; - - strcpy(dest, WriteDevices[n]); - return strlen(dest); -} - - -int GetInputDeviceCollection() -{ - // Get all the suitable devices and put in a list for GetNext to return - - snd_ctl_t *handle= NULL; - snd_pcm_t *pcm= NULL; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - snd_pcm_hw_params_t *pars; - snd_pcm_format_mask_t *fmask; - char NameString[256]; - - Debugprintf("Capture Devices\n"); - - ReadDevices = NULL; - ReadDeviceCount = 0; - - ReadDevices = realloc(ReadDevices,(ReadDeviceCount + 1) * sizeof(ReadDevices)); - - // Get Device List from ALSA - - snd_ctl_card_info_alloca(&info); - snd_pcm_info_alloca(&pcminfo); - snd_pcm_hw_params_alloca(&pars); - snd_pcm_format_mask_alloca(&fmask); - - char hwdev[80]; - unsigned min, max, ratemin, ratemax; - int card, err, dev, nsubd; - snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE; - - card = -1; - - if(snd_card_next(&card) < 0) - { - Debugprintf("No Devices"); - return 0; - } - - while(card >= 0) - { - sprintf(hwdev, "hw:%d", card); - err = snd_ctl_open(&handle, hwdev, 0); - err = snd_ctl_card_info(handle, info); - -// Debugprintf("Card %d, ID `%s', name `%s'", card, snd_ctl_card_info_get_id(info), -// snd_ctl_card_info_get_name(info)); - - dev = -1; - - if (snd_ctl_pcm_next_device(handle, &dev) < 0) // No Devicdes - { - snd_ctl_close(handle); - - ReadDevices = realloc(ReadDevices,(ReadDeviceCount + 1) * sizeof(ReadDevices)); - ReadDevices[ReadDeviceCount++] = strupr(strdup("DummyDevice")); - - Debugprintf("%d %s", ReadDeviceCount, "DummyDevice"); - goto nextcard; - } - - while(dev >= 0) - { - snd_pcm_info_set_device(pcminfo, dev); - snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, stream); - err= snd_ctl_pcm_info(handle, pcminfo); - - if (err == -ENOENT) - goto nextdevice; - - nsubd= snd_pcm_info_get_subdevices_count(pcminfo); -// Debugprintf(" Device hw:%d,%d ID `%s', name `%s', %d subdevices (%d available)", -// card, dev, snd_pcm_info_get_id(pcminfo), snd_pcm_info_get_name(pcminfo), -// nsubd, snd_pcm_info_get_subdevices_avail(pcminfo)); - - sprintf(hwdev, "hw:%d,%d", card, dev); -/* - err = snd_pcm_open(&pcm, hwdev, stream, SND_PCM_NONBLOCK); - - if (err) - { - Debugprintf("Error %d opening input device", err); - goto nextdevice; - } - - err = snd_pcm_hw_params_any(pcm, pars); - - snd_pcm_hw_params_get_channels_min(pars, &min); - snd_pcm_hw_params_get_channels_max(pars, &max); - snd_pcm_hw_params_get_rate_min(pars, &ratemin, NULL); - snd_pcm_hw_params_get_rate_max(pars, &ratemax, NULL); - - if( min == max ) - if( min == 1 ) - Debugprintf(" 1 channel, sampling rate %u..%u Hz", ratemin, ratemax); - else - Debugprintf(" %d channels, sampling rate %u..%u Hz", min, ratemin, ratemax); - else - Debugprintf(" %u..%u channels, sampling rate %u..%u Hz", min, max, ratemin, ratemax); -*/ - sprintf(NameString, "hw:%d,%d %s(%s)", card, dev, - snd_pcm_info_get_name(pcminfo), snd_ctl_card_info_get_name(info)); - - Debugprintf("%d %s", ReadDeviceCount, NameString); - - ReadDevices = realloc(ReadDevices,(ReadDeviceCount + 1) * sizeof(ReadDevices)); - ReadDevices[ReadDeviceCount++] = strupr(strdup(NameString)); - -nextdevice: - if (snd_ctl_pcm_next_device(handle, &dev) < 0) - break; - } - snd_ctl_close(handle); -nextcard: - - Debugprintf(""); - if (snd_card_next(&card) < 0 ) - break; - } - return ReadDeviceCount; -} - -int GetNextInputDevice(char * dest, int max, int n) -{ - if (n >= ReadDeviceCount) - return 0; - - strcpy(dest, ReadDevices[n]); - return strlen(dest); -} - -#endif - - -// We need a local restart tnc as we need to add params and start a python progrm on Linux - -BOOL KillOldTNC(char * Path); - -static BOOL RestartTNC(struct TNCINFO * TNC) -{ - if (TNC->ProgramPath == NULL || TNC->DontRestart) - return 0; - - if (_memicmp(TNC->ProgramPath, "REMOTE:", 7) == 0) - { - int n; - - // Try to start TNC on a remote host - - SOCKET sock = socket(AF_INET,SOCK_DGRAM,0); - struct sockaddr_in destaddr; - - Debugprintf("trying to restart TNC %s", TNC->ProgramPath); - - if (sock == INVALID_SOCKET) - return 0; - - destaddr.sin_family = AF_INET; - destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - destaddr.sin_port = htons(8500); - - if (destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - struct hostent * HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - return 0; // Resolve failed - - memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - - n = sendto(sock, TNC->ProgramPath, (int)strlen(TNC->ProgramPath), 0, (struct sockaddr *)&destaddr, sizeof(destaddr)); - - Debugprintf("Restart TNC - sendto returned %d", n); - - Sleep(100); - closesocket(sock); - - return 1; // Cant tell if it worked, but assume ok - } - - // Not Remote - - // Add parameters to command string - -#ifndef WIN32 - { - char * arg_list[64]; - char rxVal[16]; - char txVal[16]; - char tunePlus[16]; - char tuneMinus[16]; - char portVal[16]; - char txLevelVal[16]; - char RigPort[16]; - int n = 0; - - pid_t child_pid; - - struct FreeDataINFO * FDI = TNC->FreeDataInfo; - int capindex = -1, playindex = -1; - int i; - - if (ReadDeviceCount == 0) - { - GetOutputDeviceCollection(); - GetInputDeviceCollection(); - } - - // - - for (i = 0; i < ReadDeviceCount; i++) - { - printf("%s %s\n", &ReadDevices[i][0], TNC->FreeDataInfo->Capture); - if (strstr(&ReadDevices[i][0], TNC->FreeDataInfo->Capture)) - { - capindex = i; - break; - } - } - - - for (i = 0; i < WriteDeviceCount; i++) - { - printf("%s %s\n", &WriteDevices[i][0], TNC->FreeDataInfo->Playback); - - if (strstr(&WriteDevices[i][0], TNC->FreeDataInfo->Playback)) - { - playindex = i; - break; - } - } - - - capindex=playindex=3; - - printf("%d %d \n", capindex, playindex); - - signal(SIGCHLD, SIG_IGN); // Silently (and portably) reap children. - - arg_list[n++] = "python3"; - arg_list[n++] = TNC->ProgramPath; - arg_list[n++] = "--mycall"; - arg_list[n++] = FDI->ourCall; - arg_list[n++] = "--ssid"; - arg_list[n++] = FDI->SSIDList; - arg_list[n++] = "--mygrid"; - arg_list[n++] = LOC; - arg_list[n++] = "--rx"; - sprintf(rxVal, "%d", capindex); - arg_list[n++] = rxVal; - arg_list[n++] = "--tx"; - sprintf(txVal, "%d", playindex); - arg_list[n++] = txVal; - arg_list[n++] = "--port"; - sprintf(portVal, "%d", TNC->TCPPort); - arg_list[n++] = portVal; - arg_list[n++] = "--radiocontrol"; - arg_list[n++] = FDI->hamlibHost ? "rigctld" : "disabled"; - arg_list[n++] = "--tuning_range_fmin"; - sprintf(tuneMinus, "%3.1f", FDI->TuningRange * -1.0); - arg_list[n++] = tuneMinus; - arg_list[n++] = "--tuning_range_fmax"; - sprintf(tunePlus, "%3.1f", FDI->TuningRange * 1.0); - arg_list[n++] = tunePlus; - arg_list[n++] = "--tx-audio-level"; - sprintf(txLevelVal, "%d", FDI->TXLevel); - arg_list[n++] = txLevelVal; - - if (FDI->hamlibHost) - { - arg_list[n++] = "--rigctld_ip"; - arg_list[n++] = FDI->hamlibHost; - arg_list[n++] = "--rigctld_port"; - sprintf(RigPort, "%d", FDI->hamlibPort); - arg_list[n++] = RigPort; - } - - if (FDI->LimitBandWidth) - arg_list[n++] = "--500hz"; - - if (FDI->Explorer) - arg_list[n++] = "--explorer"; - - arg_list[n++] = 0; - - n = 0; - - // Fork and Exec TNC - - printf("Trying to start %s\n", TNC->ProgramPath); - - /* Duplicate this process. */ - - child_pid = fork (); - - if (child_pid == -1) - { - printf ("StartTNC fork() Failed\n"); - return 0; - } - - if (child_pid == 0) - { - execvp (arg_list[0], arg_list); - - /* The execvp function returns only if an error occurs. */ - - printf ("Failed to start TNC\n"); - exit(0); // Kill the new process - } - printf("Started TNC\n"); - sleep(5000); - - return TRUE; - } -#else - - { - int n = 0; - - STARTUPINFO SInfo; // pointer to STARTUPINFO - PROCESS_INFORMATION PInfo; // pointer to PROCESS_INFORMATION - char workingDirectory[256]; - char commandLine[512]; - char Params[512]; - - int i = strlen(TNC->ProgramPath); - - SInfo.cb=sizeof(SInfo); - SInfo.lpReserved=NULL; - SInfo.lpDesktop=NULL; - SInfo.lpTitle=NULL; - SInfo.dwFlags=0; - SInfo.cbReserved2=0; - SInfo.lpReserved2=NULL; - - Debugprintf("RestartTNC Called for %s", TNC->ProgramPath); - - - strcpy(workingDirectory, TNC->ProgramPath); - - while (i--) - { - if (workingDirectory[i] == '\\' || workingDirectory[i] == '/') - { - workingDirectory[i] = 0; - break; - } - } - - buildParamString(TNC, Params); - - if (TNC->PID) - { - KillTNC(TNC); - Sleep(100); - } - - sprintf(commandLine, "\"%s\" %s", TNC->ProgramPath, Params); - - if (CreateProcess(NULL, commandLine, NULL, NULL, FALSE,0, NULL, workingDirectory, &SInfo, &PInfo)) - { - Debugprintf("Restart TNC OK"); - TNC->PID = PInfo.dwProcessId; - return TRUE; - } - else - { - Debugprintf("Restart TNC Failed %d ", GetLastError()); - return FALSE; - } - } -#endif - return 0; -} diff --git a/HFCommon-HPLaptop.c b/HFCommon-HPLaptop.c deleted file mode 100644 index 21b7376..0000000 --- a/HFCommon-HPLaptop.c +++ /dev/null @@ -1,2154 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - - -#pragma data_seg("_BPQDATA") - -#define _CRT_SECURE_NO_DEPRECATE - -#include - -#define SD_RECEIVE 0x00 -#define SD_SEND 0x01 -#define SD_BOTH 0x02 - - -#include "kernelresource.h" -#include "CHeaders.h" -#include "tncinfo.h" -#ifndef LINBPQ -#include -#endif -//#include -#include "bpq32.h" -#include "adif.h" - -extern char * PortConfig[33]; - -HANDLE hInstance; -extern HBRUSH bgBrush; -extern HWND ClientWnd, FrameWnd; -extern int OffsetH, OffsetW; - -extern HMENU hMainFrameMenu; -extern HMENU hBaseMenu; -extern HANDLE hInstance; - -extern HKEY REGTREE; - -extern int Ver[]; - - -int KillTNC(struct TNCINFO * TNC); -int RestartTNC(struct TNCINFO * TNC); - -char * GetChallengeResponse(char * Call, char * ChallengeString); - -VOID __cdecl Debugprintf(const char * format, ...); -int FromLOC(char * Locator, double * pLat, double * pLon); -BOOL ToLOC(double Lat, double Lon , char * Locator); - -int GetPosnFromAPRS(char * Call, double * Lat, double * Lon); -char * stristr (char *ch1, char *ch2); - -static RECT Rect; - -extern struct TNCINFO * TNCInfo[41]; // Records are Malloc'd - -#define WSA_ACCEPT WM_USER + 1 -#define WSA_DATA WM_USER + 2 -#define WSA_CONNECT WM_USER + 3 - -int Winmor_Socket_Data(int sock, int error, int eventcode); - -struct WL2KInfo * WL2KReports; - -int WL2KTimer = 0; - -int ModetoBaud[31] = {0,0,0,0,0,0,0,0,0,0,0, // 0 = 10 - 200,600,3200,600,3200,3200, // 11 - 16 - 0,0,0,0,0,0,0,0,0,0,0,0,0,600}; // 17 - 30 - -extern char HFCTEXT[]; -extern int HFCTEXTLEN; - - -extern char WL2KCall[10]; -extern char WL2KLoc[7]; - - -VOID MoveWindows(struct TNCINFO * TNC) -{ -#ifndef LINBPQ - RECT rcClient; - int ClientHeight, ClientWidth; - - GetClientRect(TNC->hDlg, &rcClient); - - ClientHeight = rcClient.bottom; - ClientWidth = rcClient.right; - - if (TNC->hMonitor) - MoveWindow(TNC->hMonitor,2 , TNC->RigControlRow + 3, ClientWidth-4, ClientHeight - (TNC->RigControlRow + 3), TRUE); -#endif -} - -char * Config; -static char * ptr1, * ptr2; - -#ifndef LINBPQ - -LRESULT CALLBACK PacWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - MINMAXINFO * mmi; - - int i; - struct TNCINFO * TNC; - - HKEY hKey; - char Key[80]; - int retCode, disp; - - for (i=0; i<41; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC->hDlg == hWnd) - break; - } - - if (TNC == NULL) - return DefMDIChildProc(hWnd, message, wParam, lParam); - - switch (message) { - - case WM_CREATE: - - break; - - case WM_PAINT: - -// hdc = BeginPaint (hWnd, &ps); - -// SelectObject( hdc, hFont) ; - -// EndPaint (hWnd, &ps); -// -// wParam = hdc; - - break; - - - case WM_GETMINMAXINFO: - - if (TNC->ClientHeight) - { - mmi = (MINMAXINFO *)lParam; - mmi->ptMaxSize.x = TNC->ClientWidth; - mmi->ptMaxSize.y = TNC->ClientHeight; - mmi->ptMaxTrackSize.x = TNC->ClientWidth; - mmi->ptMaxTrackSize.y = TNC->ClientHeight; - } - - break; - - - case WM_MDIACTIVATE: - { - - // Set the system info menu when getting activated - - if (lParam == (LPARAM) hWnd) - { - // Activate - - RemoveMenu(hBaseMenu, 1, MF_BYPOSITION); - - if (TNC->hMenu) - AppendMenu(hBaseMenu, MF_STRING + MF_POPUP, (UINT)TNC->hMenu, "Actions"); - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hBaseMenu, (LPARAM) hWndMenu); - -// SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) TNC->hMenu, (LPARAM) TNC->hWndMenu); - } - else - { - // Deactivate - - SendMessage(ClientWnd, WM_MDISETMENU, (WPARAM) hMainFrameMenu, (LPARAM) NULL); - } - - // call DrawMenuBar after the menu items are set - DrawMenuBar(FrameWnd); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - } - - - - case WM_INITMENUPOPUP: - - if (wParam == (WPARAM)TNC->hMenu) - { - if (TNC->ProgramPath) - { - if (strstr(TNC->ProgramPath, " TNC") || strstr(TNC->ProgramPath, "ARDOP") - || strstr(TNC->ProgramPath, "VARA") || stristr(TNC->ProgramPath, "FREEDATA")) - { - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_ENABLED); - - break; - } - } - EnableMenuItem(TNC->hMenu, WINMOR_RESTART, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(TNC->hMenu, WINMOR_KILL, MF_BYCOMMAND | MF_GRAYED); - } - - break; - - case WM_COMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - case WINMOR_KILL: - - TNC->DontRestart = TRUE; - KillTNC(TNC); - break; - - case WINMOR_RESTART: - - TNC->DontRestart = FALSE; - KillTNC(TNC); - RestartTNC(TNC); - break; - - case WINMOR_RESTARTAFTERFAILURE: - - TNC->RestartAfterFailure = !TNC->RestartAfterFailure; - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", TNC->Port); - - retCode = RegCreateKeyEx(REGTREE, Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - RegSetValueEx(hKey,"TNC->RestartAfterFailure",0,REG_DWORD,(BYTE *)&TNC->RestartAfterFailure, 4); - RegCloseKey(hKey); - } - break; - - case ARDOP_ABORT: - - if (TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SIZING: - case WM_SIZE: - - MoveWindows(TNC); - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_SYSCOMMAND: - - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - - switch (wmId) - { - - case SC_RESTORE: - - TNC->Minimized = FALSE; - break; - - case SC_MINIMIZE: - - TNC->Minimized = TRUE; - break; - } - - return DefMDIChildProc(hWnd, message, wParam, lParam); - - case WM_CTLCOLORDLG: - return (LONG)bgBrush; - - - case WM_CTLCOLORSTATIC: - { - HDC hdcStatic = (HDC)wParam; - SetTextColor(hdcStatic, RGB(0, 0, 0)); - SetBkMode(hdcStatic, TRANSPARENT); - return (LONG)bgBrush; - } - - case WM_HSCROLL: - { - char value[16]; - - switch (LOWORD(wParam)) - { - case TB_ENDTRACK: - case TB_THUMBTRACK: - - TNC->TXOffset = SendMessage(TNC->xIDC_TXTUNE, TBM_GETPOS, 0, 0); - sprintf(value, "%d", TNC->TXOffset); - MySetWindowText(TNC->xIDC_TXTUNEVAL, value); - - break; - } - - default: - break; - } - case WM_DESTROY: - - break; - } - return DefMDIChildProc(hWnd, message, wParam, lParam); -} -#endif - -BOOL CreatePactorWindow(struct TNCINFO * TNC, char * ClassName, char * WindowTitle, int RigControlRow, WNDPROC WndProc, int Width, int Height, VOID ForcedCloseProc()) -{ -#ifdef LINBPQ - return FALSE; -#else - WNDCLASS wc; - char Title[80]; - int retCode, Type, Vallen; - HKEY hKey=0; - char Key[80]; - char Size[80]; - int Top, Left; - HANDLE hDlg = 0; - static int LP = 1235; - - if (TNC->hDlg) - { - ShowWindow(TNC->hDlg, SW_SHOWNORMAL); - SetForegroundWindow(TNC->hDlg); - return FALSE; // Already open - } - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; - wc.lpfnWndProc = WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = bgBrush; - wc.lpszMenuName = NULL; - wc.lpszClassName = ClassName; - - RegisterClass(&wc); - -// if (TNC->Hardware == H_WINMOR || TNC->Hardware == H_TELNET ||TNC->Hardware == H_ARDOP || -// TNC->Hardware == H_V4 || TNC->Hardware == H_FLDIGI || TNC->Hardware == H_UIARQ || TNC->Hardware == H_VARA) - if (TNC->PortRecord) - sprintf(Title, "%s Status - Port %d %s", WindowTitle, TNC->Port, TNC->PortRecord->PORTCONTROL.PORTDESCRIPTION); - else - sprintf(Title, "Rigcontrol"); - - if (TNC->Hardware == H_MPSK) - sprintf(Title, "Rigcontrol for MultiPSK Port %d", TNC->Port); - - TNC->hDlg = hDlg = CreateMDIWindow(ClassName, Title, 0, - 0, 0, Width, Height, ClientWnd, hInstance, ++LP); - - // CreateDialog(hInstance,ClassName,0,NULL); - - Rect.top = 100; - Rect.left = 20; - Rect.right = Width + 20; - Rect.bottom = Height + 100; - - - sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\PACTOR\\PORT%d", TNC->Port); - - retCode = RegOpenKeyEx (REGTREE, Key, 0, KEY_QUERY_VALUE, &hKey); - - if (retCode == ERROR_SUCCESS) - { - Vallen=80; - - retCode = RegQueryValueEx(hKey,"Size",0, - (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); - - if (retCode == ERROR_SUCCESS) - { - sscanf(Size,"%d,%d,%d,%d,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom, &TNC->Minimized); - - if (Rect.top < - 500 || Rect.left < - 500) - { - Rect.left = 0; - Rect.top = 0; - Rect.right = 600; - Rect.bottom = 400; - } - - if (Rect.top < OffsetH) - { - int Error = OffsetH - Rect.top; - Rect.top += Error; - Rect.bottom += Error; - } - } - - if (TNC->Hardware == H_WINMOR || TNC->Hardware == H_ARDOP|| TNC->Hardware == H_VARA) - retCode = RegQueryValueEx(hKey,"TNC->RestartAfterFailure",0, - (ULONG *)&Type,(UCHAR *)&TNC->RestartAfterFailure,(ULONG *)&Vallen); - - RegCloseKey(hKey); - } - - Top = Rect.top; - Left = Rect.left; - -// GetWindowRect(hDlg, &Rect); // Get the real size - - MoveWindow(hDlg, Left - (OffsetW /2), Top - OffsetH, Rect.right - Rect.left, Rect.bottom - Rect.top, TRUE); - - if (TNC->Minimized) - ShowWindow(hDlg, SW_SHOWMINIMIZED); - else - ShowWindow(hDlg, SW_RESTORE); - - TNC->RigControlRow = RigControlRow; - - SetWindowText(TNC->xIDC_TNCSTATE, "Free"); - - TNC->ForcedCloseProc = ForcedCloseProc; - - return TRUE; -#endif -} - - -// WL2K Reporting Code. - -static SOCKADDR_IN sinx; - - -VOID SendReporttoWL2KThread(void * unused); -VOID SendHTTPReporttoWL2KThread(void * unused); - -VOID CheckWL2KReportTimer() -{ - if (WL2KReports == NULL) - return; // Shouldn't happen! - - WL2KTimer--; - - if (WL2KTimer != 0) - return; - -#ifdef WIN32 - WL2KTimer = 2 * 32910; // Every 2 Hours - PC Tick is a bit slow -#else - WL2KTimer = 2 * 36000; // Every 2 Hours -#endif - - if (CheckAppl(NULL, "RMS ") == NULL) - if (CheckAppl(NULL, "RELAY ") == NULL) - return; - - _beginthread(SendHTTPReporttoWL2KThread, 0, 0); - - return; -} - -static char HeaderTemplate[] = "POST %s HTTP/1.1\r\n" - "Accept: application/json\r\n" -// "Accept-Encoding: gzip,deflate,gzip, deflate\r\n" - "Content-Type: application/json\r\n" - "Host: %s:%d\r\n" - "Content-Length: %d\r\n" - //r\nUser-Agent: BPQ32(G8BPQ)\r\n" -// "Expect: 100-continue\r\n" - "\r\n{%s}"; - -char Missing[] = "** Missing **"; - -VOID GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value) -{ - char * ptr1, * ptr2; - - strcpy(Value, Missing); - - ptr1 = strstr(_REPLYBUFFER, Name); - - if (ptr1 == 0) - return; - - ptr1 += (strlen(Name) + 1); - - ptr2 = strchr(ptr1, '"'); - - if (ptr2) - { - size_t ValLen = ptr2 - ptr1; - memcpy(Value, ptr1, ValLen); - Value[ValLen] = 0; - } - - return; -} - - -// Send Winlink Session Record - -extern char LOC[7]; -extern char TextVerstring[50]; - -double Distance(double laa, double loa, double lah, double loh, BOOL KM); -double Bearing(double lat2, double lon2, double lat1, double lon1); -VOID SendHTTPRequest(SOCKET sock, char * Request, char * Params, int Len, char * Return); -SOCKET OpenWL2KHTTPSock(); - - - -struct WL2KMode -{ - int Mode; - char * WL2KString; - char * ADIFString; - char * BPQString; -}; - -struct WL2KMode WL2KModeList[] = -{ - {0,"Packet 1200"}, - {1,"Packet 2400"}, - {2, "Packet 4800"}, - {3, "Packet 9600"}, - {4, "Packet 19200"}, - {5, "Packet 38400"}, - {11, "Pactor 1"}, - {12, "Pactor 1,2"}, - {13, "Pactor 1,2,3"}, - {14, "Pactor 2"}, - {15, "Pactor 2,3"}, - {16, "Pactor 3"}, - {17, "Pactor 1,2,3,4"}, - {18, "Pactor 2,3,4"}, - {19, "Pactor 3,4"}, - {20, "Pactor 4"}, - {21, "WINMOR 500"}, - {22, "WINMOR 1600"}, - {30, "Robust Packet"}, - {40, "ARDOP 200"}, - {41, "ARDOP 500"}, - {42, "ARDOP 1000"}, - {43, "ARDOP 2000"}, - {44, "ARDOP 2000 FM"}, - {50, "VARA"}, - {51, "VARA FM"}, - {52, "VARA FM WIDE"}, - {53, "VARA 500"} -}; - -char WL2KModes [55][18] = { - "Packet 1200", "Packet 2400", "Packet 4800", "Packet 9600", "Packet 19200", "Packet 38400", "High Speed Packet", "", "", "", "", - "Pactor 1", "Pactor", "Pactor", "Pactor 2", "Pactor", "Pactor 3", "Pactor", "Pactor", "Pactor", "Pactor 4", // 11 - 20 - "Winmor 500", "Winmor 1600", "", "", "", "", "", "", "", // 21 - 29 - "Robust Packet", "", "", "", "", "", "", "", "", "", // 30 - 39 - "ARDOP 200", "ARDOP 500", "ARDOP 1000", "ARDOP 2000", "ARDOP 2000 FM", "", "", "", "", "", // 40 - 49 - "VARA", "VARA FM", "VARA FM WIDE", "VARA 500", "VARA 2750"}; - - -VOID SendWL2KSessionRecordThread(void * param) -{ - SOCKET sock; - char Message[512]; - - strcpy(Message, param); - free(param); - - Debugprintf("Sending %s", Message); - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - SendHTTPRequest(sock, "/session/add", (char *)Message, (int)strlen(Message), NULL); - closesocket(sock); - } - - return; -} - -VOID SendWL2KRegisterHybridThread(void * param) -{ - SOCKET sock; - char Message[512]; - - strcpy(Message, param); - free(param); - - Debugprintf("Sending %s", Message); - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - SendHTTPRequest(sock, "/radioNetwork/params/add", (char *)Message, (int)strlen(Message), NULL); - closesocket(sock); - } - - return; -} - -VOID SendWL2KRegisterHybrid(struct TNCINFO * TNC) -{ - char Message[512]; - char Date[80] ; - int Len; - struct TCPINFO * TCP = TNC->TCPInfo; - time_t T; - struct tm * tm; - char Call[10]; - - if (TCP == NULL || TCP->GatewayLoc[0] == 0) - return; - - strcpy(Call, TCP->GatewayCall); - strlop(Call, '-'); - - T = time(NULL); - tm = gmtime(&T); - - //2021-10-31-14=35=29 - - sprintf(Date, "%04d-%02d-%02d-%02d:%02d:%02d", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - -// "Callsign":"String","Password":"String","Param":"String","Value":"String","Key":"String" - - Len = sprintf(Message, "\"Callsign\":\"%s\",\"Password\":\"%s\",\"Param\":\"RMSRelayVersion\",\"Value\":\"%s|%s|*HARMNNNN|%s|%s|\"", - Call, TCP->SecureCMSPassword, Date, "3.1.11.2", - TCP->HybridServiceCode, TCP->GatewayLoc); - - SendWL2KRegisterHybridThread(_strdup(Message)); - - Len = sprintf(Message, "\"Callsign\":\"%s\",\"Password\":\"%s\",\"Param\":\"CoLocatedRMS\",\"Value\":\"%s\"", - Call, TCP->SecureCMSPassword, TCP->HybridCoLocatedRMS); - - SendWL2KRegisterHybridThread(_strdup(Message)); - - Len = sprintf(Message, "\"Callsign\":\"%s\",\"Password\":\"%s\",\"Param\":\"AllowFreq\",\"Value\":\"%s\"", - Call, TCP->SecureCMSPassword, TCP->HybridFrequencies); - - SendWL2KRegisterHybridThread(_strdup(Message)); - - return; -} - -BOOL NoSessionAccount = FALSE; -BOOL SessionAccountChecked = FALSE; - -BOOL SendWL2KSessionRecord(ADIF * ADIF, int BytesSent, int BytesReceived) -{ -/* -The API is /session/add https://api.winlink.org/json/metadata?op=SessionAdd - -The important parameters are (others can be omitted): - -Application (gateway program name) -Server (gateway callsign) -ServerGrid -Client (client callsign) -ClientGrid -Mode (Pactor, winmor, vara, etc) -Frequency -MessagesSent -MessagesReceived -BytesSent -BytesReceived -HoldingSeconds (duration of connection) -IdTag (random alphanumeric, 12 chars) - -"Application":"RMS Trimode", -"Version":"1.3.25.0", -"Cms":"CMS-A", -"Server":"AB4NX", -"ServerGrid":"EM73WT", -"Client":"VE2SCA","ClientGrid":"", -"Sid":"","Mode":"WINMOR16", -"Frequency":10145000, -"Kilometers":0, -"Degrees":0, -"LastCommand":">", -"MessagesSent":0, -"MessagesReceived":0, -"BytesSent":179, -"BytesReceived":0, -"HoldingSeconds":126, -"IdTag":"ATK9S3QGL2E1"} -*/ - time_t T; - - char Message[4096] = ""; - char * MessagePtr; - int MessageLen; - int Dist = 0; - int intBearing = 0; - - double Lat, Lon; - double myLat, myLon; - - char Tag[32]; - - SOCKET sock; - char Response[1024]; - int Len; - - // Only report if the CMSCall has a WL2KAccount - - if (NoSessionAccount) - return TRUE; - - if (!SessionAccountChecked) - { - // only check once - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - SessionAccountChecked = TRUE; - - Len = sprintf(Message, "\"Callsign\":\"%s\"", ADIF->CMSCall); - - SendHTTPRequest(sock, "/account/exists", Message, Len, Response); - closesocket(sock); - - if (strstr(Response, "false")) - { - WritetoConsole("WL2K Traffic Reporting disabled - Gateway "); - WritetoConsole(ADIF->CMSCall); - WritetoConsole(" does not have a Winlink Account\r\n"); - Debugprintf("WL2K Traffic Reporting disabled - Gateway %s does not have a Winlink Account", ADIF->CMSCall); - NoSessionAccount = TRUE; - return TRUE; - } - } - } - - if (ADIF == NULL || ADIF->LOC[0] == 0 || ADIF->Call[0] == 0) - return TRUE; - - if (ADIF->StartTime == 0 || ADIF->ServerSID[0] == 0 || ADIF->CMSCall[0] == 0) - return TRUE; - - T = time(NULL); - - // Extract Info we need - - // Distance and Bearing - - if (LOC[0] && ADIF->LOC[0]) - { - if (FromLOC(LOC, &myLat, &myLon) == 0) // Basic checks on LOCs - return TRUE; - if (FromLOC(ADIF->LOC, &Lat, &Lon) == 0) - return TRUE; - - Dist = (int)Distance(myLat, myLon, Lat, Lon, TRUE); - intBearing = (int)Bearing(Lat, Lon, myLat, myLon); - } - - MessageLen = sprintf(Message, "\"Application\":\"%s\",", "BPQ32"); - MessageLen += sprintf(&Message[MessageLen], "\"Version\":\"%s\",", TextVerstring); - MessageLen += sprintf(&Message[MessageLen], "\"Cms\":\"%s\",", "CMS"); - MessageLen += sprintf(&Message[MessageLen], "\"Server\":\"%s\",", ADIF->CMSCall); - MessageLen += sprintf(&Message[MessageLen], "\"ServerGrid\":\"%s\",", LOC); - MessageLen += sprintf(&Message[MessageLen], "\"Client\":\"%s\",", ADIF->Call); - MessageLen += sprintf(&Message[MessageLen], "\"ClientGrid\":\"%s\",", ADIF->LOC); - MessageLen += sprintf(&Message[MessageLen], "\"Sid\":\"%s\",", ADIF->UserSID); - MessageLen += sprintf(&Message[MessageLen], "\"Mode\":\"%s\",", WL2KModes[ADIF->Mode]); - MessageLen += sprintf(&Message[MessageLen], "\"Frequency\":%lld,", ADIF->Freq); - MessageLen += sprintf(&Message[MessageLen], "\"Kilometers\":%d,", Dist); - MessageLen += sprintf(&Message[MessageLen], "\"Degrees\":%d,", intBearing); - MessageLen += sprintf(&Message[MessageLen], "\"LastCommand\":\"%s\",", ADIF->Termination); - MessageLen += sprintf(&Message[MessageLen], "\"MessagesSent\":%d,", ADIF->Sent); - MessageLen += sprintf(&Message[MessageLen], "\"MessagesReceived\":%d,", ADIF->Received); - MessageLen += sprintf(&Message[MessageLen], "\"BytesSent\":%d,", BytesSent); - MessageLen += sprintf(&Message[MessageLen], "\"BytesReceived\":%d,", BytesReceived); - MessageLen += sprintf(&Message[MessageLen], "\"HoldingSeconds\":%d,", (int)(T - ADIF->StartTime)); - sprintf(Tag, "%012X", (int)T * (rand() + 1)); - MessageLen += sprintf(&Message[MessageLen], "\"IdTag\":\"%s\"", Tag); - - MessagePtr = _strdup(Message); - _beginthread(SendWL2KSessionRecordThread, 0, (void *)MessagePtr); - - return TRUE; -} - -char APIKey[] = ",\"Key\":\"0D0C7AD6B38C45A7A9534E67111C38A7\""; - - -VOID SendHTTPRequest(SOCKET sock, char * Request, char * Params, int Len, char * Return) -{ - int InputLen = 0; - int inptr = 0; - char Buffer[2048]; - char Header[2048]; - char * ptr, * ptr1; - int Sent; - - strcat(Params, APIKey); - Len += (int)strlen(APIKey); - - sprintf(Header, HeaderTemplate, Request, "api.winlink.org", 80, Len + 2, Params); - Sent = send(sock, Header, (int)strlen(Header), 0); - - if (Sent == -1) - { - int Err = WSAGetLastError(); - Debugprintf("Error %d from WL2K Update send()", Err); - return; - } - - while (InputLen != -1) - { - InputLen = recv(sock, &Buffer[inptr], 2048 - inptr, 0); - - if (InputLen == -1 || InputLen == 0) - { - int Err = WSAGetLastError(); - Debugprintf("Error %d from WL2K Update recv()", Err); - return; - } - - // As we are using a persistant connection, can't look for close. Check - // for complete message - - inptr += InputLen; - - Buffer[inptr] = 0; - - ptr = strstr(Buffer, "\r\n\r\n"); - - if (ptr) - { - // got header - - int Hddrlen = (int)(ptr - Buffer); - - ptr1 = strstr(Buffer, "Content-Length:"); - - if (ptr1) - { - // Have content length - - int ContentLen = atoi(ptr1 + 16); - - if (ContentLen + Hddrlen + 4 == inptr) - { - // got whole response - - if (strstr(Buffer, " 200 OK")) - { - if (Return) - { - memcpy(Return, ptr + 4, ContentLen); - Return[ContentLen] = 0; - } - else - Debugprintf("WL2K Database update ok"); - - } - else - { - strlop(Buffer, 13); - Debugprintf("WL2K Update Params - %s", Params); - Debugprintf("WL2K Update failed - %s", Buffer); - } - return; - } - } - else - { - ptr1 = strstr(_strlwr(Buffer), "transfer-encoding:"); - - if (ptr1) - { - // Just accept anything until I've sorted things with Lee - Debugprintf("%s", ptr1); - Debugprintf("WL2K Database update ok"); - return; - } - } - } - } -} - -BOOL WL2KAccountChecked = FALSE; -BOOL NoWL2KAccount = FALSE; - -VOID SendHTTPReporttoWL2KThread(void * unused) -{ - // Uses HTTP/JSON Interface - - struct WL2KInfo * WL2KReport = WL2KReports; - char * LastHost = NULL; - char * LastRMSCall = NULL; - char Message[512]; - int LastSocket = 0; - SOCKET sock = 0; - struct sockaddr_in destaddr; - int addrlen=sizeof(sinx); - struct hostent * HostEnt; - int err; - u_long param=1; - BOOL bcopt=TRUE; - int Len; - - // Send all reports in list - - char Response[1024]; - - // Only report if the CMSCall has a WL2KAccount - - if (NoWL2KAccount) - return; - - if (!WL2KAccountChecked) - { - // only check once - - sock = OpenWL2KHTTPSock(); - - if (sock) - { - WL2KAccountChecked = TRUE; - - Len = sprintf(Message, "\"Callsign\":\"%s\"", - WL2KReport->BaseCall); - - SendHTTPRequest(sock, "/account/exists", Message, Len, Response); - closesocket(sock); - - if (strstr(Response, "false")) - { - WritetoConsole("WL2K Reporting disabled - Gateway "); - WritetoConsole(WL2KReport->BaseCall); - WritetoConsole(" does not have a Winlink Account\r\n"); - NoWL2KAccount = TRUE; - return; - } - } - } - - while (WL2KReport) - { - // Resolve Name if needed - - if (LastHost && strcmp(LastHost, WL2KReport->Host) == 0) // Same host? - goto SameHost; - - // New Host - Connect to it - - LastHost = WL2KReport->Host; - - destaddr.sin_family = AF_INET; - destaddr.sin_addr.s_addr = inet_addr(WL2KReport->Host); - destaddr.sin_port = htons(WL2KReport->WL2KPort); - - if (destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - Debugprintf("Resolving %s", WL2KReport->Host); - HostEnt = gethostbyname (WL2KReport->Host); - - if (!HostEnt) - { - err = WSAGetLastError(); - - Debugprintf("Resolve Failed for %s %d %x", WL2KReport->Host, err, err); - return; // Resolve failed - } - - memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - - // Allocate a Socket entry - - if (sock) - closesocket(sock); - - sock = socket(AF_INET, SOCK_STREAM, 0); - - if (sock == INVALID_SOCKET) - return; - -// ioctlsocket(sock, FIONBIO, ¶m); - - setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char FAR *)&bcopt, 4); - - destaddr.sin_family = AF_INET; - - if (sock == INVALID_SOCKET) - { - sock = 0; - return; - } - - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); - - // Connect to Host - - if (connect(sock,(LPSOCKADDR) &destaddr, sizeof(destaddr)) != 0) - { - err=WSAGetLastError(); - - // - // Connect failed - // - - Debugprintf("Connect Failed"); - closesocket(sock); - sock = 0; - break; - } - - SameHost: - - Len = sprintf(Message, - "\"Callsign\":\"%s\"," - "\"BaseCallsign\":\"%s\"," - "\"GridSquare\":\"%s\"," - "\"Frequency\":%lld," - "\"Mode\":%d," - "\"Baud\":%d," - "\"Power\":%d," - "\"Height\":%d," - "\"Gain\":%d," - "\"Direction\":%d," - "\"Hours\":\"%s\"," - "\"ServiceCode\":\"%s\"", - - WL2KReport->RMSCall, WL2KReport->BaseCall, WL2KReport->GridSquare, - WL2KReport->Freq, WL2KReport->mode, WL2KReport->baud, WL2KReport->power, - WL2KReport->height, WL2KReport->gain, WL2KReport->direction, - WL2KReport->Times, WL2KReport->ServiceCode); - - Debugprintf("Sending %s", Message); - - SendHTTPRequest(sock, "/channel/add", Message, Len, NULL); - - - // Send Version Message - - - if (LastRMSCall == NULL || strcmp(WL2KReport->RMSCall, LastRMSCall) != 0) - { - int Len; - - LastRMSCall = WL2KReport->RMSCall; - - // "Callsign":"String","Program":"String","Version":"String","Comments":"String" - - Len = sprintf(Message, "\"Callsign\":\"%s\",\"Program\":\"BPQ32\"," - "\"Version\":\"%d.%d.%d.%d\",\"Comments\":\"Test Comment\"", - WL2KReport->RMSCall, Ver[0], Ver[1], Ver[2], Ver[3]); - - Debugprintf("Sending %s", Message); - - SendHTTPRequest(sock, "/version/add", Message, Len, NULL); - } - - WL2KReport = WL2KReport->Next; - } - - Sleep(100); - closesocket(sock); - sock = 0; - -} - -struct WL2KInfo * DecodeWL2KReportLine(char * buf) -{ - //06'', '', '', , , , , - // , , , '', , '' - - // WL2KREPORT service, api.winlink.org, 80, GM8BPQ, IO68VL, 00-23, 144800000, PKT1200, 10, 20, 5, 0, BPQTEST - - char * Context; - char * p_cmd; - char * param; - char errbuf[256]; - struct WL2KInfo * WL2KReport = zalloc(sizeof(struct WL2KInfo)); - char * ptr; - char Param[8][256]; - char * ptr1, * ptr2; - int n = 0; - - memset(Param, 0, 2048); - - strcpy(errbuf, buf); - - p_cmd = strtok_s(&buf[10], ", \t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - - strcpy(WL2KReport->ServiceCode, p_cmd); - - // Can default Host and Port, so cant use strtok for them - - ptr1 = Context; - - while (ptr1 && *ptr1 && n < 2) - { - while(ptr1 && *ptr1 && *ptr1 == ' ') - ptr1++; - - ptr2 = strchr(ptr1, ','); - if (ptr2) *ptr2++ = 0; - - strcpy(&Param[n][0], ptr1); - strlop(Param[n++], ' '); - ptr1 = ptr2; - - } - - if (n < 2) - goto BadLine; - - if (Param[1][0] == 0) - WL2KReport->WL2KPort = 80; // HTTP Interface - else - WL2KReport->WL2KPort = atoi(&Param[1][0]); - - if (Param[0][0] == 0) - WL2KReport->Host = _strdup("api.winlink.org"); - else - { - _strlwr(&Param[0][0]); - - if (strstr(&Param[0][0], "winlink.org")) - { - WL2KReport->WL2KPort = 80; // HTTP Interface - WL2KReport->Host = _strdup("api.winlink.org"); - } - else - WL2KReport->Host = _strdup(&Param[0][0]); - } - - Context = ptr1; - - p_cmd = strtok_s(NULL, ", \t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - - if (WL2KReport->WL2KPort == 0) goto BadLine; - - strcpy(WL2KReport->RMSCall, p_cmd); - strcpy(WL2KReport->BaseCall, p_cmd); - strlop(WL2KReport->BaseCall, '-'); // Remove any SSID - - strcpy(WL2KCall, WL2KReport->BaseCall); // For SYSOP Update - - p_cmd = strtok_s(NULL, " ,\t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - if (strlen(p_cmd) != 6) goto BadLine; - - strcpy(WL2KReport->GridSquare, p_cmd); - strcpy(WL2KLoc, p_cmd); - - p_cmd = strtok_s(NULL, " ,\t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - if (strlen(p_cmd) > 79) goto BadLine; - - // Convert any : in times to comma - - ptr = strchr(p_cmd, ':'); - - while (ptr) - { - *ptr = ','; - ptr = strchr(p_cmd, ':'); - } - - strcpy(WL2KReport->Times, p_cmd); - - p_cmd = strtok_s(NULL, " ,\t\n\r", &Context); - if (p_cmd == NULL) goto BadLine; - - WL2KReport->Freq = strtoll(p_cmd, NULL, 10); - - if (WL2KReport->Freq == 0) // Invalid - goto BadLine; - - param = strtok_s(NULL, " ,\t\n\r", &Context); - - // Mode Designator - one of - - // PKTnnnnnn - // WINMOR500 - // WINMOR1600 - // ROBUST - // P1 P12 P123 P1234 etc - - if (memcmp(param, "PKT", 3) == 0) - { - int Speed, Mode; - - Speed = atoi(¶m[3]); - - WL2KReport->baud = Speed; - - if (Speed <= 1200) - Mode = 0; // 1200 - else if (Speed <= 2400) - Mode = 1; // 2400 - else if (Speed <= 4800) - Mode = 2; // 4800 - else if (Speed <= 9600) - Mode = 3; // 9600 - else if (Speed <= 19200) - Mode = 4; // 19200 - else if (Speed <= 38400) - Mode = 5; // 38400 - else - Mode = 6; // >38400 - - WL2KReport->mode = Mode; - } - else if (_stricmp(param, "WINMOR500") == 0) - WL2KReport->mode = 21; - else if (_stricmp(param, "WINMOR1600") == 0) - WL2KReport->mode = 22; - else if (_stricmp(param, "ROBUST") == 0) - { - WL2KReport->mode = 30; - WL2KReport->baud = 600; - } - else if (_stricmp(param, "ARDOP200") == 0) - WL2KReport->mode = 40; - else if (_stricmp(param, "ARDOP500") == 0) - WL2KReport->mode = 41; - else if (_stricmp(param, "ARDOP1000") == 0) - WL2KReport->mode = 42; - else if (_stricmp(param, "ARDOP2000") == 0) - WL2KReport->mode = 43; - else if (_stricmp(param, "ARDOP2000FM") == 0) - WL2KReport->mode = 44; - else if (_stricmp(param, "P1") == 0) - WL2KReport->mode = 11; - else if (_stricmp(param, "P12") == 0) - WL2KReport->mode = 12; - else if (_stricmp(param, "P123") == 0) - WL2KReport->mode = 13; - else if (_stricmp(param, "P2") == 0) - WL2KReport->mode = 14; - else if (_stricmp(param, "P23") == 0) - WL2KReport->mode = 15; - else if (_stricmp(param, "P3") == 0) - WL2KReport->mode = 16; - else if (_stricmp(param, "P1234") == 0) - WL2KReport->mode = 17; - else if (_stricmp(param, "P234") == 0) - WL2KReport->mode = 18; - else if (_stricmp(param, "P34") == 0) - WL2KReport->mode = 19; - else if (_stricmp(param, "P4") == 0) - WL2KReport->mode = 20; - else if (_stricmp(param, "VARA") == 0) - WL2KReport->mode = 50; - else if (_stricmp(param, "VARA2300") == 0) - WL2KReport->mode = 50; - else if (_stricmp(param, "VARAFM") == 0) - WL2KReport->mode = 51; - else if (_stricmp(param, "VARAFM12") == 0) - WL2KReport->mode = 51; - else if (_stricmp(param, "VARAFM96") == 0) - WL2KReport->mode = 52; - else if (_stricmp(param, "VARA500") == 0) - WL2KReport->mode = 53; - else if (_stricmp(param, "VARA2750") == 0) - WL2KReport->mode = 54; - else - goto BadLine; - - param = strtok_s(NULL, " ,\t\n\r", &Context); - - // Optional Params - - WL2KReport->power = (param)? atoi(param) : 0; - param = strtok_s(NULL, " ,\t\n\r", &Context); - WL2KReport->height = (param)? atoi(param) : 0; - param = strtok_s(NULL, " ,\t\n\r", &Context); - WL2KReport->gain = (param)? atoi(param) : 0; - param = strtok_s(NULL, " ,\t\n\r", &Context); - WL2KReport->direction = (param)? atoi(param) : 0; - - WL2KTimer = 60; - - WL2KReport->Next = WL2KReports; - WL2KReports = WL2KReport; - - return WL2KReport; - -BadLine: - - WritetoConsole(" Bad config record "); - WritetoConsole(errbuf); - WritetoConsole("\r\n"); - - return 0; -} - -VOID UpdateMHSupport(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction, char * Loc, BOOL Report, BOOL Digis); - -VOID UpdateMHwithDigis(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction) -{ - UpdateMHSupport(TNC, Call, Mode, Direction, NULL, TRUE, TRUE); -} -VOID UpdateMHEx(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction, char * LOC, BOOL Report) -{ - UpdateMHSupport(TNC, Call, Mode, Direction, LOC, Report, FALSE); -} - -VOID UpdateMH(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction) -{ - UpdateMHSupport(TNC, Call, Mode, Direction, NULL, TRUE, FALSE); -} - -VOID UpdateMHSupport(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction, char * Loc, BOOL Report, BOOL Digis) -{ - PMHSTRUC MH = TNC->PortRecord->PORTCONTROL.PORTMHEARD; - PMHSTRUC MHBASE = MH; - UCHAR AXCall[72] = ""; - int i; - char * LOC, * LOCEND; - char ReportMode[20]; - char NoLOC[7] = ""; - double Freq; - char ReportFreq[350] = ""; - int OldCount = 0; - char ReportCall[16]; - - if (MH == 0) return; - - if (Digis) - { - // Call is an ax.25 digi string not a text call - - memcpy(AXCall, Call, 7 * 9); - ReportCall[ConvFromAX25(Call, ReportCall)] = 0; - - // if this is a UI frame with a locator or APRS position - // we could derive a position from it - - } - else - { - strcpy(ReportCall, Call); - ConvToAX25(Call, AXCall); - AXCall[6] |= 1; // Set End of address - } - - // Adjust freq to centre - -// if (Mode != ' ' && TNC->RIG->Valchar[0]) - if (TNC->RIG->Valchar[0]) - { - if (TNC->Hardware == H_UZ7HO) - { - // See if we have Center Freq Info - if (TNC->AGWInfo->CenterFreq) - { - Freq = atof(TNC->RIG->Valchar) + ((TNC->AGWInfo->CenterFreq * 1.0) / 1000000.0); - } -#ifdef WIN32 - else if (TNC->AGWInfo->hFreq) - { - char Centre[16]; - double ModemFreq; - - SendMessage(TNC->AGWInfo->hFreq, WM_GETTEXT, 15, (LPARAM)Centre); - - ModemFreq = atof(Centre); - - Freq = atof(TNC->RIG->Valchar) + (ModemFreq / 1000000); - } -#endif - else - Freq = atof(TNC->RIG->Valchar) + 0.0015; // Assume 1500 - } - else - - // Not UZ7HO or Linux - - Freq = atof(TNC->RIG->Valchar) + 0.0015; - - _gcvt(Freq, 9, ReportFreq); - } - - if (TNC->Hardware == H_ARDOP) - { - LOC = memchr(Call, '[', 20); - - if (LOC) - { - LOCEND = memchr(Call, ']', 30); - if (LOCEND) - { - LOC--; - *(LOC++) = 0; - *(LOCEND) = 0; - LOC++; - if (strlen(LOC) != 6 && strlen(LOC) != 0) - { - Debugprintf("Corrupt LOC %s %s", Call, LOC); - LOC = NoLOC; - } - goto NOLOC; - } - } - } - - else if (TNC->Hardware != H_WINMOR) // Only WINMOR has a locator - { - LOC = NoLOC; - goto NOLOC; - } - - LOC = memchr(Call, '(', 20); - - if (LOC) - { - LOCEND = memchr(Call, ')', 30); - if (LOCEND) - { - LOC--; - *(LOC++) = 0; - *(LOCEND) = 0; - LOC++; - if (strlen(LOC) != 6 && strlen(LOC) != 0) - { - Debugprintf("Corrupt LOC %s %s", Call, LOC); - LOC = NoLOC; - } - } - } - else - LOC = NoLOC; - -NOLOC: - - if (Loc) - LOC = Loc; // Supplied Locator overrides - - for (i = 0; i < MHENTRIES; i++) - { - if (Mode == ' ' || Mode == '*') // Packet - { - if ((MH->MHCALL[0] == 0) || ((memcmp(AXCall, MH->MHCALL, 7) == 0) && MH->MHDIGI == Mode)) // Spare or our entry - { - OldCount = MH->MHCOUNT; - goto DoMove; - } - } - else - { - if ((MH->MHCALL[0] == 0) || ((memcmp(AXCall, MH->MHCALL, 7) == 0) && - MH->MHDIGI == Mode && strcmp(MH->MHFreq, ReportFreq) == 0)) // Spare or our entry - { - OldCount = MH->MHCOUNT; - goto DoMove; - } - } - MH++; - } - - // TABLE FULL AND ENTRY NOT FOUND - MOVE DOWN ONE, AND ADD TO TOP - - i = MHENTRIES - 1; - - // Move others down and add at front -DoMove: - - if (i != 0) // First - memmove(MHBASE + 1, MHBASE, i * sizeof(MHSTRUC)); - -// memcpy (MHBASE->MHCALL, Buffer->ORIGIN, 7 * 9); - memcpy (MHBASE->MHCALL, AXCall, 7 * 9); // Save Digis - MHBASE->MHDIGI = Mode; - MHBASE->MHTIME = time(NULL); - MHBASE->MHCOUNT = ++OldCount; - - memcpy(MHBASE->MHLocator, LOC, 6); - strcpy(MHBASE->MHFreq, ReportFreq); - - // Report to NodeMap - - if (Report == FALSE) - return; - - if (Mode == '*') - return; // Digi'ed Packet - - if (Mode == ' ') // Packet Data - { - if (TNC->PktUpdateMap == 1) - Mode = '!'; - else - return; - } - - ReportMode[0] = TNC->Hardware + '@'; - ReportMode[1] = Mode; - if (TNC->Hardware == H_HAL) - ReportMode[2] = TNC->CurrentMode; - else - ReportMode[2] = (TNC->RIG->CurrentBandWidth) ? TNC->RIG->CurrentBandWidth : '?'; - ReportMode[3] = Direction; - ReportMode[4] = 0; - - // If no position see if we have an APRS posn - - if (LOC[0] == 0) - { - double Lat, Lon; - - if (GetPosnFromAPRS(ReportCall, &Lat, &Lon) && Lat != 0.0) - { - ToLOC(Lat, Lon, LOC); - } - } - - SendMH(TNC, ReportCall, ReportFreq, LOC, ReportMode); - - return; -} - -VOID CloseDriverWindow(int port) -{ -#ifndef LINBPQ - - struct TNCINFO * TNC; - - TNC = TNCInfo[port]; - if (TNC == NULL) - return; - - if (TNC->hDlg == NULL) - return; - - PostMessage(TNC->hDlg, WM_CLOSE,0,0); -// DestroyWindow(TNC->hDlg); - - TNC->hDlg = NULL; -#endif - return; -} - -VOID SaveWindowPos(int port) -{ -#ifndef LINBPQ - - struct TNCINFO * TNC; - char Key[80]; - - TNC = TNCInfo[port]; - - if (TNC == NULL) - return; - - if (TNC->hDlg == NULL) - return; - - sprintf(Key, "PACTOR\\PORT%d", port); - - SaveMDIWindowPos(TNC->hDlg, Key, "Size", TNC->Minimized); - -#endif - return; -} - -VOID ShowTraffic(struct TNCINFO * TNC) -{ - char Status[80]; - - sprintf(Status, "RX %d TX %d ACKED %d ", - TNC->Streams[0].BytesRXed, TNC->Streams[0].BytesTXed, TNC->Streams[0].BytesAcked); -#ifndef LINBPQ - SetDlgItemText(TNC->hDlg, IDC_TRAFFIC, Status); -#endif -} - -BOOL InterlockedCheckBusy(struct TNCINFO * ThisTNC) -{ - // See if this port, or any interlocked ports are reporting channel busy - - struct TNCINFO * TNC; - int i; - int rxInterlock = ThisTNC->RXRadio; - int txInterlock = ThisTNC->TXRadio; - - if (ThisTNC->Busy) - return TRUE; // Our port is busy - - if (rxInterlock == 0 && txInterlock == 0) - return ThisTNC->Busy; // No Interlock - - for (i=1; i<33; i++) - { - TNC = TNCInfo[i]; - - if (TNC == NULL) - continue; - - if (TNC == ThisTNC) - continue; - - if (rxInterlock == TNC->RXRadio || txInterlock == TNC->TXRadio) // Same Group - if (TNC->Busy) - return TRUE; // Interlocked port is busy - - } - return FALSE; // None Busy -} - -char ChallengeResponse[13]; - -char * GetChallengeResponse(char * Call, char * ChallengeString) -{ - // Generates a response to the CMS challenge string... - - long long Challenge = _atoi64(ChallengeString); - long long CallSum = 0; - long long Mask; - long long Response; - long long XX = 1065484730; - - char CallCopy[10]; - UINT i; - - - if (Challenge == 0) - return "000000000000"; - -// Calculate Mask from Callsign - - memcpy(CallCopy, Call, 10); - strlop(CallCopy, '-'); - strlop(CallCopy, ' '); - - for (i = 0; i < strlen(CallCopy); i++) - { - CallSum += CallCopy[i]; - } - - Mask = CallSum + CallSum * 4963 + CallSum * 782386; - - Response = (Challenge % 930249781); - Response ^= Mask; - - sprintf(ChallengeResponse, "%012lld", Response); - - return ChallengeResponse; -} - -SOCKET OpenWL2KHTTPSock() -{ - SOCKET sock = 0; - struct sockaddr_in destaddr; - struct sockaddr_in sinx; - int addrlen=sizeof(sinx); - struct hostent * HostEnt; - int err; - u_long param=1; - BOOL bcopt=TRUE; - - destaddr.sin_family = AF_INET; - destaddr.sin_port = htons(80); - - // Resolve name to address - - HostEnt = gethostbyname ("api.winlink.org"); - - if (!HostEnt) - { - err = WSAGetLastError(); - - Debugprintf("Resolve Failed for %s %d %x", "api.winlink.org", err, err); - return 0 ; // Resolve failed - } - - memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - - // Allocate a Socket entry - - sock = socket(AF_INET,SOCK_STREAM,0); - - if (sock == INVALID_SOCKET) - return 0; - - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - if (bind(sock, (struct sockaddr *) &sinx, addrlen) != 0 ) - return FALSE; - - if (connect(sock,(struct sockaddr *) &destaddr, sizeof(destaddr)) != 0) - { - err=WSAGetLastError(); - closesocket(sock); - return 0; - } - - return sock; -} - -BOOL GetWL2KSYSOPInfo(char * Call, char * _REPLYBUFFER) -{ - SOCKET sock = 0; - int Len; - char Message[1000]; - - sock = OpenWL2KHTTPSock(); - - if (sock == 0) - return 0; - - // {"Callsign":"String"} - - Len = sprintf(Message, "\"Callsign\":\"%s\"", Call); - - SendHTTPRequest(sock, "/sysop/get", Message, Len, _REPLYBUFFER); - - closesocket(sock); - - return _REPLYBUFFER[0]; -} - -BOOL UpdateWL2KSYSOPInfo(char * Call, char * SQL) -{ - SOCKET sock = 0; - struct sockaddr_in destaddr; - struct sockaddr_in sinx; - int len = 100; - int addrlen=sizeof(sinx); - struct hostent * HostEnt; - int err; - u_long param=1; - BOOL bcopt=TRUE; - char Buffer[1000]; - char SendBuffer[1000]; - - destaddr.sin_family = AF_INET; - destaddr.sin_addr.s_addr = inet_addr("api.winlink.org"); - destaddr.sin_port = htons(80); - - HostEnt = gethostbyname ("api.winlink.org"); - - if (!HostEnt) - { - err = WSAGetLastError(); - - Debugprintf("Resolve Failed for %s %d %x", "api.winlink.org", err, err); - return 0 ; // Resolve failed - } - - memcpy(&destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - - // Allocate a Socket entry - - sock = socket(AF_INET,SOCK_STREAM,0); - - if (sock == INVALID_SOCKET) - return 0; - - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - if (bind(sock, (struct sockaddr *) &sinx, addrlen) != 0 ) - return FALSE; - - if (connect(sock,(struct sockaddr *) &destaddr, sizeof(destaddr)) != 0) - { - err=WSAGetLastError(); - closesocket(sock); - return 0; - } - - len = recv(sock, &Buffer[0], len, 0); - - len = sprintf(SendBuffer, "02%07d%-12s%s%s", (int)strlen(SQL), Call, GetChallengeResponse(Call, Buffer), SQL); - - send(sock, SendBuffer, len, 0); - - len = 1000; - - len = recv(sock, &Buffer[0], len, 0); - - Buffer[len] = 0; - Debugprintf(Buffer); - - closesocket(sock); - - return TRUE; - -} -// http://server.winlink.org:8085/csv/reply/ChannelList?Modes=40,41,42,43,44&ServiceCodes=BPQTEST,PUBLIC - -// Process config lines that are common to a number of HF modes - -extern int nextDummyInterlock; - -int standardParams(struct TNCINFO * TNC, char * buf) -{ - if (_memicmp(buf, "WL2KREPORT", 10) == 0) - TNC->WL2K = DecodeWL2KReportLine(buf); - else if (_memicmp(buf, "SESSIONTIMELIMIT", 16) == 0) - TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit = atoi(&buf[17]) * 60; - else if (_memicmp(buf, "BUSYHOLD", 8) == 0) // Hold Time for Busy Detect - TNC->BusyHold = atoi(&buf[8]); - else if (_memicmp(buf, "BUSYWAIT", 8) == 0) // Wait time before failing connect if busy - TNC->BusyWait = atoi(&buf[8]); - else if (_memicmp(buf, "AUTOSTARTDELAY", 14) == 0) // Time to wait for TNC to start - TNC->AutoStartDelay = atoi(&buf[15]); - else if (_memicmp(buf, "DEFAULTRADIOCOMMAND", 19) == 0) - TNC->DefaultRadioCmd = _strdup(&buf[20]); - else if (_memicmp(buf, "MYCALLS", 7) == 0) - { - TNC->LISTENCALLS = _strdup(&buf[8]); - strlop(TNC->LISTENCALLS, '\r'); - } - else if (_memicmp(buf, "MAXCONREQ", 9) == 0) // Hold Time for Busy Detect - TNC->MaxConReq = atoi(&buf[9]); - - else if (_memicmp(buf, "FREQUENCY", 9) == 0) - TNC->Frequency = _strdup(&buf[10]); - else if (_memicmp(buf, "SendTandRtoRelay", 16) == 0) - TNC->SendTandRtoRelay = atoi(&buf[17]); - else if (_memicmp(buf, "Radio", 5) == 0) // Rig Control RADIO for TX amd RX (Equiv to INTERLOCK) - TNC->RXRadio = TNC->TXRadio = atoi(&buf[6]); - else if (_memicmp(buf, "TXRadio", 7) == 0) // Rig Control RADIO for TX - TNC->TXRadio = atoi(&buf[8]); - else if (_memicmp(buf, "RXRadio", 7) == 0) // Rig Control RADIO for RXFRETRIES - TNC->RXRadio = atoi(&buf[8]); - else if (_memicmp(buf, "TXFreq", 6) == 0) // For PTT Sets Freq mode - TNC->TXFreq = strtoll(&buf[7], NULL, 10); - else if (_memicmp(buf, "DefaultFreq", 11) == 0) // For PTT Sets Freq mode - TNC->DefaultFreq = strtoll(&buf[12], NULL, 10); - else if (_memicmp(buf, "PTTONHEX", 8) == 0) - { - // Hex String to use for PTT on for this port - - char * ptr1 = &buf[9]; - char * ptr2 = TNC->PTTOn; - int i, j, len; - - _strupr(ptr1); - - TNC->PTTOnLen = len = strlen(ptr1) / 2; - - if (len < 240) - { - while ((len--) > 0) - { - i = *(ptr1++); - i -= '0'; - if (i > 9) - i -= 7; - - j = i << 4; - - i = *(ptr1++); - i -= '0'; - if (i > 9) - i -= 7; - - *(ptr2++) = j | i; - } - } - } - else if (_memicmp(buf, "PTTOFFHEX", 9) == 0) - { - // Hex String to use for PTT off - - char * ptr = &buf[10]; - char * ptr2 = TNC->PTTOff; - int i, j, len; - - _strupr(ptr); - - TNC->PTTOffLen = len = strlen(ptr) / 2; - - if (len < 240) - { - while ((len--) > 0) - { - i = *(ptr++); - i -= '0'; - if (i > 9) - i -= 7; - - j = i << 4; - - i = *(ptr++); - i -= '0'; - if (i > 9) - i -= 7; - - *(ptr2++) = j | i; - } - } - } - else - return FALSE; - - return TRUE; -} - -void DecodePTTString(struct TNCINFO * TNC, char * ptr) -{ - if (_stricmp(ptr, "CI-V") == 0) - TNC->PTTMode = PTTCI_V; - else if (_stricmp(ptr, "CAT") == 0) - TNC->PTTMode = PTTCI_V; - else if (_stricmp(ptr, "RTS") == 0) - TNC->PTTMode = PTTRTS; - else if (_stricmp(ptr, "DTR") == 0) - TNC->PTTMode = PTTDTR; - else if (_stricmp(ptr, "DTRRTS") == 0) - TNC->PTTMode = PTTDTR | PTTRTS; - else if (_stricmp(ptr, "CM108") == 0) - TNC->PTTMode = PTTCM108; - else if (_stricmp(ptr, "HAMLIB") == 0) - TNC->PTTMode = PTTHAMLIB; - else if (_stricmp(ptr, "FLRIG") == 0) - TNC->PTTMode = PTTFLRIG; -} - -extern SOCKET ReportSocket; -extern char LOCATOR[80]; -extern char ReportDest[7]; -extern int NumberofPorts; -extern struct RIGPORTINFO * PORTInfo[34]; // Records are Malloc'd - -time_t LastModeReportTime; -time_t LastFreqReportTime; - -VOID SendReportMsg(char * buff, int txlen); - -void sendModeReport() -{ - // if TNC is connected send mode and frequencies to Node Map as a MODE record - // Are we better sending scan info as a separate record ?? - - // MODE Port, HWType, Interlock - - struct PORTCONTROL * PORT = PORTTABLE; - - struct TNCINFO * TNC; - MESSAGE AXMSG; - PMESSAGE AXPTR = &AXMSG; - char Msg[300] = "MODE "; - int i, Len = 5; - - if ((CurrentSecs - LastModeReportTime) < 900) // Every 15 Mins - return; - - LastModeReportTime = CurrentSecs; - - for (i = 0; i < NUMBEROFPORTS; i++) - { - if (PORT->PROTOCOL == 10) - { - PEXTPORTDATA PORTVEC = (PEXTPORTDATA)PORT; - TNC = TNCInfo[PORT->PORTNUMBER]; - PORT = PORT->PORTPOINTER; - - if (TNC == NULL) - continue; - - if (TNC->CONNECTED == 0 && TNC->TNCOK == 0) - continue; - - if (ReportSocket == 0 || LOCATOR[0] == 0) - continue; - - if (TNC->Frequency) - Len += sprintf(&Msg[Len], "%d,%d,%d,%.6f/", TNC->Port, TNC->Hardware, TNC->RXRadio, atof(TNC->Frequency)); - else - Len += sprintf(&Msg[Len], "%d,%d,%d/", TNC->Port, TNC->Hardware, TNC->RXRadio); - - if (Len > 240) - break; - } - else - PORT = PORT->PORTPOINTER; - } - - if (Len == 5) - return; // Nothing to send - - // Block includes the Msg Header (7 bytes), Len Does not! - - memcpy(AXPTR->DEST, ReportDest, 7); - memcpy(AXPTR->ORIGIN, MYCALL, 7); - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->L2DATA, Msg, Len); - - SendReportMsg((char *)&AXMSG.DEST, Len + 16) ; -} - -void sendFreqReport(char * From) -{ - // Send info from rig control or Port Frequency info to Node Map for Mode page. - - MESSAGE AXMSG; - PMESSAGE AXPTR = &AXMSG; - char Msg[300] = "FREQ "; - int i, Len = 5, p; - - struct RIGPORTINFO * RIGPORT; - struct RIGINFO * RIG; - struct TimeScan * Band; - struct PORTCONTROL * PORT = PORTTABLE; - struct TNCINFO * TNC; - - if ((CurrentSecs - LastFreqReportTime) < 7200) // Every 2 Hours - return; - - LastFreqReportTime = CurrentSecs; - - for (p = 0; p < NumberofPorts; p++) - { - RIGPORT = PORTInfo[p]; - - for (i = 0; i < RIGPORT->ConfiguredRigs; i++) - { - int j = 1, k = 0; - - RIG = &RIGPORT->Rigs[i]; - - if (RIG->reportFreqs) - { - Len += sprintf(&Msg[Len], "%d/00:00/%s,\\|",RIG->Interlock,RIG->reportFreqs); - } - else - { - if (RIG->TimeBands) - { - Len += sprintf(&Msg[Len], "%d/",RIG->Interlock); - while (RIG->TimeBands[j]) - { - Band = RIG->TimeBands[j]; - k = 0; - - if (Band->Scanlist[0]) - { - Len += sprintf(&Msg[Len], "%02d:%02d/", Band->Start / 3600, Band->Start % 3600); - - while (Band->Scanlist[k]) - { - Len += sprintf(&Msg[Len],"%.0f,", Band->Scanlist[k]->Freq + RIG->rxOffset); - k++; - } - Len += sprintf(&Msg[Len], "\\"); - } - j++; - } - Len += sprintf(&Msg[Len], "|"); - } - } - } - } - - // Look for Port freq info - - for (i = 0; i < NUMBEROFPORTS; i++) - { - if (PORT->PROTOCOL == 10) - { - PEXTPORTDATA PORTVEC = (PEXTPORTDATA)PORT; - TNC = TNCInfo[PORT->PORTNUMBER]; - PORT = PORT->PORTPOINTER; - - if (TNC == NULL) - continue; - - if (TNC->Frequency == NULL) - continue; - - if (TNC->RIG->TimeBands && TNC->RIG->TimeBands[1]->Scanlist) - continue; // Have freq info from Rigcontrol - - if (TNC->RXRadio == 0) // Replace with dummy - TNC->RXRadio = nextDummyInterlock++; - - // Use negative port no instead of interlock group - - Len += sprintf(&Msg[Len], "%d/00:00/%.0f|", TNC->RXRadio, atof(TNC->Frequency) * 1000000.0); - } - else - PORT = PORT->PORTPOINTER; - } - - if (Len == 5) - return; // Nothing to send - - // Block includes the Msg Header (7 bytes), Len Does not! - - memcpy(AXPTR->DEST, ReportDest, 7); - memcpy(AXPTR->ORIGIN, MYCALL, 7); - AXPTR->DEST[6] &= 0x7e; // Clear End of Call - AXPTR->DEST[6] |= 0x80; // set Command Bit - - AXPTR->ORIGIN[6] |= 1; // Set End of Call - AXPTR->CTL = 3; //UI - AXPTR->PID = 0xf0; - memcpy(AXPTR->L2DATA, Msg, Len); - - SendReportMsg((char *)&AXMSG.DEST, Len + 16) ; -} - - diff --git a/HTTPcode-HPLaptop.c b/HTTPcode-HPLaptop.c deleted file mode 100644 index eaf894b..0000000 --- a/HTTPcode-HPLaptop.c +++ /dev/null @@ -1,4428 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - - -//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - -#define _CRT_SECURE_NO_DEPRECATE - -#define DllImport - -#include "CHeaders.h" -#include - -#include "tncinfo.h" -#include "time.h" -#include "bpq32.h" -#include "telnetserver.h" - -// This is needed to link with a lib built from source - -#ifdef WIN32 -#define ZEXPORT __stdcall -#endif - -#include "zlib.h" - -#define CKernel -#include "httpconnectioninfo.h" - -extern int MAXBUFFS, QCOUNT, MINBUFFCOUNT, NOBUFFCOUNT, BUFFERWAITS, L3FRAMES; -extern int NUMBEROFNODES, MAXDESTS, L4CONNECTSOUT, L4CONNECTSIN, L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES; -extern int STATSTIME; -extern TRANSPORTENTRY * L4TABLE; -extern BPQVECSTRUC BPQHOSTVECTOR[]; -extern BOOL APRSApplConnected; -extern char VersionString[]; -VOID FormatTime3(char * Time, time_t cTime); -DllExport int APIENTRY Get_APPLMASK(int Stream); -VOID SaveUIConfig(); -int ProcessNodeSignon(SOCKET sock, struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, int LOCAL); -VOID SetupUI(int Port); -VOID SendUIBeacon(int Port); -VOID GetParam(char * input, char * key, char * value); -VOID ARDOPAbort(struct TNCINFO * TNC); -VOID WriteMiniDump(); -BOOL KillTNC(struct TNCINFO * TNC); -BOOL RestartTNC(struct TNCINFO * TNC); -int GetAISPageInfo(char * Buffer, int ais, int adsb); -int GetAPRSPageInfo(char * Buffer, double N, double S, double W, double E, int aprs, int ais, int adsb); -unsigned char * Compressit(unsigned char * In, int Len, int * OutLen); -char * stristr (char *ch1, char *ch2); -int GetAPRSIcon(unsigned char * _REPLYBUFFER, char * NodeURL); -char * GetStandardPage(char * FN, int * Len); -BOOL SHA1PasswordHash(char * String, char * Hash); -char * byte_base64_encode(char *str, int len); - -extern struct ROUTE * NEIGHBOURS; -extern int ROUTE_LEN; -extern int MAXNEIGHBOURS; - -extern struct DEST_LIST * DESTS; // NODE LIST -extern int DEST_LIST_LEN; -extern int MAXDESTS; // MAX NODES IN SYSTEM - -extern struct _LINKTABLE * LINKS; -extern int LINK_TABLE_LEN; -extern int MAXLINKS; -extern char * RigWebPage; -extern COLORREF Colours[256]; - -extern BOOL IncludesMail; -extern BOOL IncludesChat; - -extern BOOL APRSWeb; -extern BOOL RigActive; - -extern char * UIUIDigi[33]; -extern char UIUIDEST[33][11]; // Dest for Beacons -extern UCHAR FN[33][256]; // Filename -extern int Interval[33]; // Beacon Interval (Mins) -extern char Message[33][1000]; // Beacon Text - -extern int MinCounter[33]; // Interval Countdown -extern BOOL SendFromFile[33]; - -extern HKEY REGTREE; - -extern BOOL APRSActive; - -extern UCHAR LogDirectory[]; - -extern struct RIGPORTINFO * PORTInfo[34]; -extern int NumberofPorts; - -char * strlop(char * buf, char delim); -VOID sendandcheck(SOCKET sock, const char * Buffer, int Len); -int CompareNode(const void *a, const void *b); -int CompareAlias(const void *a, const void *b); -void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen); -void ProcessChatHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen); -struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); -int SetupNodeMenu(char * Buff, int SYSOP); -int StatusProc(char * Buff); -int ProcessMailSignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, BOOL WebMail, int LOCAL); -int ProcessChatSignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, int LOCAL); -VOID APRSProcessHTTPMessage(SOCKET sock, char * MsgPtr, BOOL LOCAL, BOOL COOKIE); - - -static struct HTTPConnectionInfo * SessionList; // active term mode sessions - -char Mycall[10]; - -char MAILPipeFileName[] = "\\\\.\\pipe\\BPQMAILWebPipe"; -char CHATPipeFileName[] = "\\\\.\\pipe\\BPQCHATWebPipe"; - -char Index[] = "%s's BPQ32 Web Server

" -"" -"" -"
Node PagesAPRS Pages
"; - -char IndexNoAPRS[] = "" -""; - -//char APRSBit[] = "APRS Pages"; - -//char MailBit[] = "Mail Mgmt" -// "WebMail"; -//char ChatBit[] = "Chat Mgmt"; - -char Tail[] = ""; - -char RouteHddr[] = "

Routes

" -""; - -char RouteLine[] = ""; -char xNodeHddr[] = "
" -"
PortCallQualityNode CountFrame CountRetriesPercentMaxframeFrackLast HeardQueuedRem Qual
%s%d%s%c%d%d%d%d%d%%d%d%02d:%02d%d%d
" -"
" -"" -"
" -"

Nodes %s

"; - -char NodeHddr[] = "
" -"" -"" -"
" -"

Nodes %s

"; - -char NodeLine[] = ""; - - -char StatsHddr[] = "

Node Stats

%s:%s
" -""; - -char PortStatsHddr[] = "

Stats for Port %d

"; - -char PortStatsLine[] = ""; - - -char Beacons[] = "

Beacon Configuration for Port %d

You need to be signed in to save changes

%s %d
" -"" -"
" -"" -"" -"" -"" -"" -"
Send Interval (Minutes)
To
Path
Send From File
Text
" -"" - -"

" -""; - - -char LinkHddr[] = "

Links

" -""; - -char LinkLine[] = ""; - -char UserHddr[] = "

Sessions

Far CallOur CallPortax.25 stateLink Typeax.25 Version
%s%s%d%s%s%d
"; - -char UserLine[] = ""; - -char TermSignon[] = "BPQ32 Node %s Terminal Access" -"

BPQ32 Node %s Terminal Access

" -"

Please enter username and password to access the node

" -"" -"
%s%s%s
" -"" -"
User
Password
" -"

" -""; - - -char PassError[] = "

Sorry, User or Password is invalid - please try again

"; - -char BusyError[] = "

Sorry, No sessions available - please try later

"; - -char LostSession[] = "Sorry, Session had been lost - refresh page to sign in again"; -char NoSessions[] = "Sorry, No Sessions available - refresh page to try again"; - -char TermPage[] = "" -"BPQ32 Node %s" -"" -"" -"

BPQ32 Node %s

" -"
" -"

" -"" -"" -""; - -char TermOutput[] = "" -"" -"" -"" -"" -"" -"" -"
\""; - - -// font-family:monospace;background-color:black;color:lawngreen;font-size:12px - -char TermOutputTail[] = "
"; - -/* -char InputLine[] = "" -"
" -"" -"
"; -*/ -char InputLine[] = "" -"
" -"\" id=inp type=text text width=100%% name=input />" -"
"; - -static char NodeSignon[] = "BPQ32 Node SYSOP Access" -"

BPQ32 Node %s SYSOP Access

" -"

This page sets Cookies. Don't continue if you object to this

" -"

Please enter Callsign and Password to access the Node

" -"
" -"" -"" -"
User
Password
" -"

"; - - -static char MailSignon[] = "BPQ32 Mail Server Access" -"

BPQ32 Mail Server %s Access

" -"

Please enter Callsign and Password to access the BBS

" -"
" -"" -"" -"
User
Password
" -"

"; - -static char ChatSignon[] = "BPQ32 Chat Server Access" -"

BPQ32 Chat Server %s Access

" -"

Please enter Callsign and Password to access the Chat Server

" -"
" -"" -"" -"
User
Password
" -"

"; - - -static char MailLostSession[] = "" -"
" -"Sorry, Session had been lost

    " -"
"; - - -static char ConfigEditPage[] = "" -"Edit Config" -"
" -"

" -"
"; - -static char EXCEPTMSG[80] = ""; - - -void UndoTransparency(char * input) -{ - char * ptr1, * ptr2; - char c; - int hex; - - if (input == NULL) - return; - - ptr1 = ptr2 = input; - - // Convert any %xx constructs - - while (1) - { - c = *(ptr1++); - - if (c == 0) - break; - - if (c == '%') - { - c = *(ptr1++); - if(isdigit(c)) - hex = (c - '0') << 4; - else - hex = (tolower(c) - 'a' + 10) << 4; - - c = *(ptr1++); - if(isdigit(c)) - hex += (c - '0'); - else - hex += (tolower(c) - 'a' + 10); - - *(ptr2++) = hex; - } - else if (c == '+') - *(ptr2++) = 32; - else - *(ptr2++) = c; - } - *ptr2 = 0; -} - - - - -VOID PollSession(struct HTTPConnectionInfo * Session) -{ - int state, change; - int count, len; - char Msg[400] = ""; - char Formatted[8192]; - char * ptr1, * ptr2; - char c; - int Line; - - // Poll Node - - SessionState(Session->Stream, &state, &change); - - if (change == 1) - { - int Line = Session->LastLine++; - free(Session->ScreenLines[Line]); - - if (state == 1)// Connected - Session->ScreenLines[Line] = _strdup("*** Connected
\r\n"); - else - Session->ScreenLines[Line] = _strdup("*** Disconnected
\r\n"); - - if (Line == 99) - Session->LastLine = 0; - - Session->Changed = TRUE; - } - - if (RXCount(Session->Stream) > 0) - { - int realLen = 0; - - do - { - GetMsg(Session->Stream, &Msg[0], &len, &count); - - // replace cr with
and space with   - - - ptr1 = Msg; - ptr2 = &Formatted[0]; - - if (Session->PartLine) - { - // Last line was incomplete - append to it - - realLen = Session->PartLine; - - Line = Session->LastLine - 1; - - if (Line < 0) - Line = 99; - - strcpy(Formatted, Session->ScreenLines[Line]); - ptr2 += strlen(Formatted); - - Session->LastLine = Line; - Session->PartLine = FALSE; - } - - while (len--) - { - c = *(ptr1++); - realLen++; - - if (c == 13) - { - int LineLen; - - strcpy(ptr2, "
\r\n"); - - // Write to screen - - Line = Session->LastLine++; - free(Session->ScreenLines[Line]); - - LineLen = (int)strlen(Formatted); - - // if line starts with a colour code, process it - - if (Formatted[0] == 0x1b && LineLen > 1) - { - int ColourCode = Formatted[1] - 10; - COLORREF Colour = Colours[ColourCode]; - char ColString[30]; - - memmove(&Formatted[20], &Formatted[2], LineLen); - sprintf(ColString, "", GetRValue(Colour), GetGValue(Colour), GetBValue(Colour)); - memcpy(Formatted, ColString, 20); - strcat(Formatted, ""); - LineLen =+ 28; - } - - Session->ScreenLineLen[Line] = LineLen; - Session->ScreenLines[Line] = _strdup(Formatted); - - if (Line == 99) - Session->LastLine = 0; - - ptr2 = &Formatted[0]; - realLen = 0; - - } - else if (c == 32) - { - memcpy(ptr2, " ", 6); - ptr2 += 6; - - // Make sure line isn't too long - // but beware of spaces expanded to   - count chars in line - - if ((realLen) > 100) - { - strcpy(ptr2, "
\r\n"); - - Line = Session->LastLine++; - free(Session->ScreenLines[Line]); - - Session->ScreenLines[Line] = _strdup(Formatted); - - if (Line == 99) - Session->LastLine = 0; - - ptr2 = &Formatted[0]; - realLen = 0; - } - } - else if (c == '>') - { - memcpy(ptr2, ">", 4); - ptr2 += 4; - } - else if (c == '<') - { - memcpy(ptr2, "<", 4); - ptr2 += 4; - } - else - *(ptr2++) = c; - - } - - *ptr2 = 0; - - if (ptr2 != &Formatted[0]) - { - // Incomplete line - - // Save to screen - - Line = Session->LastLine++; - free(Session->ScreenLines[Line]); - - Session->ScreenLines[Line] = _strdup(Formatted); - - if (Line == 99) - Session->LastLine = 0; - - Session->PartLine = realLen; - } - - // strcat(Session->ScreenBuffer, Formatted); - Session->Changed = TRUE; - - } while (count > 0); - } -} - - -VOID HTTPTimer() -{ - // Run every tick. Check for status change and data available - - struct HTTPConnectionInfo * Session = SessionList; // active term mode sessions - struct HTTPConnectionInfo * PreviousSession = NULL; - -// inf(); - - while (Session) - { - Session->KillTimer++; - - if (Session->Key[0] != 'T') - { - PreviousSession = Session; - Session = Session->Next; - continue; - } - - if (Session->KillTimer > 3000) // Around 5 mins - { - int i; - int Stream = Session->Stream; - - for (i = 0; i < 100; i++) - { - free(Session->ScreenLines[i]); - } - - SessionControl(Stream, 2, 0); - SessionState(Stream, &i, &i); - DeallocateStream(Stream); - - if (PreviousSession) - PreviousSession->Next = Session->Next; // Remove from chain - else - SessionList = Session->Next; - - free(Session); - - break; - } - - PollSession(Session); - - // if (Session->ResponseTimer == 0 && Session->Changed) - // Debugprintf("Data to send but no outstanding GET"); - - if (Session->ResponseTimer) - { - Session->ResponseTimer--; - - if (Session->ResponseTimer == 0 || Session->Changed) - { - SOCKET sock = Session->sock; - char _REPLYBUFFER[100000]; - int ReplyLen; - char Header[256]; - int HeaderLen; - int Last = Session->LastLine; - int n; - struct TNCINFO * TNC = Session->TNC; - struct TCPINFO * TCP = 0; - - if (TNC) - TCP = TNC->TCPInfo; - - if (TCP && TCP->WebTermCSS) - sprintf(_REPLYBUFFER, TermOutput, TCP->WebTermCSS); - else - sprintf(_REPLYBUFFER, TermOutput, ""); - - for (n = Last;;) - { - strcat(_REPLYBUFFER, Session->ScreenLines[n]); - - if (n == 99) - n = -1; - - if (++n == Last) - break; - } - - ReplyLen = (int)strlen(_REPLYBUFFER); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", TermOutputTail); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, _REPLYBUFFER, ReplyLen); - - Session->ResponseTimer = Session->Changed = 0; - } - } - PreviousSession = Session; - Session = Session->Next; - } -} - -struct HTTPConnectionInfo * AllocateSession(SOCKET sock, char Mode) -{ - time_t KeyVal; - struct HTTPConnectionInfo * Session = zalloc(sizeof(struct HTTPConnectionInfo)); - int i; - - if (Session == NULL) - return NULL; - - if (Mode == 'T') - { - // Terminal - - for (i = 0; i < 20; i++) - Session->ScreenLines[i] = _strdup("Scroll to end
"); - - for (i = 20; i < 100; i++) - Session->ScreenLines[i] = _strdup("
\r\n"); - - Session->Stream = FindFreeStream(); - - if (Session->Stream == 0) - return NULL; - - SessionControl(Session->Stream, 1, 0); - } - - KeyVal = (int)sock * time(NULL); - - sprintf(Session->Key, "%c%012X", Mode, (int)KeyVal); - - if (SessionList) - Session->Next = SessionList; - - SessionList = Session; - - return Session; -} - -struct HTTPConnectionInfo * FindSession(char * Key) -{ - struct HTTPConnectionInfo * Session = SessionList; - - while (Session) - { - if (strcmp(Session->Key, Key) == 0) - return Session; - - Session = Session->Next; - } - - return NULL; -} - -void ProcessTermInput(SOCKET sock, char * MsgPtr, int MsgLen, char * Key) -{ - char _REPLYBUFFER[1024]; - int ReplyLen; - char Header[256]; - int HeaderLen; - int State; - struct HTTPConnectionInfo * Session = FindSession(Key); - int Stream; - - if (Session == NULL) - { - ReplyLen = sprintf(_REPLYBUFFER, "%s", LostSession); - } - else - { - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * end = &MsgPtr[MsgLen]; - int Line = Session->LastLine++; - char * ptr1, * ptr2; - char c; - UCHAR hex; - - struct TNCINFO * TNC = Session->TNC; - struct TCPINFO * TCP = 0; - - if (TNC) - TCP = TNC->TCPInfo; - - if (TCP && TCP->WebTermCSS) - ReplyLen = sprintf(_REPLYBUFFER, InputLine, Key, TCP->WebTermCSS); - else - ReplyLen = sprintf(_REPLYBUFFER, InputLine, Key, ""); - - - Stream = Session->Stream; - - input += 10; - ptr1 = ptr2 = input; - - // Convert any %xx constructs - - while (ptr1 != end) - { - c = *(ptr1++); - if (c == '%') - { - c = *(ptr1++); - if(isdigit(c)) - hex = (c - '0') << 4; - else - hex = (tolower(c) - 'a' + 10) << 4; - - c = *(ptr1++); - if(isdigit(c)) - hex += (c - '0'); - else - hex += (tolower(c) - 'a' + 10); - - *(ptr2++) = hex; - } - else if (c == '+') - *(ptr2++) = 32; - else - *(ptr2++) = c; - } - - end = ptr2; - - *ptr2 = 0; - - strcat(input, "
\r\n"); - - free(Session->ScreenLines[Line]); - - Session->ScreenLines[Line] = _strdup(input); - - if (Line == 99) - Session->LastLine = 0; - - *end++ = 13; - *end = 0; - - SessionStateNoAck(Stream, &State); - - if (State == 0) - { - char AXCall[10]; - SessionControl(Stream, 1, 0); - if (BPQHOSTVECTOR[Session->Stream -1].HOSTSESSION == NULL) - { - //No L4 sessions free - - ReplyLen = sprintf(_REPLYBUFFER, "%s", NoSessions); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return; - } - - ConvToAX25(Session->HTTPCall, AXCall); - ChangeSessionCallsign(Stream, AXCall); - if (Session->USER) - BPQHOSTVECTOR[Session->Stream -1].HOSTSESSION->Secure_Session = Session->USER->Secure; - else - Debugprintf("HTTP Term Session->USER is NULL"); - } - - SendMsg(Stream, input, (int)(end - input)); - Session->Changed = TRUE; - Session->KillTimer = 0; - } - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); -} - - -void ProcessTermClose(SOCKET sock, char * MsgPtr, int MsgLen, char * Key, int LOCAL) -{ - char _REPLYBUFFER[8192]; - int ReplyLen = sprintf(_REPLYBUFFER, InputLine, Key, ""); - char Header[256]; - int HeaderLen; - struct HTTPConnectionInfo * Session = FindSession(Key); - - if (Session) - { - Session->KillTimer = 99999; - } - - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n" - "\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); -} - -int ProcessTermSignon(struct TNCINFO * TNC, SOCKET sock, char * MsgPtr, int MsgLen, int LOCAL) -{ - char _REPLYBUFFER[8192]; - int ReplyLen; - char Header[256]; - int HeaderLen; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Context, * Appl; - char NoApp[] = ""; - struct TCPINFO * TCP = TNC->TCPInfo; - - if (input) - { - int i; - struct UserRec * USER; - - UndoTransparency(input); - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - goto Sendit; - } - user = strtok_s(&input[9], "&", &Context); - password = strtok_s(NULL, "=", &Context); - password = strtok_s(NULL, "&", &Context); - - Appl = strtok_s(NULL, "=", &Context); - Appl = strtok_s(NULL, "&", &Context); - - if (Appl == 0) - Appl = NoApp; - - if (password == NULL) - { - ReplyLen = sprintf(_REPLYBUFFER, TermSignon, Mycall, Mycall, Appl); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", PassError); - goto Sendit; - } - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if ((strcmp(password, USER->Password) == 0) && - ((_stricmp(user, USER->UserName) == 0 ) || (_stricmp(USER->UserName, "ANON") == 0))) - { - // ok - - struct HTTPConnectionInfo * Session = AllocateSession(sock, 'T'); - - if (Session) - { - char AXCall[10]; - ReplyLen = sprintf(_REPLYBUFFER, TermPage, Mycall, Mycall, Session->Key, Session->Key, Session->Key); - if (_stricmp(USER->UserName, "ANON") == 0) - strcpy(Session->HTTPCall, _strupr(user)); - else - strcpy(Session->HTTPCall, USER->Callsign); - ConvToAX25(Session->HTTPCall, AXCall); - ChangeSessionCallsign(Session->Stream, AXCall); - BPQHOSTVECTOR[Session->Stream -1].HOSTSESSION->Secure_Session = USER->Secure; - Session->USER = USER; - - if (USER->Appl[0]) - SendMsg(Session->Stream, USER->Appl, (int)strlen(USER->Appl)); - } - else - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", BusyError); - } - break; - } - } - - if (i == TCP->NumberofUsers) - { - // Not found - - ReplyLen = sprintf(_REPLYBUFFER, TermSignon, Mycall, Mycall, Appl); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", PassError); - } - - } - -Sendit: - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; -} - -char * LookupKey(char * Key) -{ - if (strcmp(Key, "##MY_CALLSIGN##") == 0) - { - char Mycall[10]; - memcpy(Mycall, &MYNODECALL, 10); - strlop(Mycall, ' '); - - return _strdup(Mycall); - } - return NULL; -} - - -int ProcessSpecialPage(char * Buffer, int FileSize) -{ - // replaces ##xxx### constructs with the requested data - - char * NewMessage = malloc(100000); - char * ptr1 = Buffer, * ptr2, * ptr3, * ptr4, * NewPtr = NewMessage; - int PrevLen; - int BytesLeft = FileSize; - int NewFileSize = FileSize; - char * StripPtr = ptr1; - - // strip comments blocks - - while (ptr4 = strstr(ptr1, ""); - if (ptr2) - { - PrevLen = (int)(ptr4 - ptr1); - memcpy(StripPtr, ptr1, PrevLen); - StripPtr += PrevLen; - ptr1 = ptr2 + 3; - BytesLeft = (int)(FileSize - (ptr1 - Buffer)); - } - } - - memcpy(StripPtr, ptr1, BytesLeft); - StripPtr += BytesLeft; - - BytesLeft = (int)(StripPtr - Buffer); - - FileSize = BytesLeft; - NewFileSize = FileSize; - ptr1 = Buffer; - ptr1[FileSize] = 0; - -loop: - ptr2 = strstr(ptr1, "##"); - - if (ptr2) - { - PrevLen = (int)(ptr2 - ptr1); // Bytes before special text - - ptr3 = strstr(ptr2+2, "##"); - - if (ptr3) - { - char Key[80] = ""; - int KeyLen; - char * NewText; - int NewTextLen; - - ptr3 += 2; - KeyLen = (int)(ptr3 - ptr2); - - if (KeyLen < 80) - memcpy(Key, ptr2, KeyLen); - - NewText = LookupKey(Key); - - if (NewText) - { - NewTextLen = (int)strlen(NewText); - NewFileSize = NewFileSize + NewTextLen - KeyLen; - // NewMessage = realloc(NewMessage, NewFileSize); - - memcpy(NewPtr, ptr1, PrevLen); - NewPtr += PrevLen; - memcpy(NewPtr, NewText, NewTextLen); - NewPtr += NewTextLen; - - free(NewText); - NewText = NULL; - } - else - { - // Key not found, so just leave - - memcpy(NewPtr, ptr1, PrevLen + KeyLen); - NewPtr += (PrevLen + KeyLen); - } - - ptr1 = ptr3; // Continue scan from here - BytesLeft = (int)(Buffer + FileSize - ptr3); - } - else // Unmatched ## - { - memcpy(NewPtr, ptr1, PrevLen + 2); - NewPtr += (PrevLen + 2); - ptr1 = ptr2 + 2; - } - goto loop; - } - - // Copy Rest - - memcpy(NewPtr, ptr1, BytesLeft); - NewMessage[NewFileSize] = 0; - - strcpy(Buffer, NewMessage); - free(NewMessage); - - return NewFileSize; -} - -int SendMessageFile(SOCKET sock, char * FN, BOOL OnlyifExists, int allowDeflate) -{ - int FileSize = 0, Sent, Loops = 0; - char * MsgBytes; - char MsgFile[512]; - FILE * hFile; - int ReadLen; - BOOL Special = FALSE; - int Len; - int HeaderLen; - char Header[256]; - char TimeString[64]; - char FileTimeString[64]; - struct stat STAT; - char * ptr; - char * Compressed = 0; - char Encoding[] = "Content-Encoding: deflate\r\n"; - char Type[64] = "Content-Type: text/html\r\n"; - -#ifdef WIN32 - - struct _EXCEPTION_POINTERS exinfo; - strcpy(EXCEPTMSG, "SendMessageFile"); - - __try { -#endif - - UndoTransparency(FN); - - if (strstr(FN, "..")) - { - FN[0] = '/'; - FN[1] = 0; - } - - if (strlen(FN) > 256) - { - FN[256] = 0; - Debugprintf("HTTP File Name too long %s", FN); - } - - if (strcmp(FN, "/") == 0) - if (APRSActive) - sprintf(MsgFile, "%s/HTML/index.html", BPQDirectory); - else - sprintf(MsgFile, "%s/HTML/indexnoaprs.html", BPQDirectory); - else - sprintf(MsgFile, "%s/HTML%s", BPQDirectory, FN); - - - // First see if file exists so we can override standard ones in code - - if (stat(MsgFile, &STAT) == 0 && (hFile = fopen(MsgFile, "rb"))) - { - FileSize = STAT.st_size; - - MsgBytes = zalloc(FileSize + 1); - - ReadLen = (int)fread(MsgBytes, 1, FileSize, hFile); - - fclose(hFile); - - // ft.QuadPart -= 116444736000000000; - // ft.QuadPart /= 10000000; - - // ctime = ft.LowPart; - - FormatTime3(FileTimeString, STAT.st_ctime); - } - else - { - // See if it is a hard coded file - - MsgBytes = GetStandardPage(&FN[1], &FileSize); - - if (MsgBytes) - { - if (FileSize == 0) - FileSize = strlen(MsgBytes); - - FormatTime3(FileTimeString, 0); - } - else - { - if (OnlyifExists) // Set if we dont want an error response if missing - return -1; - - Len = sprintf(Header, "HTTP/1.1 404 Not Found\r\nContent-Length: 16\r\n\r\nPage not found\r\n"); - send(sock, Header, Len, 0); - return 0; - } - } - - // if HTML file, look for ##...## substitutions - - if ((strcmp(FN, "/") == 0 || strstr(FN, "htm" ) || strstr(FN, "HTM")) && strstr(MsgBytes, "##" )) - { - FileSize = ProcessSpecialPage(MsgBytes, FileSize); - FormatTime3(FileTimeString, time(NULL)); - - } - - FormatTime3(TimeString, time(NULL)); - - ptr = FN; - - while (strchr(ptr, '.')) - { - ptr = strchr(ptr, '.'); - ++ptr; - } - - if (_stricmp(ptr, "js") == 0) - strcpy(Type, "Content-Type: text/javascript\r\n"); - - if (_stricmp(ptr, "pdf") == 0) - strcpy(Type, "Content-Type: application/pdf\r\n"); - - if (allowDeflate) - { - Compressed = Compressit(MsgBytes, FileSize, &FileSize); - } - else - { - Encoding[0] = 0; - Compressed = MsgBytes; - } - - if (_stricmp(ptr, "jpg") == 0 || _stricmp(ptr, "jpeg") == 0 || _stricmp(ptr, "png") == 0 || _stricmp(ptr, "gif") == 0 || _stricmp(ptr, "ico") == 0) - strcpy(Type, "Content-Type: image\r\n"); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n" - "Date: %s\r\n" - "Last-Modified: %s\r\n" - "%s%s" - "\r\n", FileSize, TimeString, FileTimeString, Type, Encoding); - - send(sock, Header, HeaderLen, 0); - - Sent = send(sock, Compressed, FileSize, 0); - - while (Sent != FileSize && Loops++ < 3000) // 100 secs max - { - if (Sent > 0) // something sent - { -// Debugprintf("%d out of %d sent", Sent, FileSize); - FileSize -= Sent; - memmove(Compressed, &Compressed[Sent], FileSize); - } - - Sleep(30); - Sent = send(sock, Compressed, FileSize, 0); - } - -// Debugprintf("%d out of %d sent %d loops", Sent, FileSize, Loops); - - - free (MsgBytes); - if (allowDeflate) - free (Compressed); - -#ifdef WIN32 - } -#include "StdExcept.c" - Debugprintf("Sending FIle %s", FN); -} -#endif - -return 0; -} - -VOID sendandcheck(SOCKET sock, const char * Buffer, int Len) -{ - int Loops = 0; - int Sent = send(sock, Buffer, Len, 0); - char * Copy = NULL; - - while (Sent != Len && Loops++ < 300) // 10 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, Len, Loops); - - if (Copy == NULL) - { - Copy = malloc(Len); - memcpy(Copy, Buffer, Len); - } - - if (Sent > 0) // something sent - { - Len -= Sent; - memmove(Copy, &Copy[Sent], Len); - } - - Sleep(30); - Sent = send(sock, Copy, Len, 0); - } - - if (Copy) - free(Copy); - - return; -} - -int RefreshTermWindow(struct TCPINFO * TCP, struct HTTPConnectionInfo * Session, char * _REPLYBUFFER) -{ - char Msg[400] = ""; - int HeaderLen, ReplyLen; - char Header[256]; - - PollSession(Session); // See if anything received - - if (Session->Changed) - { - int Last = Session->LastLine; - int n; - - if (TCP && TCP->WebTermCSS) - sprintf(_REPLYBUFFER, TermOutput, TCP->WebTermCSS); - else - sprintf(_REPLYBUFFER, TermOutput, ""); - - for (n = Last;;) - { - strcat(_REPLYBUFFER, Session->ScreenLines[n]); - - if (n == 99) - n = -1; - - if (++n == Last) - break; - } - - Session->Changed = 0; - - ReplyLen = (int)strlen(_REPLYBUFFER); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", TermOutputTail); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen); - sendandcheck(Session->sock, Header, HeaderLen); - sendandcheck(Session->sock, _REPLYBUFFER, ReplyLen); - - return 1; - } - else - return 0; -} - - -extern struct TNCINFO * TNCInfo[41]; - -int SetupNodeMenu(char * Buff, int LOCAL) -{ - int Len = 0, i; - struct TNCINFO * TNC; - int top = 0, left = 0; - - char NodeMenuHeader[] = "%s's BPQ32 Web Server" - "" - - "" - "

BPQ32 Node %s

" - "

" - "" - "" - "" - "" - "" - "" - "%s%s%s%s%s%s"; - - char DriverBit[] = "" - ""; - - char APRSBit[] = ""; - - char MailBit[] = "" - ""; - - char ChatBit[] = ""; - char SigninBit[] = ""; - - char NodeTail[] = - "" - "
RoutesNodesPortsLinksUsersStatsTerminalDriver WindowsStream StatusAPRS PagesMail MgmtWebMailChat MgmtSYSOP SigninEdit Config" - "
"; - - - Len = sprintf(Buff, NodeMenuHeader, Mycall); - - for (i=1; i<33; i++) - { - TNC = TNCInfo[i]; - if (TNC == NULL) - continue; - - if (TNC->WebWindowProc) - { - Len += sprintf(&Buff[Len], NodeMenuLine, i, TNC->WebWinX, TNC->WebWinY, top, left); - top += 22; - left += 22; - } - } - - Len += sprintf(&Buff[Len], NodeMenuRest, Mycall, - DriverBit, - (APRSWeb)?APRSBit:"", - (IncludesMail)?MailBit:"", (IncludesChat)?ChatBit:"", (LOCAL)?"":SigninBit, NodeTail); - - return Len; -} - -VOID SaveConfigFile(SOCKET sock , char * MsgPtr, char * Rest, int LOCAL) -{ - int ReplyLen = 0; - char * ptr, * ptr1, * ptr2, *input; - char c; - int MsgLen, WriteLen = 0; - char inputname[250]="bpq32.cfg"; - FILE *fp1; - char Header[256]; - int HeaderLen; - char Reply[4096]; - char Mess[256]; - char Backup1[MAX_PATH]; - char Backup2[MAX_PATH]; - struct stat STAT; - - input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - - if (input) - { - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - // ReplyLen = sprintf(Reply, "%s", ""); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return; - } - - ptr = strstr(input, "&Save="); - - if (ptr) - { - *ptr = 0; - - // Undo any % transparency - - ptr1 = ptr2 = input + 8; - - c = *(ptr1++); - - while (c) - { - if (c == '%') - { - int n; - int m = *(ptr1++) - '0'; - if (m > 9) m = m - 7; - n = *(ptr1++) - '0'; - if (n > 9) n = n - 7; - - c = m * 16 + n; - } - else if (c == '+') - c = ' '; - -#ifndef WIN32 - if (c != 13) // Strip CR if Linux -#endif - *(ptr2++) = c; - - c = *(ptr1++); - - } - - *(ptr2++) = 0; - - MsgLen = (int)strlen(input + 8); - - if (BPQDirectory[0] == 0) - { - strcpy(inputname, "bpq32.cfg"); - } - else - { - strcpy(inputname,BPQDirectory); - strcat(inputname,"/"); - strcat(inputname, "bpq32.cfg"); - } - - // Make a backup of the config - - // Keep 4 Generations - - strcpy(Backup2, inputname); - strcat(Backup2, ".bak.3"); - - strcpy(Backup1, inputname); - strcat(Backup1, ".bak.2"); - - DeleteFile(Backup2); // Remove old .bak.3 - MoveFile(Backup1, Backup2); // Move .bak.2 to .bak.3 - - strcpy(Backup2, inputname); - strcat(Backup2, ".bak.1"); - - MoveFile(Backup2, Backup1); // Move .bak.1 to .bak.2 - - strcpy(Backup1, inputname); - strcat(Backup1, ".bak"); - - MoveFile(Backup1, Backup2); // Move .bak to .bak.1 - - CopyFile(inputname, Backup1, FALSE); // Copy to .bak - - // Get length to compare with new length - - stat(inputname, &STAT); - - fp1 = fopen(inputname, "wb"); - - if (fp1) - { - WriteLen = (int)fwrite(input + 8, 1, MsgLen, fp1); - fclose(fp1); - } - - if (WriteLen != MsgLen) - sprintf_s(Mess, sizeof(Mess), "Failed to write Config File"); - else - sprintf_s(Mess, sizeof(Mess), "Configuration Saved, Orig Length %d New Length %d", - STAT.st_size, MsgLen); - } - - ReplyLen = sprintf(Reply, "", Mess); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - } - return; -} - -// Compress using deflate. Caller must free output buffer after use - -unsigned char * Compressit(unsigned char * In, int Len, int * OutLen) -{ - z_stream defstream; - int maxSize; - unsigned char * Out; - - defstream.zalloc = Z_NULL; - defstream.zfree = Z_NULL; - defstream.opaque = Z_NULL; - - defstream.avail_in = Len; // size of input - defstream.next_in = (Bytef *)In; // input char array - - deflateInit(&defstream, Z_BEST_COMPRESSION); - maxSize = deflateBound(&defstream, Len); - - Out = malloc(maxSize); - - defstream.avail_out = maxSize; // size of output - defstream.next_out = (Bytef *)Out; // output char array - - deflate(&defstream, Z_FINISH); - deflateEnd(&defstream); - - *OutLen = defstream.total_out; - - return Out; -} - - -int InnerProcessHTTPMessage(struct ConnectionInfo * conn) -{ - struct TCPINFO * TCP = conn->TNC->TCPInfo; - SOCKET sock = conn->socket; - char * MsgPtr = conn->InputBuffer; - int MsgLen = conn->InputLen; - int InputLen = 0; - int OutputLen = 0; - int Bufferlen; - struct HTTPConnectionInfo CI; - struct HTTPConnectionInfo * sockptr = &CI; - struct HTTPConnectionInfo * Session = NULL; - - char URL[100000]; - char * ptr; - char * encPtr = 0; - int allowDeflate = 0; - char * Compressed = 0; - char * HostPtr = 0; - - char * Context, * Method, * NodeURL, * Key; - char _REPLYBUFFER[250000]; - char Reply[250000]; - - int ReplyLen = 0; - char Header[256]; - int HeaderLen; - char TimeString[64]; - BOOL LOCAL = FALSE; - BOOL COOKIE = FALSE; - int Len; - char * WebSock = 0; - - char PortsHddr[] = "

Ports

" - ""; - - char PortLine[] = ""; - - char PortLineWithBeacon[] = "" - "\r\n"; - - char SessionPortLine[] = "" - "\r\n"; - - char PortLineWithDriver[] = "" - "\r\n"; - - - char PortLineWithBeaconAndDriver[] = "" - "" - "\r\n"; - - char RigControlLine[] = "" - "\r\n"; - - - char Encoding[] = "Content-Encoding: deflate\r\n"; - -#ifdef WIN32 - - struct _EXCEPTION_POINTERS exinfo; - strcpy(EXCEPTMSG, "ProcessHTTPMessage"); - - __try { -#endif - - Len = (int)strlen(MsgPtr); - if (Len > 100000) - return 0; - - strcpy(URL, MsgPtr); - - HostPtr = strstr(MsgPtr, "Host: "); - - WebSock = strstr(MsgPtr, "Upgrade"); - - if (HostPtr) - { - uint32_t Host; - char Hostname[32]= ""; - struct LOCALNET * LocalNet = conn->TNC->TCPInfo->LocalNets; - - HostPtr += 6; - memcpy(Hostname, HostPtr, 31); - strlop(Hostname, ':'); - Host = inet_addr(Hostname); - - if (strcmp(Hostname, "127.0.0.1") == 0) - LOCAL = TRUE; - else - { - if (conn->sin.sin_family != AF_INET6) - { - while(LocalNet) - { - uint32_t MaskedHost = conn->sin.sin_addr.s_addr & LocalNet->Mask; - if (MaskedHost == LocalNet->Network) - { - LOCAL = 1; - break; - } - LocalNet = LocalNet->Next; - } - } - } - } - - encPtr = stristr(MsgPtr, "Accept-Encoding:"); - - if (encPtr && stristr(encPtr, "deflate")) - allowDeflate = 1; - else - Encoding[0] = 0; - - ptr = strstr(MsgPtr, "BPQSessionCookie=N"); - - if (ptr) - { - COOKIE = TRUE; - Key = ptr + 17; - ptr = strchr(Key, ','); - if (ptr) - { - *ptr = 0; - Session = FindSession(Key); - *ptr = ','; - } - else - { - ptr = strchr(Key, 13); - if (ptr) - { - *ptr = 0; - Session = FindSession(Key); - *ptr = 13; - } - } - } - - if (WebSock) - { - // Websock connection request - Reply and remember state. - - char KeyMsg[128]; - char Webx[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // Fixed UID - char Hash[64] = ""; - char * Hash64; // base 64 version - char * ptr; - - //Sec-WebSocket-Key: l622yZS3n+zI+hR6SVWkPw== - - char ReplyMsg[] = - "HTTP/1.1 101 Switching Protocols\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Accept: %s\r\n" -// "Sec-WebSocket-Protocol: chat\r\n" - "\r\n"; - - ptr = strstr(MsgPtr, "Sec-WebSocket-Key:"); - - if (ptr) - { - ptr += 18; - while (*ptr == ' ') - ptr++; - - memcpy(KeyMsg, ptr, 40); - strlop(KeyMsg, 13); - strlop(KeyMsg, ' '); - strcat(KeyMsg, Webx); - - SHA1PasswordHash(KeyMsg, Hash); - Hash64 = byte_base64_encode(Hash, 20); - - conn->WebSocks = 1; - strlop(&URL[4], ' '); - strcpy(conn->WebURL, &URL[4]); - - ReplyLen = sprintf(Reply, ReplyMsg, Hash64); - - free(Hash64); - goto Returnit; - - } - } - - - ptr = strstr(URL, " HTTP"); - - if (ptr) - *ptr = 0; - - Method = strtok_s(URL, " ", &Context); - - memcpy(Mycall, &MYNODECALL, 10); - strlop(Mycall, ' '); - - - // APRS process internally - - if (_memicmp(Context, "/APRS/", 6) == 0 || _stricmp(Context, "/APRS") == 0) - { - APRSProcessHTTPMessage(sock, MsgPtr, LOCAL, COOKIE); - return 0; - } - - - if (_stricmp(Context, "/Node/Signon?Node") == 0) - { - char * IContext; - - NodeURL = strtok_s(Context, "?", &IContext); - Key = strtok_s(NULL, "?", &IContext); - - ProcessNodeSignon(sock, TCP, MsgPtr, Key, Reply, &Session, LOCAL); - return 0; - - } - - // If for Mail or Chat, check for a session, and send login screen if necessary - - // Moved here to simplify operation with both internal and external clients - - if (_memicmp(Context, "/Mail/", 6) == 0) - { - int RLen = 0; - char Appl; - char * input; - char * IContext; - - NodeURL = strtok_s(Context, "?", &IContext); - Key = strtok_s(NULL, "?", &IContext); - - if (_stricmp(NodeURL, "/Mail/Signon") == 0) - { - ReplyLen = ProcessMailSignon(TCP, MsgPtr, Key, Reply, &Session, FALSE, LOCAL); - - if (ReplyLen) - { - goto Returnit; - } - -#ifdef LINBPQ - strcpy(Context, "/Mail/Header"); -#else - strcpy(MsgPtr, "POST /Mail/Header"); -#endif - goto doHeader; - } - - if (_stricmp(NodeURL, "/Mail/Lost") == 0) - { - input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - - if (input && strstr(input, "Cancel=Exit")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - RLen = ReplyLen; - goto Returnit; - } - if (Key) - Appl = Key[0]; - - Key = 0; - } - - if (Key == 0 || Key[0] == 0) - { - // No Session - - // if not local send a signon screen, else create a user session - - if (LOCAL || COOKIE) - { - Session = AllocateSession(sock, 'M'); - - if (Session) - { - strcpy(Context, "/Mail/Header"); - goto doHeader; - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - RLen = ReplyLen; - - goto Returnit; - - } - - ReplyLen = sprintf(Reply, MailSignon, Mycall, Mycall); - - RLen = ReplyLen; - goto Returnit; - } - - Session = FindSession(Key); - - if (Session == NULL) - { - ReplyLen = sprintf(Reply, MailLostSession, Key); - RLen = ReplyLen; - goto Returnit; - } - } - - if (_memicmp(Context, "/Chat/", 6) == 0) - { - int RLen = 0; - char Appl; - char * input; - char * IContext; - - - HostPtr = strstr(MsgPtr, "Host: "); - - if (HostPtr) - { - uint32_t Host; - char Hostname[32]= ""; - struct LOCALNET * LocalNet = conn->TNC->TCPInfo->LocalNets; - - HostPtr += 6; - memcpy(Hostname, HostPtr, 31); - strlop(Hostname, ':'); - Host = inet_addr(Hostname); - - if (strcmp(Hostname, "127.0.0.1") == 0) - LOCAL = TRUE; - else while(LocalNet) - { - uint32_t MaskedHost = Host & LocalNet->Mask; - if (MaskedHost == LocalNet->Network) - { - char * rest; - LOCAL = 1; - rest = strchr(HostPtr, 13); - if (rest) - { - memmove(HostPtr + 9, rest, strlen(rest) + 1); - memcpy(HostPtr, "127.0.0.1", 9); - break; - } - } - LocalNet = LocalNet->Next; - } - } - - NodeURL = strtok_s(Context, "?", &IContext); - Key = strtok_s(NULL, "?", &IContext); - - if (_stricmp(NodeURL, "/Chat/Signon") == 0) - { - ReplyLen = ProcessChatSignon(TCP, MsgPtr, Key, Reply, &Session, LOCAL); - - if (ReplyLen) - { - goto Returnit; - } - -#ifdef LINBPQ - strcpy(Context, "/Chat/Header"); -#else - strcpy(MsgPtr, "POST /Chat/Header"); -#endif - goto doHeader; - } - - if (_stricmp(NodeURL, "/Chat/Lost") == 0) - { - input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - - if (input && strstr(input, "Cancel=Exit")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - RLen = ReplyLen; - goto Returnit; - } - if (Key) - Appl = Key[0]; - - Key = 0; - } - - if (Key == 0 || Key[0] == 0) - { - // No Session - - // if not local send a signon screen, else create a user session - - if (LOCAL || COOKIE) - { - Session = AllocateSession(sock, 'C'); - - if (Session) - { - strcpy(Context, "/Chat/Header"); - goto doHeader; - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - RLen = ReplyLen; - - goto Returnit; - - } - - ReplyLen = sprintf(Reply, ChatSignon, Mycall, Mycall); - - RLen = ReplyLen; - goto Returnit; - } - - Session = FindSession(Key); - - if (Session == NULL) - { - int Sent, Loops = 0; - ReplyLen = sprintf(Reply, MailLostSession, Key); - RLen = ReplyLen; -Returnit: - if (memcmp(Reply, "HTTP", 4) == 0) - { - // Full Header provided by appl - just send it - - // Send may block - - Sent = send(sock, Reply, ReplyLen, 0); - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(Reply, &Reply[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sock, Reply, ReplyLen, 0); - } - - return 0; - } - - // compress if allowed - - if (allowDeflate) - Compressed = Compressit(Reply, ReplyLen, &ReplyLen); - else - Compressed = Reply; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - } - -doHeader: - -#ifdef LINBPQ - - if ((_memicmp(Context, "/MAIL/", 6) == 0) || (_memicmp(Context, "/WebMail", 8) == 0)) - { - char _REPLYBUFFER[250000]; - struct HTTPConnectionInfo Dummy = {0}; - int Sent, Loops = 0; - - ReplyLen = 0; - - if (Session == 0) - Session = &Dummy; - - Session->TNC = (void *)LOCAL; // TNC only used for Web Terminal Sessions - - ProcessMailHTTPMessage(Session, Method, Context, MsgPtr, _REPLYBUFFER, &ReplyLen, MsgLen); - - if (memcmp(_REPLYBUFFER, "HTTP", 4) == 0) - { - // Full Header provided by appl - just send it - - // Send may block - - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(_REPLYBUFFER, &_REPLYBUFFER[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - } - return 0; - } - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - - // Send may block - - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - - if (Sent == -1) - return 0; - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(_REPLYBUFFER, &_REPLYBUFFER[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sock, _REPLYBUFFER, ReplyLen, 0); - } - - send(sock, Tail, (int)strlen(Tail), 0); - return 0; - - } - - if (_memicmp(Context, "/CHAT/", 6) == 0) - { - char _REPLYBUFFER[100000]; - - ReplyLen = 0; - - ProcessChatHTTPMessage(Session, Method, Context, MsgPtr, _REPLYBUFFER, &ReplyLen); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 0; - - } - - - /* - Sent = send(sock, _REPLYBUFFER, InputLen, 0); - - while (Sent != InputLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(_REPLYBUFFER, &_REPLYBUFFER[Sent], InputLen); - } - - Sleep(30); - Sent = send(sock, _REPLYBUFFER, InputLen, 0); - } - return 0; - } - */ -#else - - // Pass to MailChat if active - - if ((_memicmp(Context, "/MAIL/", 6) == 0) || (_memicmp(Context, "/WebMail", 8) == 0)) - { - // If for Mail, Pass to Mail Server via Named Pipe - - HANDLE hPipe; - - hPipe = CreateFile(MAILPipeFileName, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (hPipe == (HANDLE)-1) - { - InputLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 28\r\n\r\nMail Data is not available\r\n"); - send(sock, Reply, InputLen, 0); - } - else - { - // int Sent; - int Loops = 0; - struct HTTPConnectionInfo Dummy = {0}; - - if (Session == 0) - Session = &Dummy; - - Session->TNC = LOCAL; // TNC is only used on Web Terminal Sessions so can reuse as LOCAL flag - - WriteFile(hPipe, Session, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - WriteFile(hPipe, MsgPtr, MsgLen, &InputLen, NULL); - - - ReadFile(hPipe, Session, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - ReadFile(hPipe, Reply, 250000, &ReplyLen, NULL); - if (ReplyLen <= 0) - { - InputLen = GetLastError(); - } - - CloseHandle(hPipe); - goto Returnit; - } - return 0; - } - - if (_memicmp(Context, "/CHAT/", 6) == 0) - { - HANDLE hPipe; - - hPipe = CreateFile(CHATPipeFileName, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (hPipe == (HANDLE)-1) - { - InputLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 28\r\n\r\nChat Data is not available\r\n"); - send(sock, Reply, InputLen, 0); - } - else - { - // int Sent; - int Loops = 0; - - WriteFile(hPipe, Session, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - WriteFile(hPipe, MsgPtr, MsgLen, &InputLen, NULL); - - - ReadFile(hPipe, Session, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - ReadFile(hPipe, Reply, 100000, &ReplyLen, NULL); - if (ReplyLen <= 0) - { - InputLen = GetLastError(); - } - - CloseHandle(hPipe); - goto Returnit; - } - return 0; - } - -#endif - - NodeURL = strtok_s(NULL, "?", &Context); - - if (NodeURL == NULL) - return 0; - - if (strcmp(Method, "POST") == 0) - { - if (_stricmp(NodeURL, "/Node/freqOffset") == 0) - { - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - int port = atoi(Context); - - if (input == 0) - return 1; - - input += 4; - - if (port > 0 && port < 33) - { - struct TNCINFO * TNC = TNCInfo[port]; - char value[6]; - - if (TNC == 0) - return 1; - - TNC->TXOffset = atoi(input); -#ifdef WIN32 - sprintf(value, "%d", TNC->TXOffset); - MySetWindowText(TNC->xIDC_TXTUNEVAL, value); - SendMessage(TNC->xIDC_TXTUNE, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) TNC->TXOffset); // min. & max. positions - -#endif - } - return 1; - } - - if (_stricmp(NodeURL, "/Node/PortAction") == 0) - { - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - int port = atoi(Context); - - if (input == 0) - return 1; - - input += 4; - - if (port > 0 && port < 33) - { - struct TNCINFO * TNC = TNCInfo[port]; - - if (TNC == 0) - return 1; - - if (LOCAL == FALSE && COOKIE == FALSE) - return 1; - - if (strcmp(input, "Abort") == 0) - { - if (TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - } - else if (strcmp(input, "Kill") == 0) - { - TNC->DontRestart = TRUE; - KillTNC(TNC); - } - else if (strcmp(input, "KillRestart") == 0) - { - TNC->DontRestart = FALSE; - KillTNC(TNC); - RestartTNC(TNC); - - } - } - return 1; - } - - if (_stricmp(NodeURL, "/TermInput") == 0) - { - ProcessTermInput(sock, MsgPtr, MsgLen, Context); - return 0; - } - - if (_stricmp(NodeURL, "/Node/TermSignon") == 0) - { - ProcessTermSignon(conn->TNC, sock, MsgPtr, MsgLen, LOCAL); - } - - if (_stricmp(NodeURL, "/Node/Signon") == 0) - { - ProcessNodeSignon(sock, TCP, MsgPtr, Key, Reply, &Session, LOCAL); - return 0; - } - - if (_stricmp(NodeURL, "/Node/TermClose") == 0) - { - ProcessTermClose(sock, MsgPtr, MsgLen, Context, LOCAL); - return 0; - } - - if (_stricmp(NodeURL, "/Node/BeaconAction") == 0) - { - char Header[256]; - int HeaderLen; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - int Port; - char Param[100]; -#ifndef LINBPQ - int retCode, disp; - char Key[80]; - HKEY hKey; -#endif - struct PORTCONTROL * PORT; - int Slot = 0; - - - if (LOCAL == FALSE && COOKIE == FALSE) - { - // Send Not Authorized - - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
Not authorized - please sign in"); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; - } - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; - } - - GetParam(input, "Port", &Param[0]); - Port = atoi(&Param[1]); - PORT = GetPortTableEntryFromPortNum(Port); // Need slot not number - if (PORT) - Slot = PORT->PortSlot; - - GetParam(input, "Every", &Param[0]); - Interval[Slot] = atoi(&Param[1]); - - - //extern char * UIUIDigi[33]; - //extern char UIUIDEST[33][11]; // Dest for Beacons - //extern UCHAR FN[33][256]; // Filename - //extern int [33]; // Beacon Interval (Mins) - //extern char Message[33][1000]; // Beacon Text - - - GetParam(input, "Dest", &Param[0]); - _strupr(Param); - strcpy(UIUIDEST[Slot], &Param[1]); - - GetParam(input, "Path", &Param[0]); - _strupr(Param); - if (UIUIDigi[Slot]) - free(UIUIDigi[Slot]); - UIUIDigi[Slot] = _strdup(&Param[1]); - - GetParam(input, "File", &Param[0]); - strcpy(FN[Slot], &Param[1]); - GetParam(input, "Text", &Param[0]); - strcpy(Message[Slot], &Param[1]); - - MinCounter[Slot] = Interval[Slot]; - - SendFromFile[Slot] = 0; - - if (FN[Slot][0]) - SendFromFile[Slot] = 1; - - SetupUI(Slot); - -#ifdef LINBPQ - SaveUIConfig(); -#else - SaveUIConfig(); - - wsprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\UIUtil\\UIPort%d", Port); - - retCode = RegCreateKeyEx(REGTREE, - Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp); - - if (retCode == ERROR_SUCCESS) - { - retCode = RegSetValueEx(hKey, "UIDEST", 0, REG_SZ,(BYTE *)&UIUIDEST[Port][0], strlen(&UIUIDEST[Port][0])); - retCode = RegSetValueEx(hKey, "FileName", 0, REG_SZ,(BYTE *)&FN[Port][0], strlen(&FN[Port][0])); - retCode = RegSetValueEx(hKey, "Message", 0, REG_SZ,(BYTE *)&Message[Port][0], strlen(&Message[Port][0])); - retCode = RegSetValueEx(hKey, "Interval", 0, REG_DWORD,(BYTE *)&Interval[Port], 4); - retCode = RegSetValueEx(hKey, "SendFromFile", 0, REG_DWORD,(BYTE *)&SendFromFile[Port], 4); - retCode = RegSetValueEx(hKey, "Digis",0, REG_SZ, UIUIDigi[Port], strlen(UIUIDigi[Port])); - - RegCloseKey(hKey); - } -#endif - if (strstr(input, "Test=Test")) - SendUIBeacon(Slot); - - - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], Beacons, Port, - Interval[Slot], &UIUIDEST[Slot][0], &UIUIDigi[Slot][0], &FN[Slot][0], &Message[Slot][0], Port); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; - } - - if (_stricmp(NodeURL, "/Node/CfgSave") == 0) - { - // Save Config File - - SaveConfigFile(sock, MsgPtr, Key, LOCAL); - return 0; - } - - if (_stricmp(NodeURL, "/Node/LogAction") == 0) - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 1; - } - - - if (_stricmp(NodeURL, "/Node/ARDOPAbort") == 0) - { - int port = atoi(Context); - - if (port > 0 && port < 33) - { - struct TNCINFO * TNC = TNCInfo[port]; - - if (TNC && TNC->ForcedCloseProc) - TNC->ForcedCloseProc(TNC, 0); - - - if (TNC && TNC->WebWindowProc) - ReplyLen = TNC->WebWindowProc(TNC, _REPLYBUFFER, LOCAL); - - - ReplyLen = sprintf(Reply, "", "Ok"); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - // goto SendResp; - - // HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + strlen(Tail)); - // send(sock, Header, HeaderLen, 0); - // send(sock, _REPLYBUFFER, ReplyLen, 0); - // send(sock, Tail, strlen(Tail), 0); - - return 1; - } - - } - - send(sock, _REPLYBUFFER, InputLen, 0); - return 0; - } - - if (_stricmp(NodeURL, "/") == 0 || _stricmp(NodeURL, "/Index.html") == 0) - { - // Send if present, else use default - - Bufferlen = SendMessageFile(sock, NodeURL, TRUE, allowDeflate); // return -1 if not found - - if (Bufferlen != -1) - return 0; // We've sent it - else - { - if (APRSApplConnected) - ReplyLen = sprintf(_REPLYBUFFER, Index, Mycall, Mycall); - else - ReplyLen = sprintf(_REPLYBUFFER, IndexNoAPRS, Mycall, Mycall); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 0; - } - } - - else if (_stricmp(NodeURL, "/NodeMenu.html") == 0 || _stricmp(NodeURL, "/Node/NodeMenu.html") == 0) - { - // Send if present, else use default - - char Menu[] = "/NodeMenu.html"; - - Bufferlen = SendMessageFile(sock, Menu, TRUE, allowDeflate); // return -1 if not found - - if (Bufferlen != -1) - return 0; // We've sent it - } - - else if (_memicmp(NodeURL, "/aisdata.txt", 12) == 0) - { - char * Compressed; - ReplyLen = GetAISPageInfo(_REPLYBUFFER, 1, 1); - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: Text\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - - else if (_memicmp(NodeURL, "/aprsdata.txt", 13) == 0) - { - char * Compressed; - char * ptr; - double N, S, W, E; - int aprs = 1, ais = 1, adsb = 1; - - ptr = &NodeURL[14]; - - N = atof(ptr); - ptr = strlop(ptr, '|'); - S = atof(ptr); - ptr = strlop(ptr, '|'); - W = atof(ptr); - ptr = strlop(ptr, '|'); - E = atof(ptr); - ptr = strlop(ptr, '|'); - if (ptr) - { - aprs = atoi(ptr); - ptr = strlop(ptr, '|'); - ais = atoi(ptr); - ptr = strlop(ptr, '|'); - adsb = atoi(ptr); - } - ReplyLen = GetAPRSPageInfo(_REPLYBUFFER, N, S, W, E, aprs, ais, adsb); - - if (ReplyLen < 240000) - ReplyLen += GetAISPageInfo(&_REPLYBUFFER[ReplyLen], ais, adsb); - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: Text\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - } - - else if (_memicmp(NodeURL, "/Icon", 5) == 0 && _memicmp(&NodeURL[10], ".png", 4) == 0) - { - // APRS internal Icon - - char * Compressed; - - ReplyLen = GetAPRSIcon(_REPLYBUFFER, NodeURL); - - if (allowDeflate) - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - else - Compressed = _REPLYBUFFER; - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: Text\r\n%s\r\n", ReplyLen, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - - return 0; - - } - - else if (_memicmp(NodeURL, "/NODE/", 6)) - { - // Not Node, See if a local file - - Bufferlen = SendMessageFile(sock, NodeURL, FALSE, allowDeflate); // Send error if not found - return 0; - } - - // Node URL - - { - - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - - if (_stricmp(NodeURL, "/Node/webproc.css") == 0) - { - char WebprocCSS[] = - ".dropbtn {position: relative; border: 1px solid black;padding:1px;}\r\n" - ".dropdown {position: relative; display: inline-block;}\r\n" - ".dropdown-content {display: none; position: absolute;background-color: #ccc; " - "min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0,0,00.2); z-index: 1;}\r\n" - ".dropdown-content a {color: black; padding: 1px 1px;text-decoration:none;display:block;}" - ".dropdown-content a:hover {background-color: #dddfff;}\r\n" - ".dropdown:hover .dropdown-content {display: block;}\r\n" - ".dropdown:hover .dropbtn {background-color: #ddd;}\r\n" - "input.btn:active {background:black;color:white;}\r\n" - "submit.btn:active {background:black;color:white;}\r\n"; - ReplyLen = sprintf(_REPLYBUFFER, "%s", WebprocCSS); - } - - else if (_stricmp(NodeURL, "/Node/Killandrestart") == 0) - { - int port = atoi(Context); - - if (port > 0 && port < 33) - { - struct TNCINFO * TNC = TNCInfo[port]; - - KillTNC(TNC); - TNC->DontRestart = FALSE; - RestartTNC(TNC); - - if (TNC && TNC->WebWindowProc) - ReplyLen = TNC->WebWindowProc(TNC, _REPLYBUFFER, LOCAL); - - } - } - - else if (_stricmp(NodeURL, "/Node/Port") == 0 || _stricmp(NodeURL, "/Node/ARDOPAbort") == 0) - { - int port = atoi(Context); - - if (port > 0 && port < 33) - { - struct TNCINFO * TNC = TNCInfo[port]; - - if (TNC && TNC->WebWindowProc) - ReplyLen = TNC->WebWindowProc(TNC, _REPLYBUFFER, LOCAL); - } - - } - - else if (_stricmp(NodeURL, "/Node/Streams") == 0) - { - ReplyLen = StatusProc(_REPLYBUFFER); - } - - else if (_stricmp(NodeURL, "/Node/Stats.html") == 0) - { - struct tm * TM; - char UPTime[50]; - time_t szClock = STATSTIME * 60; - - TM = gmtime(&szClock); - - sprintf(UPTime, "%.2d:%.2d:%.2d", TM->tm_yday, TM->tm_hour, TM->tm_min); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", StatsHddr); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Version", VersionString); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Uptime (Days Hours Mins)", UPTime); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Semaphore: Get-Rel/Clashes", Semaphore.Gets - Semaphore.Rels, Semaphore.Clashes); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Buffers: Max/Cur/Min/Out/Wait", MAXBUFFS, QCOUNT, MINBUFFCOUNT, NOBUFFCOUNT, BUFFERWAITS); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "Known Nodes/Max Nodes", NUMBEROFNODES, MAXDESTS); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "L4 Connects Sent/Rxed ", L4CONNECTSOUT, L4CONNECTSIN); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "L4 Frames TX/RX/Resent/Reseq", L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - "L3 Frames Relayed", L3FRAMES); - - } - - else if (_stricmp(NodeURL, "/Node/RigControl.html") == 0) - { - char Test[] = - "\r\n" - "Rigcontrol\r\n" - "\r\n" - "\r\n" - "\r\n" - "
Waiting for data...
\r\n" - "\r\n"; - - - char NoRigCtl[] = - "\r\n" - "Rigcontrol\r\n" - "\r\n" - "\r\n" - "
RigControl Not Configured...
\r\n" - "\r\n"; - - if (RigWebPage) - ReplyLen = sprintf(_REPLYBUFFER, "%s", Test); - else - ReplyLen = sprintf(_REPLYBUFFER, "%s", NoRigCtl); - } - - else if (_stricmp(NodeURL, "/Node/ShowLog.html") == 0) - { - char ShowLogPage[] = - "" - "" - "Log Display" - "" - "
" - "
" -// "" - "" - "" - "
"; - - char * _REPLYBUFFER; - int ReplyLen; - char Header[256]; - int HeaderLen; - char * CfgBytes; - int CfgLen; - char inputname[250]; - FILE *fp1; - struct stat STAT; - char DummyKey[] = "DummyKey"; - time_t T; - struct tm * tm; - char Name[64] = ""; - - T = time(NULL); - tm = gmtime(&T); - - if (LOCAL == FALSE && COOKIE == FALSE) - { - // Send Not Authorized - - char _REPLYBUFFER[4096]; - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
Not authorized - please sign in"); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return 1; - } - - if (COOKIE == FALSE) - Key = DummyKey; - - if (memcmp(Context, "date=", 5) == 0) - { - memset(tm, 0, sizeof(struct tm)); - tm->tm_year = atoi(&Context[5]) - 1900; - tm->tm_mon = atoi(&Context[10]) - 1; - tm->tm_mday = atoi(&Context[13]); - } - - - - if (strcmp(Context, "input=Back") == 0) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return 1; - } - - if (LogDirectory[0] == 0) - { - strcpy(inputname, "logs/"); - } - else - { - strcpy(inputname,LogDirectory); - strcat(inputname,"/"); - strcat(inputname, "/logs/"); - } - - if (strstr(Context, "CMS")) - { - sprintf(Name, "CMSAccess_%04d%02d%02d.log", - tm->tm_year +1900, tm->tm_mon+1, tm->tm_mday); - } - else if (strstr(Context, "Debug")) - { - sprintf(Name, "log_%02d%02d%02d_DEBUG.txt", - tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); - } - else if (strstr(Context, "BBS")) - { - sprintf(Name, "log_%02d%02d%02d_BBS.txt", - tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); - } - else if (strstr(Context, "Chat")) - { - sprintf(Name, "log_%02d%02d%02d_CHAT.txt", - tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); - } - else if (strstr(Context, "Telnet")) - { - sprintf(Name, "Telnet_%02d%02d%02d.log", - tm->tm_year - 100, tm->tm_mon+1, tm->tm_mday); - } - - strcat(inputname, Name); - - if (stat(inputname, &STAT) == -1) - { - CfgBytes = malloc(256); - sprintf(CfgBytes, "Log %s not found", inputname); - CfgLen = strlen(CfgBytes); - } - else - { - fp1 = fopen(inputname, "rb"); - - if (fp1 == 0) - { - CfgBytes = malloc(256); - sprintf(CfgBytes, "Log %s not found", inputname); - CfgLen = strlen(CfgBytes); - } - else - { - CfgLen = STAT.st_size; - - CfgBytes = malloc(CfgLen + 1); - - CfgLen = (int)fread(CfgBytes, 1, CfgLen, fp1); - CfgBytes[CfgLen] = 0; - } - } - - _REPLYBUFFER = malloc(CfgLen + 1000); - - ReplyLen = sprintf(_REPLYBUFFER, ShowLogPage, CfgBytes); - free (CfgBytes); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, _REPLYBUFFER, ReplyLen); - sendandcheck(sock, Tail, (int)strlen(Tail)); - free (_REPLYBUFFER); - - return 1; - } - - else if (_stricmp(NodeURL, "/Node/EditCfg.html") == 0) - { - char * _REPLYBUFFER; - int ReplyLen; - char Header[256]; - int HeaderLen; - char * CfgBytes; - int CfgLen; - char inputname[250]="bpq32.cfg"; - FILE *fp1; - struct stat STAT; - char DummyKey[] = "DummyKey"; - - if (LOCAL == FALSE && COOKIE == FALSE) - { - // Send Not Authorized - - char _REPLYBUFFER[4096]; - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
Not authorized - please sign in"); - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - send(sock, Header, HeaderLen, 0); - send(sock, _REPLYBUFFER, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - return 1; - } - - if (COOKIE ==FALSE) - Key = DummyKey; - - if (BPQDirectory[0] == 0) - { - strcpy(inputname, "bpq32.cfg"); - } - else - { - strcpy(inputname,BPQDirectory); - strcat(inputname,"/"); - strcat(inputname, "bpq32.cfg"); - } - - - if (stat(inputname, &STAT) == -1) - { - CfgBytes = _strdup("Config File not found"); - } - else - { - fp1 = fopen(inputname, "rb"); - - if (fp1 == 0) - { - CfgBytes = _strdup("Config File not found"); - } - else - { - CfgLen = STAT.st_size; - - CfgBytes = malloc(CfgLen + 1); - - CfgLen = (int)fread(CfgBytes, 1, CfgLen, fp1); - CfgBytes[CfgLen] = 0; - } - } - - _REPLYBUFFER = malloc(CfgLen + 1000); - - ReplyLen = sprintf(_REPLYBUFFER, ConfigEditPage, Key, CfgBytes); - free (CfgBytes); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, _REPLYBUFFER, ReplyLen); - sendandcheck(sock, Tail, (int)strlen(Tail)); - free (_REPLYBUFFER); - - return 1; - } - - - - if (_stricmp(NodeURL, "/Node/PortBeacons") == 0) - { - char * PortChar = strtok_s(NULL, "&", &Context); - int PortNo = atoi(PortChar); - struct PORTCONTROL * PORT; - int PortSlot = 0; - - PORT = GetPortTableEntryFromPortNum(PortNo); // Need slot not number - if (PORT) - PortSlot = PORT->PortSlot; - - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], Beacons, PortNo, - Interval[PortSlot], &UIUIDEST[PortSlot][0], &UIUIDigi[PortSlot][0], &FN[PortSlot][0], &Message[PortSlot][0], PortNo); - } - - - - if (_stricmp(NodeURL, "/Node/PortStats") == 0) - { - struct _EXTPORTDATA * Port; - - char * PortChar = strtok_s(NULL, "&", &Context); - int PortNo = atoi(PortChar); - int Protocol; - int PortType; - - // char PORTTYPE; // H/W TYPE - // 0 = ASYNC, 2 = PC120, 4 = DRSI - // 6 = TOSH, 8 = QUAD, 10 = RLC100 - // 12 = RLC400 14 = INTERNAL 16 = EXTERNAL - -#define KISS 0 -#define NETROM 2 -#define HDLC 6 -#define L2 8 -#define WINMOR 10 - - - // char PROTOCOL; // PORT PROTOCOL - // 0 = KISS, 2 = NETROM, 4 = BPQKISS - //; 6 = HDLC, 8 = L2 - - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsHddr, PortNo); - - Port = (struct _EXTPORTDATA *)GetPortTableEntryFromPortNum(PortNo); - - if (Port == NULL) - { - ReplyLen = sprintf(_REPLYBUFFER, "Invalid Port"); - goto SendResp; - } - - Protocol = Port->PORTCONTROL.PROTOCOL; - PortType = Port->PORTCONTROL.PROTOCOL; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Frames Digied", Port->PORTCONTROL.L2DIGIED); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Frames Heard", Port->PORTCONTROL.L2FRAMES); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Frames Received", Port->PORTCONTROL.L2FRAMESFORUS); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Frames Sent", Port->PORTCONTROL.L2FRAMESSENT); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Timeouts", Port->PORTCONTROL.L2TIMEOUTS); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "REJ Frames Received", Port->PORTCONTROL.L2REJCOUNT); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "RX out of Seq", Port->PORTCONTROL.L2OUTOFSEQ); - // ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Resequenced", Port->PORTCONTROL.L2RESEQ); - if (Protocol == HDLC) - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "Underrun", Port->PORTCONTROL.L2URUNC); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "RX Overruns", Port->PORTCONTROL.L2ORUNC); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "RX CRC Errors", Port->PORTCONTROL.RXERRORS); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "Frames abandoned", Port->PORTCONTROL.L1DISCARD); - } - else if ((Protocol == KISS && Port->PORTCONTROL.KISSFLAGS) || Protocol == NETROM) - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "Poll Timeout", Port->PORTCONTROL.L2URUNC); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "RX CRC Errors", Port->PORTCONTROL.RXERRORS); - } - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "FRMRs Sent", Port->PORTCONTROL.L2FRMRTX); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "FRMRs Received", Port->PORTCONTROL.L2FRMRRX); - - // DB 'Link Active % ' - // DD AVSENDING - - } - - if (_stricmp(NodeURL, "/Node/Ports.html") == 0) - { - struct _EXTPORTDATA * ExtPort; - struct PORTCONTROL * Port; - - int count; - char DLL[20]; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", PortsHddr); - - for (count = 1; count <= NUMBEROFPORTS; count++) - { - Port = GetPortTableEntryFromSlot(count); - ExtPort = (struct _EXTPORTDATA *)Port; - - if (Port->PORTTYPE == 0x10) - { - strcpy(DLL, ExtPort->PORT_DLL_NAME); - strlop(DLL, '.'); - } - else if (Port->PORTTYPE == 0) - strcpy(DLL, "ASYNC"); - - else if (Port->PORTTYPE == 22) - strcpy(DLL, "I2C"); - - else if (Port->PORTTYPE == 14) - strcpy(DLL, "INTERNAL"); - - else if (Port->PORTTYPE > 0 && Port->PORTTYPE < 14) - strcpy(DLL, "HDLC"); - - - if (Port->TNC && Port->TNC->WebWindowProc) // Has a Window - { - if (Port->UICAPABLE) - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithBeaconAndDriver, Port->PORTNUMBER, DLL, - Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200); - else - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithDriver, Port->PORTNUMBER, DLL, - Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200); - - continue; - } - - if (Port->PORTTYPE == 16 && Port->PROTOCOL == 10 && Port->UICAPABLE == 0) // EXTERNAL, Pactor/WINMO - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], SessionPortLine, Port->PORTNUMBER, DLL, - Port->PORTDESCRIPTION, Port->PORTNUMBER); - else - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithBeacon, Port->PORTNUMBER, Port->PORTNUMBER, - DLL, DLL, Port->PORTDESCRIPTION, Port->PORTNUMBER); - } - - if (RigActive) - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], RigControlLine, 33, "Rig Control", "Rig Control", 600, 350, 200, 200); - - } - - if (_stricmp(NodeURL, "/Node/Nodes.html") == 0) - { - struct DEST_LIST * Dests = DESTS; - int count, i; - char Normcall[10]; - char Alias[10]; - int Width = 5; - int x = 0, n = 0; - struct DEST_LIST * List[1000]; - char Param = 0; - - if (Context) - { - _strupr(Context); - Param = Context[0]; - } - - for (count = 0; count < MAXDESTS; count++) - { - if (Dests->DEST_CALL[0] != 0) - { - if (Param != 'T' || Dests->DEST_COUNT) - List[n++] = Dests; - - if (n > 999) - break; - } - - Dests++; - } - - if (n > 1) - { - if (Param == 'C') - qsort(List, n, sizeof(void *), CompareNode); - else - qsort(List, n, sizeof(void *), CompareAlias); - } - - Alias[6] = 0; - - if (Param == 'T') - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], NodeHddr, "with traffic"); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], ""); - } - else if (Param == 'C') - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], NodeHddr, "sorted by Call"); - else - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], NodeHddr, "sorted by Alias"); - - for (i = 0; i < n; i++) - { - int len = ConvFromAX25(List[i]->DEST_CALL, Normcall); - Normcall[len]=0; - - memcpy(Alias, List[i]->DEST_ALIAS, 6); - strlop(Alias, ' '); - - if (Param == 'T') - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - Normcall, Alias, List[i]->DEST_COUNT, List[i]->DEST_RTT /16, - (List[i]->DEST_STATE & 0x40)? 'B':' ', (List[i]->DEST_STATE & 63)); - - } - else - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], NodeLine, Normcall, Alias, Normcall); - - if (++x == Width) - { - x = 0; - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], ""); - } - } - } - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], ""); - } - - if (_stricmp(NodeURL, "/Node/NodeDetail") == 0) - { - UCHAR AXCall[8]; - struct DEST_LIST * Dest = DESTS; - struct NR_DEST_ROUTE_ENTRY * NRRoute; - struct ROUTE * Neighbour; - char Normcall[10]; - int i, len, count, Active; - char Alias[7]; - - Alias[6] = 0; - - _strupr(Context); - - ConvToAX25(Context, AXCall); - - for (count = 0; count < MAXDESTS; count++) - { - if (CompareCalls(Dest->DEST_CALL, AXCall)) - { - break; - } - Dest++; - } - - if (count == MAXDESTS) - { - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "

Call %s not found

", Context); - goto SendResp; - } - - memcpy(Alias, Dest->DEST_ALIAS, 6); - strlop(Alias, ' '); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], - "

Info for Node %s:%s

", Alias, Context); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "

PortDriverIDBeaconsDriver Window
%d %s%s
%d %s%s Beacons
%d%s%s
%d%s%s Driver Window
%d%s%s BeaconsDriver Window
%d%s%s Rig Control
%s%s
%s%s
%s%d%d
%s%d%d%d%d%d
%s%d%d
%s%d%d
%s%d%d%d%d
%s%d
CallFramesRTTBPQ?Hops
%s:%s%d%d%c%.0d
"); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
FramesRTTBPQ?Hops
%d%d%c%.0d
", - Dest->DEST_COUNT, Dest->DEST_RTT /16, - (Dest->DEST_STATE & 0x40)? 'B':' ', (Dest->DEST_STATE & 63)); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "

Neighbours

"); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], - "" - ""); - - NRRoute = &Dest->NRROUTE[0]; - - Active = Dest->DEST_ROUTE; - - for (i = 1; i < 4; i++) - { - Neighbour = NRRoute->ROUT_NEIGHBOUR; - - if (Neighbour) - { - len = ConvFromAX25(Neighbour->NEIGHBOUR_CALL, Normcall); - Normcall[len] = 0; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", - (Active == i)?'>':' ',NRRoute->ROUT_QUALITY, NRRoute->ROUT_OBSCOUNT, Neighbour->NEIGHBOUR_PORT, Normcall); - } - NRRoute++; - } - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
Qual Obs Port Call
%c %d%d%d%s
"); - - goto SendResp; - - } - /* - - MOV ESI,OFFSET32 NODEROUTEHDDR - MOV ECX,11 - REP MOVSB - - LEA ESI,DEST_CALL[EBX] - CALL DECODENODENAME ; CONVERT TO ALIAS:CALL - REP MOVSB - - CMP DEST_RTT[EBX],0 - JE SHORT @f ; TIMER NOT SET - DEST PROBABLY NOT USED - - MOVSB ; ADD SPACE - CALL DORTT - - @@: - MOV AL,CR - STOSB - - MOV ECX,3 - MOV DH,DEST_ROUTE[EBX] ; CURRENT ACTIVE ROUTE - MOV DL,1 - - push ebx - - PUBLIC CMDN110 - CMDN110: - - MOV ESI,ROUT1_NEIGHBOUR[EBX] - CMP ESI,0 - JE CMDN199 - - - MOV AX,' ' - CMP DH,DL - JNE SHORT CMDN112 ; NOT CURRENT DEST - MOV AX,' >' - - CMDN112: - - STOSW - - PUSH ECX - - MOV AL,ROUT1_QUALITY[EBX] - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - MOV AL,ROUT1_OBSCOUNT[EBX] - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - MOV AL,NEIGHBOUR_PORT[ESI] ; GET PORT - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - - PUSH EDI - CALL CONVFROMAX25 ; CONVERT TO CALL - POP EDI - - MOV ESI,OFFSET32 NORMCALL - REP MOVSB - - MOV AL,CR - STOSB - - ADD EBX,ROUTEVECLEN - INC DL ; ROUTE NUMBER - - POP ECX - DEC ECX - JNZ CMDN110 - - PUBLIC CMDN199 - CMDN199: - - POP EBX - - ; DISPLAY INP3 ROUTES - - MOV ECX,3 - MOV DL,4 - - PUBLIC CMDNINP3 - CMDNINP3: - - MOV ESI,INPROUT1_NEIGHBOUR[EBX] - CMP ESI,0 - JE CMDNINPEND - - MOV AX,' ' - CMP DH,DL - JNE SHORT @F ; NOT CURRENT DEST - MOV AX,' >' - - @@: - - STOSW - - PUSH ECX - - MOV AL, Hops1[EBX] - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - MOVZX EAX, SRTT1[EBX] - - MOV EDX,0 - MOV ECX, 100 - DIV ECX - CALL CONV_5DIGITS - MOV AL,'.' - STOSB - MOV EAX, EDX - CALL PRINTNUM - MOV AL,'s' - STOSB - MOV AL,' ' - STOSB - - MOV AL,NEIGHBOUR_PORT[ESI] ; GET PORT - CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS - - mov AL,' ' - stosb - - PUSH EDI - CALL CONVFROMAX25 ; CONVERT TO CALL - POP EDI - - MOV ESI,OFFSET32 NORMCALL - REP MOVSB - - - MOV AL,CR - STOSB - - ADD EBX,INPROUTEVECLEN - INC DL ; ROUTE NUMBER - - POP ECX - LOOP CMDNINP3 - - CMDNINPEND: - - ret - - */ - - - if (_stricmp(NodeURL, "/Node/Routes.html") == 0) - { - struct ROUTE * Routes = NEIGHBOURS; - int MaxRoutes = MAXNEIGHBOURS; - int count; - char Normcall[10]; - char locked; - int NodeCount; - int Percent = 0; - int Iframes, Retries; - char Active[10]; - int Queued; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", RouteHddr); - - for (count=0; countNEIGHBOUR_CALL[0] != 0) - { - int len = ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall); - Normcall[len]=0; - - if ((Routes->NEIGHBOUR_FLAG & 1) == 1) - locked = '!'; - else - locked = ' '; - - NodeCount = COUNTNODES(Routes); - - if (Routes->NEIGHBOUR_LINK) - Queued = COUNT_AT_L2(Routes->NEIGHBOUR_LINK); - else - Queued = 0; - - Iframes = Routes->NBOUR_IFRAMES; - Retries = Routes->NBOUR_RETRIES; - - if (Routes->NEIGHBOUR_LINK && Routes->NEIGHBOUR_LINK->L2STATE >= 5) - strcpy(Active, ">"); - else - strcpy(Active, " "); - - if (Iframes) - Percent = (Retries * 100) / Iframes; - else - Percent = 0; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], RouteLine, Active, Routes->NEIGHBOUR_PORT, Normcall, locked, - Routes->NEIGHBOUR_QUAL, NodeCount, Iframes, Retries, Percent, Routes->NBOUR_MAXFRAME, Routes->NBOUR_FRACK, - Routes->NEIGHBOUR_TIME >> 8, Routes->NEIGHBOUR_TIME & 0xff, Queued, Routes->OtherendsRouteQual); - } - Routes+=1; - } - } - - if (_stricmp(NodeURL, "/Node/Links.html") == 0) - { - struct _LINKTABLE * Links = LINKS; - int MaxLinks = MAXLINKS; - int count; - char Normcall1[10]; - char Normcall2[10]; - char State[12] = "", Type[12] = "Uplink"; - int axState; - int cctType; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", LinkHddr); - - for (count=0; countLINKCALL[0] != 0) - { - int len = ConvFromAX25(Links->LINKCALL, Normcall1); - Normcall1[len] = 0; - - len = ConvFromAX25(Links->OURCALL, Normcall2); - Normcall2[len] = 0; - - axState = Links->L2STATE; - - if (axState == 2) - strcpy(State, "Connecting"); - else if (axState == 3) - strcpy(State, "FRMR"); - else if (axState == 4) - strcpy(State, "Closing"); - else if (axState == 5) - strcpy(State, "Active"); - else if (axState == 6) - strcpy(State, "REJ Sent"); - - cctType = Links->LINKTYPE; - - if (cctType == 1) - strcpy(Type, "Uplink"); - else if (cctType == 2) - strcpy(Type, "Downlink"); - else if (cctType == 3) - strcpy(Type, "Node-Node"); - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], LinkLine, Normcall1, Normcall2, Links->LINKPORT->PORTNUMBER, - State, Type, 2 - Links->VER1FLAG ); - - Links+=1; - } - } - } - - if (_stricmp(NodeURL, "/Node/Users.html") == 0) - { - TRANSPORTENTRY * L4 = L4TABLE; - TRANSPORTENTRY * Partner; - int MaxLinks = MAXLINKS; - int count; - char State[12] = "", Type[12] = "Uplink"; - char LHS[50] = "", MID[10] = "", RHS[50] = ""; - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", UserHddr); - - for (count=0; count < MAXCIRCUITS; count++) - { - if (L4->L4USER[0]) - { - RHS[0] = MID[0] = 0; - - if ((L4->L4CIRCUITTYPE & UPLINK) == 0) //SHORT CMDS10A ; YES - { - // IF DOWNLINK, ONLY DISPLAY IF NO CROSSLINK - - if (L4->L4CROSSLINK == 0) //jne CMDS60 ; WILL PROCESS FROM OTHER END - { - // ITS A DOWNLINK WITH NO PARTNER - MUST BE A CLOSING SESSION - // DISPLAY TO THE RIGHT FOR NOW - - strcpy(LHS, "(Closing) "); - DISPLAYCIRCUIT(L4, RHS); - goto CMDS50; - } - else - goto CMDS60; // WILL PROCESS FROM OTHER END - } - - if (L4->L4CROSSLINK == 0) - { - // Single Entry - - DISPLAYCIRCUIT(L4, LHS); - } - else - { - DISPLAYCIRCUIT(L4, LHS); - - Partner = L4->L4CROSSLINK; - - if (Partner->L4STATE == 5) - strcpy(MID, "<-->"); - else - strcpy(MID, "<~~>"); - - DISPLAYCIRCUIT(Partner, RHS); - } -CMDS50: - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], UserLine, LHS, MID, RHS); - } -CMDS60: - L4++; - } - } - /* - PUBLIC CMDUXX_1 - CMDUXX_1: - push EBX - push ESI - PUSH ECX - push EDI - - call _FINDDESTINATION - pop EDI - - jz SHORT NODE_FOUND - - push EDI ; NET/ROM not found - call CONVFROMAX25 ; CONVERT TO CALL - pop EDI - mov ESI,OFFSET32 NORMCALL - rep movsb - - jmp SHORT END_CMDUXX - - PUBLIC NODE_FOUND - NODE_FOUND: - - lea ESI,DEST_CALL[EBX] - call DECODENODENAME - - REP MOVSB - - PUBLIC END_CMDUXX - END_CMDUXX: - - POP ECX - pop ESI - pop EBX - ret - - }}} - */ - - else if (_stricmp(NodeURL, "/Node/Terminal.html") == 0) - { - if (COOKIE && Session) - { - // Already signed in as sysop - - struct UserRec * USER = Session->USER; - - struct HTTPConnectionInfo * NewSession = AllocateSession(sock, 'T'); - - if (NewSession) - { - char AXCall[10]; - ReplyLen = sprintf(_REPLYBUFFER, TermPage, Mycall, Mycall, NewSession->Key, NewSession->Key, NewSession->Key); - strcpy(NewSession->HTTPCall, USER->Callsign); - ConvToAX25(NewSession->HTTPCall, AXCall); - ChangeSessionCallsign(NewSession->Stream, AXCall); - BPQHOSTVECTOR[NewSession->Stream -1].HOSTSESSION->Secure_Session = USER->Secure; - Session->USER = USER; - NewSession->TNC = conn->TNC; - - - // if (Appl[0]) - // { - // strcat(Appl, "\r"); - // SendMsg(Session->Stream, Appl, strlen(Appl)); - // } - - } - else - { - ReplyLen = SetupNodeMenu(_REPLYBUFFER, LOCAL); - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", BusyError); - } - } - else if (LOCAL) - { - // connected to 127.0.0.1 so sign in using node call - - struct HTTPConnectionInfo * NewSession = AllocateSession(sock, 'T'); - - if (NewSession) - { - ReplyLen = sprintf(_REPLYBUFFER, TermPage, Mycall, Mycall, NewSession->Key, NewSession->Key, NewSession->Key); - strcpy(NewSession->HTTPCall, MYNODECALL); - ChangeSessionCallsign(NewSession->Stream, MYCALL); - BPQHOSTVECTOR[NewSession->Stream -1].HOSTSESSION->Secure_Session = TRUE; - NewSession->TNC = conn->TNC; - } - } - else - ReplyLen = sprintf(_REPLYBUFFER, TermSignon, Mycall, Mycall, Context); - } - - else if (_stricmp(NodeURL, "/Node/Signon.html") == 0) - { - ReplyLen = sprintf(_REPLYBUFFER, NodeSignon, Mycall, Mycall, Context); - } - - else if (_stricmp(NodeURL, "/Node/Drivers") == 0) - { - int Bufferlen = SendMessageFile(sock, "/Drivers.htm", TRUE, allowDeflate); // return -1 if not found - - if (Bufferlen != -1) - return 0; // We've sent it - } - - else if (_stricmp(NodeURL, "/Node/OutputScreen.html") == 0) - { - struct HTTPConnectionInfo * Session = FindSession(Context); - - if (Session == NULL) - { - ReplyLen = sprintf(_REPLYBUFFER, "%s", LostSession); - } - else - { - Session->sock = sock; // socket to reply on - ReplyLen = RefreshTermWindow(TCP, Session, _REPLYBUFFER); - - if (ReplyLen == 0) // Nothing new - { - // Debugprintf("GET with no data avail - response held"); - Session->ResponseTimer = 1200; // Delay response for up to a minute - } - else - { - // Debugprintf("GET - outpur sent, timer was %d, set to zero", Session->ResponseTimer); - Session->ResponseTimer = 0; - } - - Session->KillTimer = 0; - return 0; // Refresh has sent any available output - } - } - - else if (_stricmp(NodeURL, "/Node/InputLine.html") == 0) - { - struct TNCINFO * TNC = conn->TNC; - struct TCPINFO * TCP = 0; - - if (TNC) - TCP = TNC->TCPInfo; - - if (TCP && TCP->WebTermCSS) - ReplyLen = sprintf(_REPLYBUFFER, InputLine, Context, TCP->WebTermCSS); - else - ReplyLen = sprintf(_REPLYBUFFER, InputLine, Context, ""); - - } - - else if (_stricmp(NodeURL, "/Node/PTT") == 0) - { - struct TNCINFO * TNC = conn->TNC; - int x = atoi(Context); - } - - -SendResp: - - FormatTime3(TimeString, time(NULL)); - - strcpy(&_REPLYBUFFER[ReplyLen], Tail); - ReplyLen += (int)strlen(Tail); - - - if (allowDeflate) - { - Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); - } - else - { - Encoding[0] = 0; - Compressed = _REPLYBUFFER; - } - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n" - "Date: %s\r\n%s\r\n", ReplyLen, TimeString, Encoding); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, Compressed, ReplyLen); - - if (allowDeflate) - free (Compressed); - } - return 0; - -#ifdef WIN32 - } -#include "StdExcept.c" -} -return 0; -#endif -} - -void ProcessHTTPMessage(void * conn) -{ - // conn is a malloc'ed copy to handle reused connections, so need to free it - - InnerProcessHTTPMessage((struct ConnectionInfo *)conn); - free(conn); - return; -} - -static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; -static char *dat[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - - -VOID FormatTime3(char * Time, time_t cTime) -{ - struct tm * TM; - TM = gmtime(&cTime); - - sprintf(Time, "%s, %02d %s %3d %02d:%02d:%02d GMT", dat[TM->tm_wday], TM->tm_mday, month[TM->tm_mon], - TM->tm_year + 1900, TM->tm_hour, TM->tm_min, TM->tm_sec); - -} - -// Sun, 06 Nov 1994 08:49:37 GMT - -int StatusProc(char * Buff) -{ - int i; - char callsign[12] = ""; - char flag[3]; - UINT Mask, MaskCopy; - int Flags; - int AppNumber; - int OneBits; - int Len = sprintf(Buff, "" - "Stream Status"); - - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], ""); - - for (i=1;i<65; i++) - { - callsign[0]=0; - - if (GetAllocationState(i)) - - strcpy(flag,"*"); - else - strcpy(flag," "); - - GetCallsign(i,callsign); - - Mask = MaskCopy = Get_APPLMASK(i); - - // if only one bit set, convert to number - - AppNumber = 0; - OneBits = 0; - - while (MaskCopy) - { - if (MaskCopy & 1) - OneBits++; - - AppNumber++; - MaskCopy = MaskCopy >> 1; - } - - Flags=GetApplFlags(i); - - if (OneBits > 1) - Len += sprintf(&Buff[Len], "" - "", - i, flag, RXCount(i), TXCount(i), MONCount(i), Mask, Flags, callsign, BPQHOSTVECTOR[i-1].PgmName); - - else - Len += sprintf(&Buff[Len], "" - "", - i, flag, RXCount(i), TXCount(i), MONCount(i), AppNumber, Flags, callsign, BPQHOSTVECTOR[i-1].PgmName); - - if ((i & 1) == 0) - Len += sprintf(&Buff[Len], ""); - - } - - Len += sprintf(&Buff[Len], "
    RX   TX   MON  App  Flg Callsign  Program    RX   TX   MON  App  Flg Callsign  Program
%d%s%d%d%d%x%x%s%s%d%s%d%d%d%d%x%s%s
"); - return Len; -} - -int ProcessNodeSignon(SOCKET sock, struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, int LOCAL) -{ - int ReplyLen = 0; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Key; - char Header[256]; - int HeaderLen; - struct HTTPConnectionInfo *Sess; - - - if (input) - { - int i; - struct UserRec * USER; - - UndoTransparency(input); - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n" - "\r\n", (int)(ReplyLen + strlen(Tail))); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - } - user = strtok_s(&input[9], "&", &Key); - password = strtok_s(NULL, "=", &Key); - password = Key; - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if (user && _stricmp(user, USER->UserName) == 0) - { - if (strcmp(password, USER->Password) == 0 && USER->Secure) - { - // ok - - Sess = *Session = AllocateSession(sock, 'N'); - Sess->USER = USER; - - ReplyLen = SetupNodeMenu(Reply, LOCAL); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n" - "Set-Cookie: BPQSessionCookie=%s; Path = /\r\n\r\n", (int)(ReplyLen + strlen(Tail)), Sess->Key); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return ReplyLen; - } - } - } - } - - ReplyLen = sprintf(Reply, NodeSignon, Mycall, Mycall); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", PassError); - - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", (int)(ReplyLen + strlen(Tail))); - send(sock, Header, HeaderLen, 0); - send(sock, Reply, ReplyLen, 0); - send(sock, Tail, (int)strlen(Tail), 0); - - return 0; - - - return ReplyLen; -} - - - - -int ProcessMailSignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, BOOL WebMail, int LOCAL) -{ - int ReplyLen = 0; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Key; - struct HTTPConnectionInfo * NewSession; - - if (input) - { - int i; - struct UserRec * USER; - - UndoTransparency(input); - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - return ReplyLen; - } - user = strtok_s(&input[9], "&", &Key); - password = strtok_s(NULL, "=", &Key); - password = Key; - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if (user && _stricmp(user, USER->UserName) == 0) - { - if (strcmp(password, USER->Password) == 0 && (USER->Secure || WebMail)) - { - // ok - - NewSession = AllocateSession(Appl[0], 'M'); - - *Session = NewSession; - - if (NewSession) - { - - ReplyLen = 0; - strcpy(NewSession->Callsign, USER->Callsign); - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - return ReplyLen; - } - } - } - } - - ReplyLen = sprintf(Reply, MailSignon, Mycall, Mycall); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", PassError); - - return ReplyLen; -} - - -int ProcessChatSignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, struct HTTPConnectionInfo ** Session, int LOCAL) -{ - int ReplyLen = 0; - char * input = strstr(MsgPtr, "\r\n\r\n"); // End of headers - char * user, * password, * Key; - - if (input) - { - int i; - struct UserRec * USER; - - UndoTransparency(input); - - if (strstr(input, "Cancel=Cancel")) - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - return ReplyLen; - } - - user = strtok_s(&input[9], "&", &Key); - password = strtok_s(NULL, "=", &Key); - password = Key; - - - for (i = 0; i < TCP->NumberofUsers; i++) - { - USER = TCP->UserRecPtr[i]; - - if (user && _stricmp(user, USER->UserName) == 0) - { - if (strcmp(password, USER->Password) == 0 && USER->Secure) - { - // ok - - *Session = AllocateSession(Appl[0], 'C'); - - if (Session) - { - ReplyLen = 0; - } - else - { - ReplyLen = SetupNodeMenu(Reply, LOCAL); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", BusyError); - } - return ReplyLen; - } - } - } - } - - ReplyLen = sprintf(Reply, ChatSignon, Mycall, Mycall); - ReplyLen += sprintf(&Reply[ReplyLen], "%s", PassError); - - return ReplyLen; - -} - -#ifdef WIN32 - -#include -#include - -#define SHA1_HASH_LEN 20 - -BOOL SHA1PasswordHash(char * lpszPassword, char * Hash) -{ - HCRYPTPROV hCryptProv; // Handle to our context - HCRYPTHASH hCryptHash; // Handle to our hash - BYTE bHashValue[SHA1_HASH_LEN]; // This will hold our SHA-1 hash - DWORD dwSize = SHA1_HASH_LEN; // Size of output - BOOL bSuccess = FALSE; // We change this to TRUE if we complete the operations - // Declare all the variables at the start of our code for C89 compatability - - if(CryptAcquireContext(&hCryptProv, NULL, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - { // Initiate usage of the functions - if(CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hCryptHash)) - { // Create a SHA1 hash - if(CryptHashData(hCryptHash, (PBYTE)lpszPassword, lstrlen(lpszPassword) * sizeof(TCHAR), 0)) - { // Update the hash, (process our password) - if(CryptGetHashParam(hCryptHash, HP_HASHVAL, bHashValue, &dwSize, 0)) - { // Extract the hash - - memcpy(Hash, bHashValue, 20); - bSuccess = TRUE; - } - } - CryptDestroyHash(hCryptHash); - } - CryptReleaseContext(hCryptProv, 0); - } - - return bSuccess; -} - -#else - -#include - -BOOL SHA1PasswordHash(char * data, char * Hash) -{ - SHA1(data, strlen(data), Hash); - return 1; -} -#endif - -int BuildRigCtlPage(char * _REPLYBUFFER) -{ - int ReplyLen; - - struct RIGPORTINFO * PORT; - struct RIGINFO * RIG; - int p, i; - - char Page[] = - "\r\n" - // "\r\n" - "Rigcontrol\r\n" - "" - "

Rigcontrol

\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - ""; - char RigLine[] = - "\r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n"; - char Tail[] = - "
RadioFreqModeSTPorts
%s%s%s/1%c%c%s
\r\n" - "\r\n"; - - ReplyLen = sprintf(_REPLYBUFFER, "%s", Page); - - for (p = 0; p < NumberofPorts; p++) - { - PORT = PORTInfo[p]; - - for (i=0; i< PORT->ConfiguredRigs; i++) - { - RIG = &PORT->Rigs[i]; - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], RigLine, RIG->WEB_Label, RIG->WEB_FREQ, RIG->WEB_MODE, RIG->WEB_SCAN, RIG->WEB_PTT, RIG->WEB_PORTS, RIG->Interlock); - } - } - - ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", Tail); - return ReplyLen; -} - - -void SendRigWebPage() -{ - int i, n; - struct ConnectionInfo * sockptr; - struct TNCINFO * TNC; - struct TCPINFO * TCP; - - for (i = 0; i < 33; i++) - { - TNC = TNCInfo[i]; - - if (TNC && TNC->Hardware == H_TELNET) - { - TCP = TNC->TCPInfo; - - if (TCP) - { - for (n = 0; n <= TCP->MaxSessions; n++) - { - sockptr = TNC->Streams[n].ConnectionInfo; - - if (sockptr->SocketActive) - { - if (sockptr->HTTPMode && sockptr->WebSocks && strcmp(sockptr->WebURL, "RIGCTL") == 0) - { - char RigMsg[8192]; - int RigMsgLen = strlen(RigWebPage); - char* ptr; - - RigMsg[0] = 0x81; // Fin, Data - RigMsg[1] = 126; // Unmasked, Extended Len - RigMsg[2] = RigMsgLen >> 8; - RigMsg[3] = RigMsgLen & 0xff; - strcpy(&RigMsg[4], RigWebPage); - - // If secure session enable PTT button - - if (sockptr->WebSecure) - { - while (ptr = strstr(RigMsg, "hidden")) - memcpy(ptr, " ", 6); - } - - send(sockptr->socket, RigMsg, RigMsgLen + 4, 0); - } - } - } - } - } - } -} - -// Webmail web socket code - -int ProcessWebmailWebSock(char * MsgPtr, char * OutBuffer); - -void ProcessWebmailWebSockThread(void * conn) -{ - // conn is a malloc'ed copy to handle reused connections, so need to free it - - struct ConnectionInfo * sockptr = (struct ConnectionInfo *)conn; - char * URL = sockptr->WebURL; - int Loops = 0; - int Sent; - int InputLen; - struct HTTPConnectionInfo Dummy = {0}; - int ReplyLen = 0; - -#ifdef LINBPQ - - char _REPLYBUFFER[250000]; - - ReplyLen = ProcessWebmailWebSock(URL, _REPLYBUFFER); - - // Send may block - - Sent = send(sockptr->socket, _REPLYBUFFER, ReplyLen, 0); - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - if (Sent > 0) // something sent - { - ReplyLen -= Sent; - memmove(_REPLYBUFFER, &_REPLYBUFFER[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sockptr->socket, _REPLYBUFFER, ReplyLen, 0); - } - -#else - // Send URL to BPQMail via Pipe. Just need a dummy session, as URL contains session key - - HANDLE hPipe; - char Reply[250000]; - - - - hPipe = CreateFile(MAILPipeFileName, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (hPipe == (HANDLE)-1) - { - free(conn); - return; - } - - WriteFile(hPipe, &Dummy, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - WriteFile(hPipe, URL, strlen(URL), &InputLen, NULL); - - ReadFile(hPipe, &Dummy, sizeof (struct HTTPConnectionInfo), &InputLen, NULL); - ReadFile(hPipe, Reply, 250000, &ReplyLen, NULL); - - if (ReplyLen <= 0) - { - InputLen = GetLastError(); - } - - CloseHandle(hPipe); - - // ?? do we need a thread to handle write which may block - - Sent = send(sockptr->socket, Reply, ReplyLen, 0); - - while (Sent != ReplyLen && Loops++ < 3000) // 100 secs max - { - // Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops); - - if (Sent > 0) // something sent - { - InputLen -= Sent; - memmove(Reply, &Reply[Sent], ReplyLen); - } - - Sleep(30); - Sent = send(sockptr->socket, Reply, ReplyLen, 0); - } -#endif - free(conn); - return; -} - - - - diff --git a/RigControl-HPLaptop.c b/RigControl-HPLaptop.c deleted file mode 100644 index e0d38be..0000000 --- a/RigControl-HPLaptop.c +++ /dev/null @@ -1,9179 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// Rig Control Module -// - -// Dec 29 2009 - -// Add Scan Control for SCS - -// August 2010 - -// Fix logic error in Port Initialisation (wasn't always raising RTS and DTR -// Clear RTS and DTR on close - -// Fix Kenwood processing of multiple messages in one packet. - -// Fix reporting of set errors in scan to the wrong session - - -// Yaesu List - -// FT990 define as FT100 - - -#define _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_DEPRECATE - - -#include -#include -#include "time.h" - -#include "CHeaders.h" -#include "tncinfo.h" -#ifdef WIN32 -#include -#else -char *fcvt(double number, int ndigits, int *decpt, int *sign); -#include -#include -#include -#endif -#include "bpq32.h" - -#include "hidapi.h" - -extern struct TNCINFO * TNCInfo[41]; // Records are Malloc'd - -int Row = -20; - -extern struct PORTCONTROL * PORTTABLE; - -VOID __cdecl Debugprintf(const char * format, ...); - -struct RIGINFO * RigConfig(struct TNCINFO * TNC, char * buf, int Port); -struct RIGPORTINFO * CreateTTYInfo(int port, int speed); -BOOL OpenConnection(int); -BOOL SetupConnection(int); -BOOL RigCloseConnection(struct RIGPORTINFO * PORT); -BOOL RigWriteCommBlock(struct RIGPORTINFO * PORT); -BOOL DestroyTTYInfo(int port); -void CheckRX(struct RIGPORTINFO * PORT); -static int OpenRigCOMMPort(struct RIGPORTINFO * PORT, VOID * Port, int Speed); -VOID ICOMPoll(struct RIGPORTINFO * PORT); -VOID ProcessFrame(struct RIGPORTINFO * PORT, UCHAR * rxbuff, int len); -VOID ProcessICOMFrame(struct RIGPORTINFO * PORT, UCHAR * rxbuffer, int Len); -int SendResponse(int Stream, char * Msg); -VOID ProcessYaesuFrame(struct RIGPORTINFO * PORT); -VOID YaesuPoll(struct RIGPORTINFO * PORT); -VOID ProcessYaesuCmdAck(struct RIGPORTINFO * PORT); -VOID ProcessKenwoodFrame(struct RIGPORTINFO * PORT, int Length); -VOID KenwoodPoll(struct RIGPORTINFO * PORT); -VOID DummyPoll(struct RIGPORTINFO * PORT); -VOID SwitchAntenna(struct RIGINFO * RIG, char Antenna); -VOID DoBandwidthandAntenna(struct RIGINFO *RIG, struct ScanEntry * ptr); -VOID SetupScanInterLockGroups(struct RIGINFO *RIG); -VOID ProcessFT100Frame(struct RIGPORTINFO * PORT); -VOID ProcessFT990Frame(struct RIGPORTINFO * PORT); -VOID ProcessFT1000Frame(struct RIGPORTINFO * PORT); -VOID AddNMEAChecksum(char * msg); -VOID ProcessNMEA(struct RIGPORTINFO * PORT, char * NMEAMsg, int len); -VOID COMSetDTR(HANDLE fd); -VOID COMClearDTR(HANDLE fd); -VOID COMSetRTS(HANDLE fd); -VOID COMClearRTS(HANDLE fd); -void CM108_set_ptt(struct RIGINFO *RIG, int PTTState); -BOOL OpenHIDPort(struct RIGPORTINFO * PORT, VOID * Port, int Speed); -int HID_Read_Block(struct RIGPORTINFO * PORT); -int HID_Write_Block(struct RIGPORTINFO * PORT); -HANDLE rawhid_open(char * Device); -int rawhid_recv(int num, void *buf, int len, int timeout); -int rawhid_send(int num, void *buf, int len, int timeout); -void rawhid_close(int num); -VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT); -VOID ConnecttoFLRIG(struct RIGPORTINFO * PORT); -int DecodeHAMLIBAddr(struct RIGPORTINFO * PORT, char * ptr); -void ProcessHAMLIBFrame(struct RIGPORTINFO * PORT, int Length); -VOID HAMLIBPoll(struct RIGPORTINFO * PORT); -void HAMLIBSlaveThread(struct RIGINFO * RIG); -void CheckAndProcessRTLUDP(struct RIGPORTINFO * PORT); -VOID RTLUDPPoll(struct RIGPORTINFO * PORT); -VOID ConnecttoRTLUDP(struct RIGPORTINFO * PORT); -VOID FLRIGPoll(struct RIGPORTINFO * PORT); -void ProcessFLRIGFrame(struct RIGPORTINFO * PORT); -VOID FLRIGSendCommand(struct RIGPORTINFO * PORT, char * Command, char * Value); - -VOID SetupPortRIGPointers(); -VOID PTTCATThread(struct RIGINFO *RIG); -VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT); - -int SendPTCRadioCommand(struct TNCINFO * TNC, char * Block, int Length); -int GetPTCRadioCommand(struct TNCINFO * TNC, char * Block); -int BuildRigCtlPage(char * _REPLYBUFFER); -void SendRigWebPage(); - -extern TRANSPORTENTRY * L4TABLE; -HANDLE hInstance; - -VOID APIENTRY CreateOneTimePassword(char * Password, char * KeyPhrase, int TimeOffset); -BOOL APIENTRY CheckOneTimePassword(char * Password, char * KeyPhrase); - -char * GetApplCallFromName(char * App); - -char Modes[25][6] = {"LSB", "USB", "AM", "CW", "RTTY", "FM", "WFM", "CW-R", "RTTY-R", - "????","????","????","????","????","????","????","????","DV", "LSBD1", - "USBD1", "LSBD2","USBD2", "LSBD3","USBD3", "????"}; - -/* -DV = 17 -F8101 -(0000=LSB, 0001=USB, 0002=AM, -0003=CW, 0004=RTTY, -0018=LSB D1, 0019=USB D1, -0020=LSB D2, 0021=USB D2, -0022=LSB D3, 0023=USB D3 -*/ -// 0 1 2 3 4 5 6 7 8 9 0A 0B 0C 88 - -char YaesuModes[16][6] = {"LSB", "USB", "CW", "CWR", "AM", "", "", "", "FM", "", "DIG", "", "PKT", "FMN", "????"}; - -char FT100Modes[9][6] = {"LSB", "USB", "CW", "CWR", "AM", "DIG", "FM", "WFM", "????"}; - -char FT990Modes[13][6] = {"LSB", "USB", "CW2k4", "CW500", "AM6k", "AM2k4", "FM", "FM", "RTTYL", "RTTYU", "PKTL", "PKTFM", "????"}; - -char FT1000Modes[13][6] = {"LSB", "USB", "CW", "CWR", "AM", "AMS", "FM", "WFM", "RTTYL", "RTTYU", "PKTL", "PKTF", "????"}; - -char FTRXModes[8][6] = {"LSB", "USB", "CW", "AM", "FM", "RTTY", "PKT", ""}; - -char KenwoodModes[16][6] = {"????", "LSB", "USB", "CW", "FM", "AM", "FSK", "????"}; - -//char FT2000Modes[16][6] = {"????", "LSB", "USB", "CW", "FM", "AM", "FSK", "PKT-L", "FSK-R", "PKT-FM", "FM-N", "PKT-U", "????"}; -char FT2000Modes[16][6] = {"????", "LSB", "USB", "CW", "FM", "AM", "FSK", "CW-R", "PKT-L", "FSK-R", "PKT-FM", "FM-N", "PKT-U", "????"}; - -char FT991AModes[16][9] = {"????", "LSB", "USB", "CW-U", "FM", "AM", "RTTY-LSB", "CW-L", "DATA-LSB", "RTTY-USB", "DATA-FM", "FM-N", "DATA-USB", "AM-N", "C4FM", "????"}; - -char FLEXModes[16][6] = {"LSB", "USB", "DSB", "CWL", "CWU", "FM", "AM", "DIGU", "SPEC", "DIGL", "SAM", "DRM"}; - -char AuthPassword[100] = ""; - -char LastPassword[17]; - -int NumberofPorts = 0; - -BOOL EndPTTCATThread = FALSE; - -int HAMLIBMasterRunning = 0; -int HAMLIBSlaveRunning = 0; -int FLRIGRunning = 0; - -char * RigWebPage = 0; -int RigWebPageLen = 0; - - -struct RIGPORTINFO * PORTInfo[34] = {NULL}; // Records are Malloc'd - -struct RIGINFO * DLLRIG = NULL; // Rig record for dll PTT interface (currently only for UZ7HO); - - -struct TimeScan * AllocateTimeRec(struct RIGINFO * RIG) -{ - struct TimeScan * Band = zalloc(sizeof (struct TimeScan)); - - RIG->TimeBands = realloc(RIG->TimeBands, (++RIG->NumberofBands+2) * sizeof(void *)); - RIG->TimeBands[RIG->NumberofBands] = Band; - RIG->TimeBands[RIG->NumberofBands+1] = NULL; - - return Band; -} - -struct ScanEntry ** CheckTimeBands(struct RIGINFO * RIG) -{ - int i = 0; - time_t NOW = time(NULL) % 86400; - - // Find TimeBand - - while (i < RIG->NumberofBands) - { - if (RIG->TimeBands[i + 1]->Start > NOW) - { - break; - } - i++; - } - - RIG->FreqPtr = RIG->TimeBands[i]->Scanlist; - - return RIG->FreqPtr; -} - -VOID Rig_PTTEx(struct RIGINFO * RIG, BOOL PTTState, struct TNCINFO * TNC); - -VOID Rig_PTT(struct TNCINFO * TNC, BOOL PTTState) -{ - if (TNC == NULL) return; - - if (TNC->TXRIG) - Rig_PTTEx(TNC->TXRIG, PTTState, TNC); - else - Rig_PTTEx(TNC->RIG, PTTState, TNC); -} - -VOID Rig_PTTEx(struct RIGINFO * RIG, BOOL PTTState, struct TNCINFO * TNC) -{ - struct RIGPORTINFO * PORT; - int i, Len; - char cmd[32]; - char onString[128]; // Actual CAT strings to send. May be modified for QSY on PTT - char offString[128]; - int onLen = 0, offLen = 0; - - if (RIG == NULL) return; - - PORT = RIG->PORT; - - if (PORT == NULL) - return; - - // CAT string defaults to that set up by RIGConfig in RIG->PTTOn and RIG->PTTOff, - // but can be overidden by Port specify strings from TNC->PTTOn and TNC->PTTOff. - // If PTTSetsFreq is set on a Rig, that overrides the RIG->PTTOn but not TNC->PTTOn - - - if (PTTState) - { - MySetWindowText(RIG->hPTT, "T"); - RIG->WEB_PTT = 'T'; - RIG->PTTTimer = PTTLimit; - RIG->repeatPTTOFFTimer = 0; // Cancel repeated off command - - if (TNC && TNC->PTTOn[0]) - { - memcpy(onString, TNC->PTTOn, TNC->PTTOnLen); - onLen = TNC->PTTOnLen; - } - else - { - memcpy(onString, RIG->PTTOn, RIG->PTTOnLen); - onLen = RIG->PTTOnLen; - - // If PTT_SETS_FREQ set calculate TX Freq and see if changed - - // Freq can be set on the TNC, the RIG, or calculated from current rx freq + pttOffset - - if (TNC && RIG->PTTSetsFreq) - { - long long txfreq = 0; - - if (TNC->TXFreq) - txfreq = TNC->TXFreq + TNC->TXOffset + RIG->txError; - else if (TNC->RIG && TNC->RIG->txFreq) - txfreq = RIG->txFreq; // Used if not associated with a TNC port - eg HAMLIB + WSJT - else if (TNC->RIG && TNC->RIG->RigFreq != 0.0) - { - // Use RigFreq + pttOffset, so TX Tracks RX - - long long rxfreq = (long long)(TNC->RIG->RigFreq * 1000000.0) - TNC->RIG->rxOffset; - txfreq = rxfreq + RIG->pttOffset + RIG->txError; - txfreq += RIG->rxError; - } - - if (txfreq) - { - if (RIG->lastSetFreq != txfreq) - { - char FreqString[80]; - char * CmdPtr = onString; - - RIG->lastSetFreq = txfreq; - - // Convert to CAT string - - sprintf(FreqString, "%012d", txfreq); - - switch (PORT->PortType) - { - case ICOM: - - // CI-V must send all commands as one string, or Radio will start to ack them and - // collide with rest of command - - // Set Freq is sent before set PTT, so set up QSY string then copy PTT string to buffer - // Need to convert two chars to bcd digit - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x5; // Set frequency command - - *(CmdPtr++) = (FreqString[11] - 48) | ((FreqString[10] - 48) << 4); - *(CmdPtr++) = (FreqString[9] - 48) | ((FreqString[8] - 48) << 4); - *(CmdPtr++) = (FreqString[7] - 48) | ((FreqString[6] - 48) << 4); - *(CmdPtr++) = (FreqString[5] - 48) | ((FreqString[4] - 48) << 4); - if (RIG->IC735) - { - *(CmdPtr++) = 0xFD; - onLen = 10; - } - else - { - *(CmdPtr++) = (FreqString[3] - 48); - *(CmdPtr++) = 0xFD; - onLen = 11; - } - - // Now add PTT String - - memcpy(&onString[onLen], RIG->PTTOn, RIG->PTTOnLen); - onLen += RIG->PTTOnLen; - - break; - - case HAMLIB: - - // Dont need to save, as we can send strings separately - - Len = sprintf(cmd, "F %lld\n", txfreq); - i = send(PORT->remoteSock, cmd, Len, 0); - RIG->PollCounter = 100; // Don't read for 10 secs to avoid clash with PTT OFF - } - } - } - } - } - } - else - { - // Drop PTT - - MySetWindowText(RIG->hPTT, " "); - RIG->WEB_PTT = ' '; - RIG->PTTTimer = 0; - if (PORT->PortType == ICOM) - RIG->repeatPTTOFFTimer = 300; // set 30 second repeated off command - - if (TNC && TNC->PTTOff[0]) - { - memcpy(offString, TNC->PTTOff, TNC->PTTOffLen); - offLen = TNC->PTTOffLen; - RIG->lastSetFreq = 0; - } - else - { - memcpy(offString, RIG->PTTOff, RIG->PTTOffLen); - offLen = RIG->PTTOffLen; - - // If PTT_SETS_FREQ set calculate TX Freq and see if changed - - if (PTTState == 0 && RIG->PTTSetsFreq && RIG->defaultFreq) - { - // Dropped PTT. See if need to set freq back to default - - long long txfreq = RIG->defaultFreq + RIG->txError; - - if (RIG->lastSetFreq != txfreq) - { - char FreqString[80]; - char * CmdPtr = offString; - - RIG->lastSetFreq = txfreq; - - // Convert to CAT string - - sprintf(FreqString, "%012d", txfreq); - - switch (PORT->PortType) - { - case ICOM: - - // CI-V must send all commands as one string, or Radio will start to ack them and - // collide with rest of command - - // Set Freq is sent after drop PTT, so copy PTT string to buffer then set up QSY string - // Need to convert two chars to bcd digit - - // We copied off string earlier, so just append QSY string - - CmdPtr += offLen; - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x5; // Set frequency command - - *(CmdPtr++) = (FreqString[11] - 48) | ((FreqString[10] - 48) << 4); - *(CmdPtr++) = (FreqString[9] - 48) | ((FreqString[8] - 48) << 4); - *(CmdPtr++) = (FreqString[7] - 48) | ((FreqString[6] - 48) << 4); - *(CmdPtr++) = (FreqString[5] - 48) | ((FreqString[4] - 48) << 4); - if (RIG->IC735) - { - *(CmdPtr++) = 0xFD; - offLen += 10; - } - else - { - *(CmdPtr++) = (FreqString[3] - 48); - *(CmdPtr++) = 0xFD; - offLen += 11; - } - - case FLRIG: - - sprintf(cmd, "%lld", txfreq); - FLRIGSendCommand(PORT, "rig.set_vfo", cmd); - RIG->PollCounter = 100; // Don't read for 10 secs to avoid clash with PTT OFF - - case HAMLIB: - - // Dont need to save, as we can send strings separately - - Len = sprintf(cmd, "F %lld\n", txfreq); - send(PORT->remoteSock, cmd, Len, 0); - RIG->PollCounter = 100; // Don't read for 10 secs to avoid clash with PTT OFF - } - } - } - } - } - - // Now send the command - - if (RIG->PTTMode & PTTCI_V) - { - UCHAR * Poll = PORT->TXBuffer; - - // Don't read for 10 secs to avoid clash with PTT OFF - // Should do this for all rigs on port - - for (i = 0; i< PORT->ConfiguredRigs; i++) - PORT->Rigs[i].PollCounter = 100; - - PORT->AutoPoll = TRUE; - - switch (PORT->PortType) - { - case ICOM: - case KENWOOD: - case FT2000: - case FT991A: - case FLEX: - case NMEA: - - if (PTTState) - { - memcpy(Poll, onString, onLen); - PORT->TXLen = onLen; - } - else - { - memcpy(Poll, offString, offLen); - PORT->TXLen = offLen; - } - - RigWriteCommBlock(PORT); - - if (PORT->PortType == ICOM && !PTTState) - RigWriteCommBlock(PORT); // Send ICOM PTT OFF Twice - - PORT->Retries = 1; - - if (PORT->PortType != ICOM) - PORT->Timeout = 0; - - return; - - case FT100: - case FT990: - case FT1000: - - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = PTTState; // OFF/ON - *(Poll++) = 15; - - PORT->TXLen = 5; - RigWriteCommBlock(PORT); - - PORT->Retries = 1; - PORT->Timeout = 0; - - return; - - case YAESU: // 897 - maybe others - - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = PTTState ? 0x08 : 0x88; // CMD = 08 : PTT ON CMD = 88 : PTT OFF - - PORT->TXLen = 5; - RigWriteCommBlock(PORT); - - PORT->Retries = 1; - PORT->Timeout = 0; - - return; - - case FLRIG: - - sprintf(cmd, "%d", PTTState); - FLRIGSendCommand(PORT, "rig.set_ptt", cmd); - RIG->PollCounter = 100; // Don't read for 10 secs to avoid clash with PTT OFF - - return; - - case HAMLIB: - - Len = sprintf(cmd, "T %d\n", PTTState); - send(PORT->remoteSock, cmd, Len, 0); - RIG->PollCounter = 100; // Don't read for 10 secs to avoid clash with PTT OFF - - return; - } - } - - if (RIG->PTTMode & PTTRTS) - if (PTTState) - COMSetRTS(PORT->hPTTDevice); - else - COMClearRTS(PORT->hPTTDevice); - - if (RIG->PTTMode & PTTDTR) - if (PTTState) - COMSetDTR(PORT->hPTTDevice); - else - COMClearDTR(PORT->hPTTDevice); - - if (RIG->PTTMode & PTTCM108) - CM108_set_ptt(RIG, PTTState); - - if (RIG->PTTMode & PTTHAMLIB) - { - char Msg[16]; - int Len = sprintf(Msg, "T %d\n", PTTState); - - Len = send(PORT->remoteSock, Msg, Len, 0); - RIG->PollCounter = 100; // Don't read for 10 secs to avoid clash with PTT OFF - } - if (RIG->PTTMode & PTTFLRIG) - { - char cmd[32]; - - sprintf(cmd, "%d", PTTState); - FLRIGSendCommand(PORT, "rig.set_ptt", cmd); - RIG->PollCounter = 100; // Don't read for 10 secs to avoid clash with PTT OFF - } -} - -void saveNewFreq(struct RIGINFO * RIG, double Freq, char * Mode) -{ - if (Freq > 0.0) - { - _gcvt((Freq + RIG->rxOffset) / 1000000.0, 9, RIG->Valchar); - strcpy(RIG->WEB_FREQ, RIG->Valchar); - MySetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - } - - if (Mode[0]) - { - strcpy(RIG->ModeString, Mode); - MySetWindowText(RIG->hMODE, Mode); - } - -} - -// Need version that doesn't need Port Number - -int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, int Session, char * Command); - -int Rig_Command(int Session, char * Command) -{ - char * ptr; - int i, n, p, Port; - TRANSPORTENTRY * L4 = L4TABLE; - struct RIGPORTINFO * PORT; - struct RIGINFO * RIG; - - // Only Allow RADIO from Secure Applications - - _strupr(Command); - - ptr = strchr(Command, 13); - if (ptr) *(ptr) = 0; // Null Terminate - - if (memcmp(Command, "AUTH ", 5) == 0) - { - if (AuthPassword[0] && (memcmp(LastPassword, &Command[5], 16) != 0)) - { - if (CheckOneTimePassword(&Command[5], AuthPassword)) - { - L4 += Session; - L4->Secure_Session = 1; - - sprintf(Command, "Ok\r"); - - memcpy(LastPassword, &Command[5], 16); // Save - - return FALSE; - } - } - - sprintf(Command, "Sorry AUTH failed\r"); - return FALSE; - } - - if (Session != -1) // Used for internal Stop/Start - { - L4 += Session; - - if (L4->Secure_Session == 0) - { - sprintf(Command, "Sorry - you are not allowed to use this command\r"); - return FALSE; - } - } - if (NumberofPorts == 0) - { - sprintf(Command, "Sorry - Rig Control not configured\r"); - return FALSE; - } - - // if Port starts with 'R' then select Radio (was Interlock) number, not BPQ Port - - if (Command[0] == 'R') - { - n = sscanf(&Command[1],"%d ", &Port); - - for (p = 0; p < NumberofPorts; p++) - { - PORT = PORTInfo[p]; - - for (i=0; i< PORT->ConfiguredRigs; i++) - { - RIG = &PORT->Rigs[i]; - - if (RIG->Interlock == Port) - goto portok; - } - } - - sprintf(Command, "Sorry - Port not found\r"); - return FALSE; - } - - n = sscanf(Command,"%d ", &Port); - - // Look for the port - - - for (p = 0; p < NumberofPorts; p++) - { - PORT = PORTInfo[p]; - - for (i=0; i< PORT->ConfiguredRigs; i++) - { - RIG = &PORT->Rigs[i]; - - if (RIG->BPQPort & (1 << Port)) - goto portok; - } - } - - sprintf(Command, "Sorry - Port not found\r"); - return FALSE; - -portok: - - return Rig_CommandEx(PORT, RIG, Session, Command); -} - - - -static char MsgHddr[] = "POST /RPC2 HTTP/1.1\r\n" - "User-Agent: XMLRPC++ 0.8\r\n" - "Host: 127.0.0.1:7362\r\n" - "Content-Type: text/xml\r\n" - "Content-length: %d\r\n" - "\r\n%s"; - -static char Req[] = "\r\n" - "%s\r\n" - "%s" - "\r\n"; - - - - -int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, int Session, char * Command) -{ - int n, ModeNo, Filter, Port = 0; - double Freq = 0.0; - char FreqString[80]="", FilterString[80]="", Mode[80]="", Data[80] = "", Dummy[80] = ""; - struct MSGWITHOUTLEN * buffptr; - UCHAR * Poll; - - int i; - TRANSPORTENTRY * L4 = L4TABLE; - char * ptr; - int Split, DataFlag, Bandwidth, Antenna; - struct ScanEntry * FreqPtr; - char * CmdPtr; - int Len; - char MemoryBank = 0; // For Memory Scanning - int MemoryNumber = 0; - - // Only Allow RADIO from Secure Applications - - _strupr(Command); - - ptr = strchr(Command, 13); - if (ptr) *(ptr) = 0; // Null Terminate - - if (memcmp(Command, "AUTH ", 5) == 0) - { - if (AuthPassword[0] && (memcmp(LastPassword, &Command[5], 16) != 0)) - { - if (CheckOneTimePassword(&Command[5], AuthPassword)) - { - L4 += Session; - L4->Secure_Session = 1; - - sprintf(Command, "Ok\r"); - - memcpy(LastPassword, &Command[5], 16); // Save - - return FALSE; - } - } - - sprintf(Command, "Sorry AUTH failed\r"); - return FALSE; - } - - if (Session != -1) // Used for internal Stop/Start - { - L4 += Session; - - if (L4->Secure_Session == 0) - { - sprintf(Command, "Sorry - you are not allowed to use this command\r"); - return FALSE; - } - } - if (NumberofPorts == 0) - { - sprintf(Command, "Sorry - Rig Control not configured\r"); - return FALSE; - } - - // if Port starts with 'R' then select Radio (was Interlock) number, not BPQ Port - - if (Command[0] == 'R') - n = sscanf(Command,"%s %s %s %s %s", &Dummy, &FreqString[0], &Mode[0], &FilterString[0], &Data[0]); - else - n = sscanf(Command,"%d %s %s %s %s", &Port, &FreqString[0], &Mode[0], &FilterString[0], &Data[0]); - - if (_stricmp(FreqString, "CLOSE") == 0) - { - PORT->Closed = 1; - RigCloseConnection(PORT); - - MySetWindowText(RIG->hSCAN, "C"); - RIG->WEB_SCAN = 'C'; - - sprintf(Command, "Ok\r"); - return FALSE; - } - - if (_stricmp(FreqString, "OPEN") == 0) - { - PORT->ReopenDelay = 300; - PORT->Closed = 0; - - MySetWindowText(RIG->hSCAN, ""); - RIG->WEB_SCAN = ' '; - - sprintf(Command, "Ok\r"); - return FALSE; - } - - if (n > 1) - { - if (_stricmp(FreqString, "SCANSTART") == 0) - { - if (RIG->NumberofBands) - { - RIG->ScanStopped &= (0xffffffff ^ (1 << Port)); - - if (Session != -1) // Used for internal Stop/Start - RIG->ScanStopped &= 0xfffffffe; // Clear Manual Stopped Bit - - if (n > 2) - RIG->ScanCounter = atoi(Mode) * 10; //Start Delay - else - RIG->ScanCounter = 10; - - RIG->WaitingForPermission = FALSE; // In case stuck - - if (RIG->ScanStopped == 0) - { - SetWindowText(RIG->hSCAN, "S"); - RIG->WEB_SCAN = 'S'; - } - sprintf(Command, "Ok\r"); - - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 SCANSTART Port %d", Port); - } - else - sprintf(Command, "Sorry no Scan List defined for this port\r"); - - return FALSE; - } - - if (_stricmp(FreqString, "SCANSTOP") == 0) - { - RIG->ScanStopped |= (1 << Port); - - if (Session != -1) // Used for internal Stop/Start - RIG->ScanStopped |= 1; // Set Manual Stopped Bit - - MySetWindowText(RIG->hSCAN, ""); - RIG->WEB_SCAN = ' '; - - sprintf(Command, "Ok\r"); - - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 SCANSTOP Port %d", Port); - - RIG->PollCounter = 50 / RIG->PORT->ConfiguredRigs; // Dont read freq for 5 secs - - return FALSE; - } - } - - - - if (RIG->RIGOK == 0) - { - if (Session != -1) - { - if (PORT->Closed) - sprintf(Command, "Sorry - Radio port closed\r"); - else - sprintf(Command, "Sorry - Radio not responding\r"); - } - return FALSE; - } - - if (n == 2 && _stricmp(FreqString, "FREQ") == 0) - { - if (RIG->Valchar[0]) - sprintf(Command, "Frequency is %s MHz\r", RIG->Valchar); - else - sprintf(Command, "Frequency not known\r"); - - return FALSE; - } - - if (n == 2 && _stricmp(FreqString, "PTT") == 0) - { - Rig_PTTEx(RIG, TRUE, NULL); - RIG->PTTTimer = 10; // 1 sec - sprintf(Command, "Ok\r"); - return FALSE; - } - - RIG->Session = Session; // BPQ Stream - RIG->PollCounter = 50; // Dont read freq for 5 secs in case clash with Poll - - if (_stricmp(FreqString, "TUNE") == 0) - { - char ReqBuf[256]; - char SendBuff[256]; - char FLPoll[80]; - - switch (PORT->PortType) - { - case ICOM: - - buffptr = GetBuff(); - - if (buffptr == 0) - { - sprintf(Command, "Sorry - No Buffers available\r"); - return FALSE; - } - - - // Build a ScanEntry in the buffer - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - CmdPtr = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - FreqPtr->Cmd2 = NULL; - FreqPtr->Cmd3 = NULL; - - // IC7100 Tune Fe fe 88 e0 1c 01 02 fd - - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x1C; - *(CmdPtr++) = 0x01; - *(CmdPtr++) = 0x02; - *(CmdPtr++) = 0xFD; - FreqPtr[0].Cmd1Len = 8; - - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - - return TRUE; - - case KENWOOD: - - buffptr = GetBuff(); - - if (buffptr == 0) - { - sprintf(Command, "Sorry - No Buffers available\r"); - return FALSE; - } - - // Build a ScanEntry in the buffer - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - Poll = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - - FreqPtr->Cmd1Len = sprintf(Poll, "AC111;AC;"); - - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - return TRUE; - - case FLRIG: - - strcpy(FLPoll, "rig.tune"); - - Len = sprintf(ReqBuf, Req, FLPoll, ""); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - - if (PORT->CONNECTED) - { - if (send(PORT->remoteSock, SendBuff, Len, 0) != Len) - { - if (PORT->remoteSock) - closesocket(PORT->remoteSock); - - PORT->remoteSock = 0; - PORT->CONNECTED = FALSE; - PORT->hDevice = 0; - } - } - sprintf(Command, "Ok\r"); - return FALSE; - } - - sprintf(Command, "Sorry - TUNE not supported on your radio\r"); - return FALSE; - } - - if (_stricmp(FreqString, "POWER") == 0) - { - char PowerString[8] = ""; - int Power = atoi(Mode); - int len; - char cmd[80]; - - switch (PORT->PortType) - { - case ICOM: - - if (n != 3 || Power > 255) - { - strcpy(Command, "Sorry - Invalid Format - should be POWER Level (0 - 255)\r"); - return FALSE; - } - - sprintf(PowerString, "%04d", Power); - - buffptr = GetBuff(); - - if (buffptr == 0) - { - sprintf(Command, "Sorry - No Buffers available\r"); - return FALSE; - } - - - // Build a ScanEntry in the buffer - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - CmdPtr = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - FreqPtr->Cmd2 = NULL; - FreqPtr->Cmd3 = NULL; - - // IC7100 Set Power Fe fe 88 e0 14 0a xx xx fd - - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x14; - *(CmdPtr++) = 0x0A; - - // Need to convert param to decimal digits - - *(CmdPtr++) = (PowerString[1] - 48) | ((PowerString[0] - 48) << 4); - *(CmdPtr++) = (PowerString[3] - 48) | ((PowerString[2] - 48) << 4); - - *(CmdPtr++) = 0xFD; - FreqPtr[0].Cmd1Len = 9; - - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - - return TRUE; - - case KENWOOD: - - if (n != 3 || Power > 200 || Power < 5) - { - strcpy(Command, "Sorry - Invalid Format - should be POWER Level (5 - 200)\r"); - return FALSE; - } - - buffptr = GetBuff(); - - if (buffptr == 0) - { - sprintf(Command, "Sorry - No Buffers available\r"); - return FALSE; - } - - // Build a ScanEntry in the buffer - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - Poll = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - - FreqPtr->Cmd1Len = sprintf(Poll, "PC%03d;PC;", Power); - - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - return TRUE; - - case FLRIG: - - len = sprintf(cmd, "%d", Power); - - FLRIGSendCommand(PORT, "rig.set_power", cmd); - - sprintf(Command, "Ok\r"); - return FALSE; - } - - sprintf(Command, "Sorry - POWER not supported on your Radio\r"); - return FALSE; - } - - if (_stricmp(FreqString, "CMD") == 0) - { - // Send arbitrary command to radio - - char c; - int val; - char * ptr1; - int Len; - - if (n < 3) - { - strcpy(Command, "Sorry - Invalid Format - should be HEX Hexstring\r"); - return FALSE; - } - - buffptr = GetBuff(); - - if (buffptr == NULL) - return FALSE; - - ptr1 = strstr(Command, "CMD"); - - if (ptr1 == NULL) - return FALSE; - - ptr1 += 4; - - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - CmdPtr = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - FreqPtr->Cmd2 = NULL; - FreqPtr->Cmd3 = NULL; - - - switch (PORT->PortType) - { - case ICOM: - - // String is in Hex - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - - while (c = *(ptr1++)) - { - if (c == ' ') continue; // Allow space between pairs - - val = c - 0x30; - if (val > 15) val -= 7; - val <<= 4; - c = *(ptr1++) - 0x30; - if (c > 15) c -= 7; - val |= c; - *(CmdPtr++) = val; - } - - *(CmdPtr++) = 0xFD; - - - *(CmdPtr) = 0; - - Len = (int)(CmdPtr - (char *)&buffptr[30]); - break; - - case KENWOOD: - case FT991A: - case FT2000: - case FLEX: - case NMEA: - - // use text command - - Len = sprintf(CmdPtr, ptr1); - break; - - case YAESU: - - // String is in Hex (5 values) - - while (c = *(ptr1++)) - { - if (c == ' ') continue; // Allow space between pairs - - val = c - 0x30; - if (val > 15) val -= 7; - val <<= 4; - c = *(ptr1++) - 0x30; - if (c > 15) c -= 7; - val |= c; - *(CmdPtr++) = val; - } - - *(CmdPtr) = 0; - - Len = 5; - break; - - default: - sprintf(Command, "Sorry - CMD not supported on your Radio\r"); - return FALSE; - } - - FreqPtr[0].Cmd1Len = Len; // for ICOM - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - return TRUE; - } - - if (_memicmp(FreqString, "Chan", 4) == 0) - { - if (strchr(FreqString, '/') ) // Bank/Chan - { - MemoryBank = FreqString[4]; - MemoryNumber = atoi(&FreqString[6]); - } - else - MemoryNumber = atoi(&FreqString[4]); // Just Chan - - Freq = 0.0; - } - else - { - Freq = atof(FreqString); - - if (Freq < 0.1 && PORT->PortType != FLRIG) - { - strcpy(Command, "Sorry - Invalid Frequency\r"); - return FALSE; - } - } - - Freq = Freq * 1000000.0; - - sprintf(FreqString, "%09.0f", Freq); - - if (PORT->PortType != ICOM) - strcpy(Data, FilterString); // Others don't have a filter. - - Split = DataFlag = Bandwidth = Antenna = 0; - - _strupr(Data); - - if (strchr(Data, '+')) - Split = '+'; - else if (strchr(Data, '-')) - Split = '-'; - else if (strchr(Data, 'S')) - Split = 'S'; - else if (strchr(Data, 'D')) - DataFlag = 1; - - if (strchr(Data, 'W')) - Bandwidth = 'W'; - else if (strchr(Data, 'N')) - Bandwidth = 'N'; - - if (strstr(Data, "A1")) - Antenna = '1'; - else if (strstr(Data, "A2")) - Antenna = '2'; - else if (strstr(Data, "A3")) - Antenna = '3'; - else if (strstr(Data, "A4")) - Antenna = '4'; - else if (strstr(Data, "A5")) - Antenna = '5'; - else if (strstr(Data, "A6")) - Antenna = '6'; - - switch (PORT->PortType) - { - case ICOM: - - if (n == 2) - // Set Freq Only - - ModeNo = -1; - else - { - if (n < 4 && RIG->ICF8101 == 0) - { - strcpy(Command, "Sorry - Invalid Format - should be Port Freq Mode Filter Width\r"); - return FALSE; - } - - Filter = atoi(FilterString); - - for (ModeNo = 0; ModeNo < 24; ModeNo++) - { - if (_stricmp(Modes[ModeNo], Mode) == 0) - break; - } - - if (ModeNo == 24) - { - sprintf(Command, "Sorry - Invalid Mode\r"); - return FALSE; - } - } - - buffptr = GetBuff(); - - if (buffptr == 0) - { - sprintf(Command, "Sorry - No Buffers available\r"); - return FALSE; - } - - // Build a ScanEntry in the buffer - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - FreqPtr->Freq = Freq; - FreqPtr->Bandwidth = Bandwidth; - FreqPtr->Antenna = Antenna; - FreqPtr->Dwell = 51; - - CmdPtr = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - FreqPtr->Cmd2 = NULL; - FreqPtr->Cmd3 = NULL; - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - - - if (MemoryNumber) - { - // Set Memory Channel instead of Freq, Mode, etc - - char ChanString[5]; - - // Send Set Memory, then Channel - - *(CmdPtr++) = 0x08; - *(CmdPtr++) = 0xFD; - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - - sprintf(ChanString, "%04d", MemoryNumber); - - *(CmdPtr++) = 0x08; - *(CmdPtr++) = (ChanString[1] - 48) | ((ChanString[0] - 48) << 4); - *(CmdPtr++) = (ChanString[3] - 48) | ((ChanString[2] - 48) << 4); - *(CmdPtr++) = 0xFD; - - FreqPtr[0].Cmd1Len = 14; - - if (MemoryBank) - { - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x08; - *(CmdPtr++) = 0xA0; - *(CmdPtr++) = MemoryBank - 0x40; - *(CmdPtr++) = 0xFD; - - FreqPtr[0].Cmd1Len += 8; - } - } - else - { - if (RIG->ICF8101) - { - // Set Freq is 1A 35 and set Mode 1A 36 - - *(CmdPtr++) = 0x1A; - *(CmdPtr++) = 0x35; // Set frequency command - - // Need to convert two chars to bcd digit - - *(CmdPtr++) = (FreqString[8] - 48) | ((FreqString[7] - 48) << 4); - *(CmdPtr++) = (FreqString[6] - 48) | ((FreqString[5] - 48) << 4); - *(CmdPtr++) = (FreqString[4] - 48) | ((FreqString[3] - 48) << 4); - *(CmdPtr++) = (FreqString[2] - 48) | ((FreqString[1] - 48) << 4); - *(CmdPtr++) = (FreqString[0] - 48); - *(CmdPtr++) = 0xFD; - FreqPtr[0].Cmd1Len = 12; - - if (ModeNo != -1) // Dont Set - { - CmdPtr = FreqPtr->Cmd2 = FreqPtr->Cmd2Msg; - FreqPtr[0].Cmd2Len = 9; - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x1A; - *(CmdPtr++) = 0x36; // Set mode command - *(CmdPtr++) = 0; - if (ModeNo > 10) - *(CmdPtr++) = ModeNo + 6; - else - *(CmdPtr++) = ModeNo; - *(CmdPtr++) = 0xFD; - } - } - else - { - - *(CmdPtr++) = 0x5; // Set frequency command - - // Need to convert two chars to bcd digit - - *(CmdPtr++) = (FreqString[8] - 48) | ((FreqString[7] - 48) << 4); - *(CmdPtr++) = (FreqString[6] - 48) | ((FreqString[5] - 48) << 4); - *(CmdPtr++) = (FreqString[4] - 48) | ((FreqString[3] - 48) << 4); - *(CmdPtr++) = (FreqString[2] - 48) | ((FreqString[1] - 48) << 4); - if (RIG->IC735) - { - *(CmdPtr++) = 0xFD; - FreqPtr[0].Cmd1Len = 10; - } - else - { - *(CmdPtr++) = (FreqString[0] - 48); - *(CmdPtr++) = 0xFD; - FreqPtr[0].Cmd1Len = 11; - } - - // Send Set VFO in case last chan was memory - - // *(CmdPtr++) = 0xFE; - // *(CmdPtr++) = 0xFE; - // *(CmdPtr++) = RIG->RigAddr; - // *(CmdPtr++) = 0xE0; - - // *(CmdPtr++) = 0x07; - // *(CmdPtr++) = 0xFD; - - // FreqPtr[0].Cmd1Len = 17; - - if (ModeNo != -1) // Dont Set - { - CmdPtr = FreqPtr->Cmd2 = FreqPtr->Cmd2Msg; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x6; // Set Mode - *(CmdPtr++) = ModeNo; - *(CmdPtr++) = Filter; - *(CmdPtr++) = 0xFD; - - FreqPtr->Cmd2Len = 8; - - if (Split) - { - CmdPtr = FreqPtr->Cmd3 = FreqPtr->Cmd3Msg; - FreqPtr->Cmd3Len = 7; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0xF; // Set Mode - if (Split == 'S') - *(CmdPtr++) = 0x10; - else - if (Split == '+') - *(CmdPtr++) = 0x12; - else - if (Split == '-') - *(CmdPtr++) = 0x11; - - *(CmdPtr++) = 0xFD; - } - else if (DataFlag) - { - CmdPtr = FreqPtr->Cmd3 = FreqPtr->Cmd3Msg; - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x1a; - - if ((strcmp(RIG->RigName, "IC7100") == 0) || - (strcmp(RIG->RigName, "IC7410") == 0) || - (strcmp(RIG->RigName, "IC7600") == 0) || - (strcmp(RIG->RigName, "IC7610") == 0) || - (strcmp(RIG->RigName, "IC7300") == 0)) - { - FreqPtr[0].Cmd3Len = 9; - *(CmdPtr++) = 0x6; // Send/read DATA mode with filter set - *(CmdPtr++) = 0x1; // Data On - *(CmdPtr++) = Filter; //Filter - } - else if (strcmp(RIG->RigName, "IC7200") == 0) - { - FreqPtr[0].Cmd3Len = 9; - *(CmdPtr++) = 0x4; // Send/read DATA mode with filter set - *(CmdPtr++) = 0x1; // Data On - *(CmdPtr++) = Filter; // Filter - } - else - { - FreqPtr[0].Cmd3Len = 8; - *(CmdPtr++) = 0x6; // Set Data - *(CmdPtr++) = 0x1; //On - } - - *(CmdPtr++) = 0xFD; - } - } - - if (Antenna == '5' || Antenna == '6') - { - // Antenna select for 746 and maybe others - - // Could be going in cmd2 3 or 4 - - if (FreqPtr[0].Cmd2 == NULL) - { - CmdPtr = FreqPtr->Cmd2 = FreqPtr->Cmd2Msg; - FreqPtr[0].Cmd2Len = 7; - } - else if (FreqPtr[0].Cmd3 == NULL) - { - CmdPtr = FreqPtr->Cmd3 = FreqPtr->Cmd3Msg; - FreqPtr[0].Cmd3Len = 7; - } - else - { - CmdPtr = FreqPtr->Cmd4 = FreqPtr->Cmd4Msg; - FreqPtr[0].Cmd4Len = 7; - } - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x12; // Set Antenna - *(CmdPtr++) = Antenna - '5'; // 0 for A5 1 for A6 - *(CmdPtr++) = 0xFD; - } - } - } - - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - - return TRUE; - - case YAESU: - - if (n == 2) // Just set freq - { - ModeNo = -1; - } - else - { - for (ModeNo = 0; ModeNo < 15; ModeNo++) - { - if (_stricmp(YaesuModes[ModeNo], Mode) == 0) - break; - } - - if (ModeNo == 15) - { - sprintf(Command, "Sorry -Invalid Mode\r"); - return FALSE; - } - } - - buffptr = GetBuff(); - - if (buffptr == 0) - { - sprintf(Command, "Sorry - No Buffers available\r"); - return FALSE; - } - - // Build a ScanEntry in the buffer - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - FreqPtr->Freq = Freq; - FreqPtr->Bandwidth = Bandwidth; - FreqPtr->Antenna = Antenna; - - Poll = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - - // Send Mode then Freq - setting Mode seems to change frequency - - FreqPtr->Cmd1Len = 0; - - if (ModeNo != -1) // Set freq only - { - *(Poll++) = ModeNo; - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 7; // Set Mode - FreqPtr->Cmd1Len = 5; - } - - *(Poll++) = (FreqString[1] - 48) | ((FreqString[0] - 48) << 4); - *(Poll++) = (FreqString[3] - 48) | ((FreqString[2] - 48) << 4); - *(Poll++) = (FreqString[5] - 48) | ((FreqString[4] - 48) << 4); - *(Poll++) = (FreqString[7] - 48) | ((FreqString[6] - 48) << 4); - *(Poll++) = 1; // Set Freq - - FreqPtr->Cmd1Len += 5; - - if (strcmp(PORT->Rigs[0].RigName, "FT847") == 0) - { - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 3; // Status Poll - - FreqPtr->Cmd1Len = 15; - } - - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - - return TRUE; - - - case FT100: - case FT990: - case FT1000: - - if (n == 2) // Set Freq Only - ModeNo = -1; - else - { - if (n < 3) - { - strcpy(Command, "Sorry - Invalid Format - should be Port Freq Mode\r"); - return FALSE; - } - - if (PORT->PortType == FT100) - { - for (ModeNo = 0; ModeNo < 8; ModeNo++) - { - if (_stricmp(FT100Modes[ModeNo], Mode) == 0) - break; - } - - if (ModeNo == 8) - { - sprintf(Command, "Sorry -Invalid Mode\r"); - return FALSE; - } - } - else if (PORT->PortType == FT990) - { - for (ModeNo = 0; ModeNo < 12; ModeNo++) - { - if (_stricmp(FT990Modes[ModeNo], Mode) == 0) - break; - } - - if (ModeNo == 12) - { - sprintf(Command, "Sorry -Invalid Mode\r"); - return FALSE; - } - } - else - { - for (ModeNo = 0; ModeNo < 12; ModeNo++) - { - if (_stricmp(FT1000Modes[ModeNo], Mode) == 0) - break; - } - - if (ModeNo == 12) - { - sprintf(Command, "Sorry -Invalid Mode\r"); - return FALSE; - } - } - } - - buffptr = GetBuff(); - - if (buffptr == 0) - { - sprintf(Command, "Sorry - No Buffers available\r"); - return FALSE; - } - - // Build a ScanEntry in the buffer - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - FreqPtr->Freq = Freq; - FreqPtr->Bandwidth = Bandwidth; - FreqPtr->Antenna = Antenna; - - Poll = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - - // Send Mode then Freq - setting Mode seems to change frequency - - if (ModeNo == -1) // Don't set Mode - { - // Changing the length messes up a lot of code, - // so set freq twice instead of omitting entry - - *(Poll++) = (FreqString[7] - 48) | ((FreqString[6] - 48) << 4); - *(Poll++) = (FreqString[5] - 48) | ((FreqString[4] - 48) << 4); - *(Poll++) = (FreqString[3] - 48) | ((FreqString[2] - 48) << 4); - *(Poll++) = (FreqString[1] - 48) | ((FreqString[0] - 48) << 4); - *(Poll++) = 10; // Set Freq - } - else - { - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = ModeNo; - *(Poll++) = 12; // Set Mode - } - - *(Poll++) = (FreqString[7] - 48) | ((FreqString[6] - 48) << 4); - *(Poll++) = (FreqString[5] - 48) | ((FreqString[4] - 48) << 4); - *(Poll++) = (FreqString[3] - 48) | ((FreqString[2] - 48) << 4); - *(Poll++) = (FreqString[1] - 48) | ((FreqString[0] - 48) << 4); - *(Poll++) = 10; // Set Freq - - *(Poll++) = 0; - *(Poll++) = 0; - *(Poll++) = 0; - if (PORT->PortType == FT990 || PORT->YaesuVariant == FT1000D) - *(Poll++) = 3; - else - *(Poll++) = 2; // 100 or 1000MP - - *(Poll++) = 16; // Status Poll - - FreqPtr->Cmd1Len = 15; - - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - - return TRUE; - - case KENWOOD: - case FT2000: - case FT991A: - case FLEX: - - if (n < 3) - { - strcpy(Command, "Sorry - Invalid Format - should be Port Freq Mode\r"); - return FALSE; - } - - for (ModeNo = 0; ModeNo < 16; ModeNo++) - { - if (PORT->PortType == FT2000) - if (_stricmp(FT2000Modes[ModeNo], Mode) == 0) - break; - - if (PORT->PortType == FT991A) - if (_stricmp(FT991AModes[ModeNo], Mode) == 0) - break; - - if (PORT->PortType == KENWOOD) - if (_stricmp(KenwoodModes[ModeNo], Mode) == 0) - break; - if (PORT->PortType == FLEX) - if (_stricmp(FLEXModes[ModeNo], Mode) == 0) - break; - } - - if (ModeNo > 15) - { - sprintf(Command, "Sorry -Invalid Mode\r"); - return FALSE; - } - - buffptr = GetBuff(); - - if (buffptr == 0) - { - sprintf(Command, "Sorry - No Buffers available\r"); - return FALSE; - } - - // Build a ScanEntry in the buffer - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - FreqPtr->Freq = Freq; - FreqPtr->Bandwidth = Bandwidth; - FreqPtr->Antenna = Antenna; - - Poll = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - - if (PORT->PortType == FT2000) - FreqPtr->Cmd1Len = sprintf(Poll, "FA%s;MD0%X;FA;MD;", &FreqString[1], ModeNo); - else - if (PORT->PortType == FT991A) - FreqPtr->Cmd1Len = sprintf(Poll, "FA%s;MD0%X;FA;MD;", &FreqString, ModeNo); - else - if (PORT->PortType == FLEX) - FreqPtr->Cmd1Len = sprintf(Poll, "ZZFA00%s;ZZMD%02d;ZZFA;ZZMD;", &FreqString[1], ModeNo); - else - { - if (Antenna == '5' || Antenna == '6') - FreqPtr->Cmd1Len = sprintf(Poll, "FA00%s;MD%d;AN%c;FA;MD;", FreqString, ModeNo, Antenna - 4); - else - FreqPtr->Cmd1Len = sprintf(Poll, "FA00%s;MD%d;FA;MD;", FreqString, ModeNo); - } - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - - return TRUE; - - case NMEA: - - if (n < 3) - { - strcpy(Command, "Sorry - Invalid Format - should be Port Freq Mode\r"); - return FALSE; - } - buffptr = GetBuff(); - - if (buffptr == 0) - { - sprintf(Command, "Sorry - No Buffers available\r"); - return FALSE; - } - - // Build a ScanEntry in the buffer - - FreqPtr = (struct ScanEntry *)buffptr->Data; - memset(FreqPtr, 0, sizeof(struct ScanEntry)); - - FreqPtr->Freq = Freq; - FreqPtr->Bandwidth = Bandwidth; - FreqPtr->Antenna = Antenna; - - Poll = FreqPtr->Cmd1 = FreqPtr->Cmd1Msg; - - i = sprintf(Poll, "$PICOA,90,%02x,RXF,%.6f*xx\r\n", RIG->RigAddr, Freq/1000000.); - AddNMEAChecksum(Poll); - Len = i; - i = sprintf(Poll + Len, "$PICOA,90,%02x,TXF,%.6f*xx\r\n", RIG->RigAddr, Freq/1000000.); - AddNMEAChecksum(Poll + Len); - Len += i; - i = sprintf(Poll + Len, "$PICOA,90,%02x,MODE,%s*xx\r\n", RIG->RigAddr, Mode); - AddNMEAChecksum(Poll + Len); - - FreqPtr->Cmd1Len = i + Len; - - C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - - return TRUE; - - case HAMLIB: - { - char cmd[80]; - - int len = sprintf(cmd, "F %s\n+f\nM %s %d\n+m\n", - FreqString, Mode, atoi(Data)); - - send(PORT->remoteSock, cmd, len, 0); - sprintf(Command, "Ok\r"); - - saveNewFreq(RIG, Freq, Mode); - - return FALSE; - } - - case FLRIG: - { - char cmd[80]; - - int len = sprintf(cmd, "%.0f", Freq); - - strcpy(PORT->ScanEntry.Cmd2Msg, Mode); - strcpy(PORT->ScanEntry.Cmd3Msg, FilterString); - - if (Freq > 0.0) - FLRIGSendCommand(PORT, "rig.set_vfo", cmd); - - else if (PORT->ScanEntry.Cmd2Msg[0] && Mode[0] != '*') - { - sprintf(cmd, "%s", PORT->ScanEntry.Cmd2Msg); - FLRIGSendCommand(PORT, "rig.set_mode", cmd); - } - - else if (PORT->ScanEntry.Cmd3Msg[0] && strcmp(PORT->ScanEntry.Cmd3Msg, "0") != 0) - { - sprintf(cmd, "%s", PORT->ScanEntry.Cmd3Msg); - FLRIGSendCommand(PORT, "rig.set_bandwidth", cmd); - } - else - { - sprintf(Command, "Sorry - Nothing to do\r"); - return FALSE; - } - - PORT->AutoPoll = 0; - - saveNewFreq(RIG, Freq, Mode); - return TRUE; - } - - - case RTLUDP: - { - char cmd[80]; - int len = 5; - int FreqInt = (int)Freq; - int FM = 0; - int AM = 1; - int USB = 2; - int LSB = 3; - - cmd[0] = 0; - cmd[1] = FreqInt & 0xff; - cmd[2] = (FreqInt >> 8) & 0xff; - cmd[3] = (FreqInt >> 16) & 0xff; - cmd[4] = (FreqInt >> 24) & 0xff; - - len = sendto(PORT->remoteSock, cmd, 5, 0, &PORT->remoteDest, sizeof(struct sockaddr)); - - if (Mode[0]) - { - if (strcmp(Mode, "FM") == 0) - memcpy(&cmd[1], &FM, 4); - else if (strcmp(Mode, "AM") == 0) - memcpy(&cmd[1], &AM, 4); - else if (strcmp(Mode, "USB") == 0) - memcpy(&cmd[1], &USB, 4); - else if (strcmp(Mode, "LSB") == 0) - memcpy(&cmd[1], &LSB, 4); - - cmd[0] = 1; - len = sendto(PORT->remoteSock, cmd, 5, 0, &PORT->remoteDest, sizeof(struct sockaddr)); - } - - saveNewFreq(RIG, Freq, Mode); - - sprintf(Command, "Ok\r"); - return FALSE; - } - - - - - - } - return TRUE; -} - -int BittoInt(UINT BitMask) -{ - // Returns bit position of first 1 bit in BitMask - - int i = 0; - while ((BitMask & 1) == 0) - { - BitMask >>= 1; - i ++; - } - return i; -} - -extern char * RadioConfigMsg[36]; - -struct TNCINFO RIGTNC; // Dummy TNC Record for Rigcontrol without a corresponding TNC - -DllExport BOOL APIENTRY Rig_Init() -{ - struct RIGPORTINFO * PORT; - int i, p, port; - struct RIGINFO * RIG; - struct TNCINFO * TNC = &RIGTNC; - HWND hDlg; -#ifndef LINBPQ - int RigRow = 0; -#endif - int NeedRig = 0; - int Interlock = 0; - - memset(&RIGTNC, 0, sizeof(struct TNCINFO)); - - TNCInfo[40] = TNC; - - // Get config info - - NumberofPorts = 0; - - for (port = 0; port < 32; port++) - PORTInfo[port] = NULL; - - // See if any rigcontrol defined (either RADIO or RIGCONTROL lines) - - for (port = 0; port < 32; port++) - { - if (RadioConfigMsg[port]) - NeedRig++; - } - - if (NeedRig == 0) - { - SetupPortRIGPointers(); // Sets up Dummy Rig Pointer - return FALSE; - } - - -#ifndef LINBPQ - - TNC->Port = 40; - CreatePactorWindow(TNC, "RIGCONTROL", "RigControl", 10, PacWndProc, 550, NeedRig * 20 + 60, NULL); - hDlg = TNC->hDlg; - -#endif - - TNC->ClientHeight = NeedRig * 20 + 60; - TNC->ClientWidth = 550; - - for (port = 0; port < 33; port++) - { - if (RadioConfigMsg[port]) - { - char msg[1000]; - - char * SaveRigConfig = _strdup(RadioConfigMsg[port]); - char * RigConfigMsg1 = _strdup(RadioConfigMsg[port]); - - Interlock = atoi(&RigConfigMsg1[5]); - - RIG = RigConfig(TNC, RigConfigMsg1, port); - - if (RIG == NULL) - { - // Report Error - - sprintf(msg,"Port %d Invalid Rig Config %s", port, SaveRigConfig); - WritetoConsole(msg); - free(SaveRigConfig); - free(RigConfigMsg1); - continue; - } - - RIG->Interlock = Interlock; - - if (RIG->PORT->IOBASE[0] == 0) - { - // We have to find the SCS TNC in this scan group as TNC is now a dummy - - struct TNCINFO * PTCTNC; - int n; - - for (n = 1; n < 33; n++) - { - PTCTNC = TNCInfo[n]; - - if (PTCTNC == NULL || (PTCTNC->Hardware != H_SCS && PTCTNC->Hardware != H_ARDOP)) - continue; - - if (PTCTNC->RXRadio != Interlock) - continue; - - RIG->PORT->PTC = PTCTNC; - } - } - -#ifndef LINBPQ - - // Create line for this rig - - RIG->hLabel = CreateWindow(WC_STATIC , "", WS_CHILD | WS_VISIBLE, - 10, RigRow, 80,20, hDlg, NULL, hInstance, NULL); - - // RIG->hCAT = CreateWindow(WC_STATIC , "", WS_CHILD | WS_VISIBLE, - // 90, RigRow, 40,20, hDlg, NULL, hInstance, NULL); - - RIG->hFREQ = CreateWindow(WC_STATIC , "", WS_CHILD | WS_VISIBLE, - 95, RigRow, 100,20, hDlg, NULL, hInstance, NULL); - - RIG->hMODE = CreateWindow(WC_STATIC , "", WS_CHILD | WS_VISIBLE, - 200, RigRow, 100,20, hDlg, NULL, hInstance, NULL); - - RIG->hSCAN = CreateWindow(WC_STATIC , "", WS_CHILD | WS_VISIBLE, - 300, RigRow, 20,20, hDlg, NULL, hInstance, NULL); - - RIG->hPTT = CreateWindow(WC_STATIC , "", WS_CHILD | WS_VISIBLE, - 320, RigRow, 20,20, hDlg, NULL, hInstance, NULL); - - RIG->hPORTS = CreateWindow(WC_STATIC , "", WS_CHILD | WS_VISIBLE, - 340, RigRow, 210, 20, hDlg, NULL, hInstance, NULL); - - RigRow += 20; - - //if (PORT->PortType == ICOM) - //{ - // sprintf(msg,"%02X", PORT->Rigs[i].RigAddr); - // SetWindowText(RIG->hCAT, msg); - //} - SetWindowText(RIG->hLabel, RIG->RigName); -#endif - - RIG->WEB_Label = _strdup(RIG->RigName); - // RIG->WEB_CAT; - RIG->WEB_FREQ = zalloc(80); - RIG->WEB_MODE = zalloc(80); - RIG->WEB_PORTS = zalloc(80); - strcpy(RIG->WEB_FREQ, "-----------"); - strcpy(RIG->WEB_MODE, "------"); - - RIG->WEB_PTT = ' '; - RIG->WEB_SCAN = ' '; - } - } - - for (p = 0; p < NumberofPorts; p++) - { - PORT = PORTInfo[p]; - - if (PORT->PortType == HAMLIB) - { - HAMLIBMasterRunning = 1; - ConnecttoHAMLIB(PORT); - } - else if (PORT->PortType == FLRIG) - { - FLRIGRunning = 1; - ConnecttoFLRIG(PORT); - } - else if (PORT->PortType == RTLUDP) - ConnecttoRTLUDP(PORT); - else if (PORT->HIDDevice) // This is RAWHID, Not CM108 - OpenHIDPort(PORT, PORT->IOBASE, PORT->SPEED); - else if (PORT->PTC == 0 && _stricmp(PORT->IOBASE, "CM108") != 0) - OpenRigCOMMPort(PORT, PORT->IOBASE, PORT->SPEED); - - if (PORT->PTTIOBASE[0]) // Using separate port for PTT? - { - if (PORT->PTTIOBASE[3] == '=') - PORT->hPTTDevice = OpenCOMPort(&PORT->PTTIOBASE[4], PORT->SPEED, FALSE, FALSE, FALSE, 0); - else - PORT->hPTTDevice = OpenCOMPort(&PORT->PTTIOBASE[3], PORT->SPEED, FALSE, FALSE, FALSE, 0); - } - else - PORT->hPTTDevice = PORT->hDevice; // Use same port for PTT - } - - for (p = 0; p < NumberofPorts; p++) - { - PORT = PORTInfo[p]; - - for (i=0; i < PORT->ConfiguredRigs; i++) - { - int j; - int k = 0; - int BitMask; - struct _EXTPORTDATA * PortEntry; - - RIG = &PORT->Rigs[i]; - - SetupScanInterLockGroups(RIG); - - // Get record for each port in Port Bitmap - - // The Scan "Request Permission to Change" code needs the Port Records in order - - // Those with active connect lock (eg SCS) first, then those with just a connect pending lock (eg WINMOR) - // then those with neither - - BitMask = RIG->BPQPort; - for (j = 0; j < 32; j++) - { - if (BitMask & 1) - { - PortEntry = (struct _EXTPORTDATA *)GetPortTableEntryFromPortNum(j); // BPQ32 port record for this port - if (PortEntry) - if (PortEntry->SCANCAPABILITIES == CONLOCK) - RIG->PortRecord[k++] = PortEntry; - } - BitMask >>= 1; - } - - BitMask = RIG->BPQPort; - for (j = 0; j < 32; j++) - { - if (BitMask & 1) - { - PortEntry = (struct _EXTPORTDATA *)GetPortTableEntryFromPortNum(j); // BPQ32 port record for this port - if (PortEntry) - if (PortEntry->SCANCAPABILITIES == SIMPLE) - RIG->PortRecord[k++] = PortEntry; - } - BitMask >>= 1; - } - - BitMask = RIG->BPQPort; - for (j = 0; j < 32; j++) - { - if (BitMask & 1) - { - PortEntry = (struct _EXTPORTDATA *)GetPortTableEntryFromPortNum(j); // BPQ32 port record for this port - if (PortEntry) - if (PortEntry->SCANCAPABILITIES == NONE) - RIG->PortRecord[k++] = PortEntry; - } - BitMask >>= 1; - } - - RIG->PORT = PORT; // For PTT - - if (RIG->NumberofBands) - CheckTimeBands(RIG); // Set initial timeband - -#ifdef WIN32 - if (RIG->PTTCATPort[0]) // Serial port RTS to CAT - _beginthread(PTTCATThread,0,RIG); -#endif - if (RIG->HAMLIBPORT) - { - // Open listening socket - - struct sockaddr_in local_sin; /* Local socket - internet style */ - struct sockaddr_in * psin; - SOCKET sock = 0; - u_long param=1; - - char szBuff[80]; - - psin=&local_sin; - psin->sin_family = AF_INET; - psin->sin_addr.s_addr = INADDR_ANY; - - sock = socket(AF_INET, SOCK_STREAM, 0); - - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (char *)¶m,4); - - psin->sin_port = htons(RIG->HAMLIBPORT); // Convert to network ordering - - if (bind( sock, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) - { - sprintf(szBuff, "bind(sock) failed port %d Error %d\n", port, WSAGetLastError()); - WritetoConsoleLocal(szBuff); - closesocket(sock); - } - else - { - if (listen(sock, 5) < 0) - { - sprintf(szBuff, "listen(sock) failed port %d Error %d\n", port, WSAGetLastError()); - WritetoConsoleLocal(szBuff); - } - else - { - ioctl(sock, FIONBIO, ¶m); - RIG->ListenSocket = sock; - _beginthread(HAMLIBSlaveThread, 0, RIG); - } - } - } - Rig_PTTEx(RIG, 0, NULL); // Send initial PTT Off (Mainly to set input mux on soundcard rigs) - } - } - - // MoveWindow(hDlg, Rect.left, Rect.top, Rect.right - Rect.left, Row + 100, TRUE); - - SetupPortRIGPointers(); - - RigWebPage = zalloc(10); - - WritetoConsole("\nRig Control Enabled\n"); - - return TRUE; -} - -DllExport BOOL APIENTRY Rig_Close() -{ - struct RIGPORTINFO * PORT; - struct TNCINFO * TNC; - int n, p; - - HAMLIBMasterRunning = 0; // Close HAMLIB thread(s) - HAMLIBSlaveRunning = 0; // Close HAMLIB thread(s) - FLRIGRunning = 0; // Close FLRIG thread(s) - - for (p = 0; p < NumberofPorts; p++) - { - PORT = PORTInfo[p]; - - if (PORT->PortType == NMEA) - { - // Send Remote OFF - - int i; - char REMOFF[80]; - - i = sprintf(REMOFF, "$PICOA,90,%02x,REMOTE,OFF*xx\r\n", PORT->Rigs[0].RigAddr); - AddNMEAChecksum(REMOFF); - - WriteCOMBlock(PORT->hDevice, REMOFF, i); - Sleep(200); - } - - if (PORT->PortType != HAMLIB && PORT->PortType != RTLUDP && PORT->PortType != FLRIG && strcmp(PORT->IOBASE, "RAWHID") != 0) - { - if (PORT->hPTTDevice != PORT->hDevice) - CloseCOMPort(PORT->hPTTDevice); - - CloseCOMPort(PORT->hDevice); - } - - PORT->hDevice = 0; - PORT->hPTTDevice = 0; - - // Free the RIG and Port Records - - for (n = 0; n < PORT->ConfiguredRigs; n++) - { - struct RIGINFO * RIG = &PORT->Rigs[n]; - struct HAMLIBSOCK * Entry = RIG->Sockets; - struct HAMLIBSOCK * Save; - - // if RIG has any HAMLIB slave connections, close them - - Entry = RIG->Sockets; - - while (Entry) - { - closesocket(Entry->Sock); - Save = Entry; - Entry = Entry->Next; - free(Save); - } - - RIG->Sockets = 0; - - if (RIG->TimeBands) - free (RIG->TimeBands[1]->Scanlist); - - if (RIG->PTTCATPort[0]) - { - Rig_PTTEx(RIG, FALSE, NULL); // Make sure PTT is down - EndPTTCATThread = TRUE; - } - } - - free (PORT); - PORTInfo[p] = NULL; - } - - NumberofPorts = 0; // For possible restart - - // And free the TNC config info - - for (p = 1; p < 33; p++) - { - TNC = TNCInfo[p]; - - if (TNC == NULL) - continue; - - TNC->RIG = NULL; - - // memset(TNC->WL2KInfoList, 0, sizeof(TNC->WL2KInfoList)); - - } - - return TRUE; -} - - - -BOOL Rig_Poll() -{ - int p, i, Len; - char RigWeb[16384]; - - struct RIGPORTINFO * PORT; - struct RIGINFO * RIG; - - for (p = 0; p < NumberofPorts; p++) - { - PORT = PORTInfo[p]; - - if (PORT->PortType == DUMMY) - { - DummyPoll(PORT); - return TRUE; - } - - if (PORT->hDevice == 0) - { - // Try to reopen every 15 secs - - PORT->ReopenDelay++; - - if (PORT->ReopenDelay > 150) - { - PORT->ReopenDelay = 0; - - if (PORT->PortType == HAMLIB) - ConnecttoHAMLIB(PORT); - else if (PORT->PortType == FLRIG) - ConnecttoFLRIG(PORT); - else if (PORT->PortType == RTLUDP) - ConnecttoRTLUDP(PORT); - else if (PORT->HIDDevice) - OpenHIDPort(PORT, PORT->IOBASE, PORT->SPEED); - else if (PORT->PTC == 0 - && _stricmp(PORT->IOBASE, "REMOTE") != 0 - && _stricmp(PORT->IOBASE, "CM108") != 0) - { - if (PORT->Closed == 0) - { - OpenRigCOMMPort(PORT, PORT->IOBASE, PORT->SPEED); - if (PORT->IOBASE && PORT->PTTIOBASE[0] == 0) // Using separate port for PTT? - PORT->hPTTDevice = PORT->hDevice; - } - } - } - } - - if (PORT == NULL || (PORT->hDevice == 0 && PORT->PTC == 0 && PORT->remoteSock == 0)) - continue; - - // Check PTT Timers - - for (i=0; i< PORT->ConfiguredRigs; i++) - { - RIG = &PORT->Rigs[i]; - - // Active PTT command - - if (RIG->PTTTimer) - { - RIG->PTTTimer--; - if (RIG->PTTTimer == 0) - Rig_PTTEx(RIG, FALSE, NULL); - } - - // repeated off timer - - if (RIG->repeatPTTOFFTimer) - { - RIG->repeatPTTOFFTimer--; - if (RIG->repeatPTTOFFTimer == 0) - { - Rig_PTTEx(RIG, FALSE, NULL); - RIG->repeatPTTOFFTimer = 0; // Don't repeat repeat! - } - } - } - - CheckRX(PORT); - - switch (PORT->PortType) - { - case ICOM: - - ICOMPoll(PORT); - break; - - case YAESU: - case FT100: - case FT990: - case FT1000: - - YaesuPoll(PORT); - break; - - case KENWOOD: - case FT2000: - case FT991A: - case FLEX: - case NMEA: - - KenwoodPoll(PORT); - break; - - case HAMLIB: - HAMLIBPoll(PORT); - break; - - case RTLUDP: - RTLUDPPoll(PORT); - break; - - case FLRIG: - FLRIGPoll(PORT); - break; - - - } - } - - // Build page for Web Display - - Len = BuildRigCtlPage(RigWeb); - - if (strcmp(RigWebPage, RigWeb) == 0) - return TRUE; // No change - - free(RigWebPage); - - RigWebPage = _strdup(RigWeb); - - SendRigWebPage(); - - return TRUE; -} - - -BOOL RigCloseConnection(struct RIGPORTINFO * PORT) -{ - // disable event notification and wait for thread - // to halt - - CloseCOMPort(PORT->hDevice); - PORT->hDevice = 0; - return TRUE; - -} // end of CloseConnection() - -#ifndef WIN32 -#define ONESTOPBIT 0 -#define ONE5STOPBITS 1 -#define TWOSTOPBITS 2 -#endif - -int OpenRigCOMMPort(struct RIGPORTINFO * PORT, VOID * Port, int Speed) -{ - if (PORT->remoteSock) // Using WINMORCONTROL - return TRUE; - - if (PORT->PortType == FT2000 || PORT->PortType == FT991A || strcmp(PORT->Rigs[0].RigName, "FT847") == 0) // FT2000 and similar seem to need two stop bits - PORT->hDevice = OpenCOMPort((VOID *)Port, Speed, FALSE, FALSE, PORT->Alerted, TWOSTOPBITS); - else if (PORT->PortType == NMEA) - PORT->hDevice = OpenCOMPort((VOID *)Port, Speed, FALSE, FALSE, PORT->Alerted, ONESTOPBIT); - else - PORT->hDevice = OpenCOMPort((VOID *)Port, Speed, FALSE, FALSE, PORT->Alerted, TWOSTOPBITS); - - if (PORT->hDevice == 0) - { - PORT->Alerted = TRUE; - return FALSE; - } - - PORT->Alerted = FALSE; - - if (PORT->PortType == PTT || (PORT->Rigs[0].PTTMode & PTTRTS)) - COMClearRTS(PORT->hDevice); - else - COMSetRTS(PORT->hDevice); - - if (PORT->PortType == PTT || (PORT->Rigs[0].PTTMode & PTTDTR)) - COMClearDTR(PORT->hDevice); - else - COMSetDTR(PORT->hDevice); - - if (strcmp(PORT->Rigs[0].RigName, "FT847") == 0) - { - // Looks like FT847 Needa a "Cat On" Command - - UCHAR CATON[6] = {0,0,0,0,0}; - - WriteCOMBlock(PORT->hDevice, CATON, 5); - } - - if (PORT->PortType == NMEA) - { - // Looks like NMEA Needs Remote ON - - int i; - char REMON[80]; - - i = sprintf(REMON, "$PICOA,90,%02x,REMOTE,ON*xx\r\n", PORT->Rigs[0].RigAddr); - AddNMEAChecksum(REMON); - - WriteCOMBlock(PORT->hDevice, REMON, i); - } - - - return TRUE; -} - -void CheckRX(struct RIGPORTINFO * PORT) -{ - int Length; - char NMEAMsg[100]; - unsigned char * ptr; - int len; - - if (PORT->PortType == FLRIG) - { - // Data received in thread - - return; - } - - if (PORT->PortType == HAMLIB) - { - // Data received in thread (do we need thread?? - - Length = PORT->RXLen; - PORT->RXLen = 0; - } - - else if (PORT->PortType == RTLUDP) - { - CheckAndProcessRTLUDP(PORT); - Length = 0; - PORT->RXLen = 0; - return; - } - - else if (PORT->HIDDevice) - Length = HID_Read_Block(PORT); - else if (PORT->PTC) - Length = GetPTCRadioCommand(PORT->PTC, &PORT->RXBuffer[PORT->RXLen]); - else if (PORT->remoteSock) - { - struct sockaddr_in rxaddr; - int addrlen = sizeof(struct sockaddr_in); - - Length = recvfrom(PORT->remoteSock, PORT->RXBuffer, 500, 0, (struct sockaddr *)&rxaddr, &addrlen); - if (Length == -1) - Length = 0; - } - else - { - if (PORT->hDevice == 0) - return; - - // only try to read number of bytes in queue - - if (PORT->RXLen == 500) - PORT->RXLen = 0; - - Length = 500 - (DWORD)PORT->RXLen; - - Length = ReadCOMBlock(PORT->hDevice, &PORT->RXBuffer[PORT->RXLen], Length); - } - - if (Length == 0) - return; // Nothing doing - - PORT->RXLen += Length; - - Length = PORT->RXLen; - - switch (PORT->PortType) - { - case ICOM: - - if (Length < 6) // Minimum Frame Sise - return; - - if (PORT->RXBuffer[Length-1] != 0xfd) - return; - - ProcessICOMFrame(PORT, PORT->RXBuffer, Length); // Could have multiple packets in buffer - - PORT->RXLen = 0; // Ready for next frame - return; - - case YAESU: - - // Possible responses are a single byte ACK/NAK or a 5 byte info frame - - if (Length == 1 && PORT->CmdSent > 0) - { - ProcessYaesuCmdAck(PORT); - return; - } - - if (Length < 5) // Frame Sise - return; - - if (Length > 5) // Frame Sise - { - PORT->RXLen = 0; // Corruption - reset and wait for retry - return; - } - - ProcessYaesuFrame(PORT); - - PORT->RXLen = 0; // Ready for next frame - return; - - case FT100: - - // Only response should be a 16 byte info frame - - if (Length < 32) // Frame Sise why??????? - return; - - if (Length > 32) // Frame Sise - { - PORT->RXLen = 0; // Corruption - reset and wait for retry - return; - } - - ProcessFT100Frame(PORT); - - PORT->RXLen = 0; // Ready for next frame - return; - - case FT990: - - // Only response should be a 32 byte info frame - - if (Length < 32) // Frame Sise - return; - - if (Length > 32) // Frame Sise - { - PORT->RXLen = 0; // Corruption - reset and wait for retry - return; - } - - ProcessFT990Frame(PORT); - PORT->RXLen = 0; // Ready for next frame - return; - - - case FT1000: - - // Only response should be a 16 byte info frame - - ptr = PORT->RXBuffer; - - if (Length < 16) // Frame Sise - return; - - if (Length > 16) // Frame Sise - { - PORT->RXLen = 0; // Corruption - reset and wait for retry - return; - } - - ProcessFT1000Frame(PORT); - - PORT->RXLen = 0; // Ready for next frame - return; - - case KENWOOD: - case FT2000: - case FT991A: - case FLEX: - - if (Length < 2) // Minimum Frame Sise - return; - - if (Length > 50) // Garbage - { - PORT->RXLen = 0; // Ready for next frame - return; - } - - if (PORT->RXBuffer[Length-1] != ';') - return; - - ProcessKenwoodFrame(PORT, Length); - - PORT->RXLen = 0; // Ready for next frame - return; - - case NMEA: - - ptr = memchr(PORT->RXBuffer, 0x0a, Length); - - while (ptr != NULL) - { - ptr++; // include lf - len = (int)(ptr - &PORT->RXBuffer[0]); - - memcpy(NMEAMsg, PORT->RXBuffer, len); - - NMEAMsg[len] = 0; - -// if (Check0183CheckSum(NMEAMsg, len)) - ProcessNMEA(PORT, NMEAMsg, len); - - Length -= len; // bytes left - - if (Length > 0) - { - memmove(PORT->RXBuffer, ptr, Length); - ptr = memchr(PORT->RXBuffer, 0x0a, Length); - } - else - ptr=0; - } - - PORT->RXLen = Length; - return; - - case HAMLIB: - - ProcessHAMLIBFrame(PORT, Length); - PORT->RXLen = 0; - return; - } -} - -VOID ProcessICOMFrame(struct RIGPORTINFO * PORT, UCHAR * rxbuffer, int Len) -{ - UCHAR * FendPtr; - int NewLen; - - // Split into Packets. By far the most likely is a single frame - // so treat as special case - - FendPtr = memchr(rxbuffer, 0xfd, Len); - - if (FendPtr == &rxbuffer[Len-1]) - { - ProcessFrame(PORT, rxbuffer, Len); - return; - } - - // Process the first Packet in the buffer - - NewLen = (int)(FendPtr - rxbuffer + 1); - - ProcessFrame(PORT, rxbuffer, NewLen); - - // Loop Back - - ProcessICOMFrame(PORT, FendPtr+1, Len - NewLen); - return; -} - - -BOOL RigWriteCommBlock(struct RIGPORTINFO * PORT) -{ - // if using a PTC radio interface send to the SCSPactor Driver, else send to COM port - - int ret; - - if (PORT->HIDDevice) - HID_Write_Block(PORT); - else - if (PORT->PTC) - SendPTCRadioCommand(PORT->PTC, PORT->TXBuffer, PORT->TXLen); - else if (PORT->remoteSock) - ret = sendto(PORT->remoteSock, PORT->TXBuffer, PORT->TXLen, 0, &PORT->remoteDest, sizeof(struct sockaddr)); - else - { - BOOL fWriteStat; - DWORD BytesWritten; - -#ifndef WIN32 - BytesWritten = write(PORT->hDevice, PORT->TXBuffer, PORT->TXLen); -#else - fWriteStat = WriteFile(PORT->hDevice, PORT->TXBuffer, PORT->TXLen, &BytesWritten, NULL ); -#endif - if (PORT->TXLen != BytesWritten) - { - struct RIGINFO * RIG = &PORT->Rigs[PORT->CurrentRig]; // Only one on Yaseu - - if (RIG->RIGOK) - { - SetWindowText(RIG->hFREQ, "Port Closed"); - SetWindowText(RIG->hMODE, "----------"); - strcpy(RIG->WEB_FREQ, "-----------");; - strcpy(RIG->WEB_MODE, "------"); - } - - RIG->RIGOK = FALSE; - - if (PORT->hDevice) - CloseCOMPort(PORT->hDevice); - - OpenRigCOMMPort(PORT, PORT->IOBASE, PORT->SPEED); - - if (PORT->IOBASE && PORT->PTTIOBASE[0] == 0) // Using separate port for PTT? - PORT->hPTTDevice = PORT->hDevice; - - if (PORT->hDevice) - { - // Try Again - -#ifndef WIN32 - BytesWritten = write(PORT->hDevice, PORT->TXBuffer, PORT->TXLen); -#else - fWriteStat = WriteFile(PORT->hDevice, PORT->TXBuffer, PORT->TXLen, &BytesWritten, NULL ); -#endif - } - } - } - - ret = GetLastError(); - - PORT->Timeout = 100; // 2 secs - return TRUE; -} - -VOID ReleasePermission(struct RIGINFO *RIG) -{ - int i = 0; - struct _EXTPORTDATA * PortRecord; - - while (RIG->PortRecord[i]) - { - PortRecord = RIG->PortRecord[i]; - PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 3); // Release Perrmission - i++; - } -} - -int GetPermissionToChange(struct RIGPORTINFO * PORT, struct RIGINFO *RIG) -{ - struct ScanEntry ** ptr; - struct _EXTPORTDATA * PortRecord; - int i = 0; - - // Get Permission to change - - if (RIG->RIG_DEBUG) - Debugprintf("GetPermissionToChange - WaitingForPermission = %d", RIG->WaitingForPermission); - - // See if any two stage (CONLOCK) ports - - if (RIG->PortRecord[0] && RIG->PortRecord[0]->SCANCAPABILITIES != CONLOCK) - goto CheckOtherPorts; - - - if (RIG->WaitingForPermission) - { - // This code should only be called if port needs two stage - // eg Request then confirm. only SCS Pactor at the moment. - - // TNC has been asked for permission, and we are waiting respoonse - // Only SCS pactor returns WaitingForPrmission, so check shouldn't be called on others - - RIG->OKtoChange = (int)(intptr_t)RIG->PortRecord[0]->PORT_EXT_ADDR(6, RIG->PortRecord[0]->PORTCONTROL.PORTNUMBER, 2); // Get Ok Flag - - if (RIG->OKtoChange == 1) - { - if (RIG->RIG_DEBUG) - Debugprintf("Check Permission returned OK to change"); - - i = 1; - goto CheckOtherPorts; - } - - if (RIG->OKtoChange == -1) - { - // Permission Refused. Wait Scan Interval and try again - - if (RIG->RIG_DEBUG) - Debugprintf("Scan Debug %s Refused permission - waiting ScanInterval %d", - RIG->PortRecord[0]->PORT_DLL_NAME, PORT->FreqPtr->Dwell ); - - RIG->WaitingForPermission = FALSE; - SetWindowText(RIG->hSCAN, "-"); - RIG->WEB_SCAN = '='; - - RIG->ScanCounter = PORT->FreqPtr->Dwell; - - if (RIG->ScanCounter == 0) // ? After manual change - RIG->ScanCounter = 50; - - return FALSE; - } - - if (RIG->RIG_DEBUG) - Debugprintf("Scan Debug %s Still Waiting", RIG->PortRecord[0]->PORT_DLL_NAME); - - - return FALSE; // Haven't got reply yet. Will re-enter next tick - } - else - { - // not waiting for permission, so must be first call of a cycle - - if (RIG->PortRecord[0] && RIG->PortRecord[0]->PORT_EXT_ADDR) - RIG->WaitingForPermission = (int)(intptr_t)RIG->PortRecord[0]->PORT_EXT_ADDR(6, RIG->PortRecord[0]->PORTCONTROL.PORTNUMBER, 1); // Request Perrmission - - // If it returns zero there is no need to wait. - // Normally SCS Returns True for first call, but returns 0 if Link not running - - if (RIG->WaitingForPermission) - return FALSE; // Wait till driver has status - - if (RIG->RIG_DEBUG) - Debugprintf("First call to %s returned OK to change", RIG->PortRecord[0]->PORT_DLL_NAME); - - i = 1; - } - -CheckOtherPorts: - - // Either first TNC gave permission or there are no SCS like ports. - // Ask any others (these are assumed to give immediate yes/no - - while (RIG->PortRecord[i]) - { - PortRecord = RIG->PortRecord[i]; - - if (PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 1)) - { - // 1 means can't change - release all - - if (RIG->RIG_DEBUG && PORT->FreqPtr) - Debugprintf("Scan Debug %s Refused permission - waiting ScanInterval %d", - PortRecord->PORT_DLL_NAME, PORT->FreqPtr->Dwell); - - RIG->WaitingForPermission = FALSE; - MySetWindowText(RIG->hSCAN, "-"); - RIG->WEB_SCAN = '-'; - - if (PORT->FreqPtr) - RIG->ScanCounter = PORT->FreqPtr->Dwell; - - if (RIG->ScanCounter == 0) // ? After manual change - RIG->ScanCounter = 50; - - ReleasePermission(RIG); - return FALSE; - } - else - if (RIG->RIG_DEBUG) - Debugprintf("Scan Debug %s gave permission", PortRecord->PORT_DLL_NAME); - - i++; - } - - - RIG->WaitingForPermission = FALSE; - - // Update pointer to next frequency - - RIG->FreqPtr++; - - ptr = RIG->FreqPtr; - - if (ptr == NULL) - { - Debugprintf("Scan Debug - No freqs - quitting"); - return FALSE; // No Freqs - } - - if (ptr[0] == (struct ScanEntry *)0) // End of list - reset to start - { - ptr = CheckTimeBands(RIG); - - if (ptr[0] == (struct ScanEntry *)0) - { - // Empty Timeband - delay 60 secs (we need to check for timeband change sometimes) - - RIG->ScanCounter = 600; - ReleasePermission(RIG); - return FALSE; - } - } - - PORT->FreqPtr = ptr[0]; // Save Scan Command Block - - RIG->ScanCounter = PORT->FreqPtr->Dwell; - - if (RIG->ScanCounter == 0) // ? After manual change - RIG->ScanCounter = 150; - - MySetWindowText(RIG->hSCAN, "S"); - RIG->WEB_SCAN = 'S'; - - // Do Bandwidth and antenna switches (if needed) - - DoBandwidthandAntenna(RIG, ptr[0]); - - return TRUE; -} - -VOID DoBandwidthandAntenna(struct RIGINFO *RIG, struct ScanEntry * ptr) -{ - // If Bandwidth Change needed, do it - - int i; - struct _EXTPORTDATA * PortRecord; - - if (ptr->Bandwidth || ptr->RPacketMode || ptr->HFPacketMode - || ptr->PMaxLevel || ptr->ARDOPMode[0] || ptr->VARAMode) - { - i = 0; - - while (RIG->PortRecord[i]) - { - PortRecord = RIG->PortRecord[i]; - - RIG->CurrentBandWidth = ptr->Bandwidth; - - PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, ptr); - -/* if (ptr->Bandwidth == 'R') // Robust Packet - PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 6); // Set Robust Packet - else - - if (ptr->Bandwidth == 'W') - PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 4); // Set Wide Mode - else - PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 5); // Set Narrow Mode -*/ - i++; - } - } - - // If Antenna Change needed, do it - - // 5 and 6 are used for CI-V switching so ignore here - - if (ptr->Antenna && ptr->Antenna < '5') - { - SwitchAntenna(RIG, ptr->Antenna); - } - - return; -} - -VOID ICOMPoll(struct RIGPORTINFO * PORT) -{ - UCHAR * Poll = PORT->TXBuffer; - int i; - - struct RIGINFO * RIG; - - for (i=0; i< PORT->ConfiguredRigs; i++) - { - RIG = &PORT->Rigs[i]; - - if (RIG->ScanStopped == 0) - if (RIG->ScanCounter) - RIG->ScanCounter--; - } - - if (PORT->Timeout) - { - PORT->Timeout--; - - if (PORT->Timeout) // Still waiting - return; - - PORT->Retries--; - - if(PORT->Retries) - { - RigWriteCommBlock(PORT); // Retransmit Block - return; - } - - RIG = &PORT->Rigs[PORT->CurrentRig]; - - - SetWindowText(RIG->hFREQ, "-----------"); - strcpy(RIG->WEB_FREQ, "-----------"); - SetWindowText(RIG->hMODE, "------"); - strcpy(RIG->WEB_MODE, "------"); - -// SetWindowText(RIG->hFREQ, "145.810000"); -// SetWindowText(RIG->hMODE, "RTTY/1"); - - PORT->Rigs[PORT->CurrentRig].RIGOK = FALSE; - - return; - - } - - // Send Data if avail, else send poll - - PORT->CurrentRig++; - - if (PORT->CurrentRig >= PORT->ConfiguredRigs) - PORT->CurrentRig = 0; - - RIG = &PORT->Rigs[PORT->CurrentRig]; - -/* - RIG->DebugDelay ++; - - if (RIG->DebugDelay > 600) - { - RIG->DebugDelay = 0; - Debugprintf("Scan Debug %d %d %d %d %d %d", PORT->CurrentRig, - RIG->NumberofBands, RIG->RIGOK, RIG->ScanStopped, RIG->ScanCounter, - RIG->WaitingForPermission); - } -*/ - if (RIG->NumberofBands && RIG->RIGOK && (RIG->ScanStopped == 0)) - { - if (RIG->ScanCounter <= 0) - { - // Send Next Freq - - if (GetPermissionToChange(PORT, RIG)) - { - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq/1000000.0); - - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd1, PORT->FreqPtr->Cmd1Len); - - if (PORT->FreqPtr->Freq > 0.0) - { - _gcvt((PORT->FreqPtr->Freq + RIG->rxOffset) / 1000000.0, 9, RIG->Valchar); // For MH - strcpy(RIG->WEB_FREQ, RIG->Valchar); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - } - - - PORT->TXLen = PORT->FreqPtr->Cmd1Len; - RigWriteCommBlock(PORT); - PORT->Retries = 2; - PORT->AutoPoll = TRUE; - - return; - } - } - } - - if (RIG->RIGOK && RIG->BPQtoRADIO_Q) - { - struct MSGWITHOUTLEN * buffptr; - - buffptr = Q_REM(&RIG->BPQtoRADIO_Q); - - // Copy the ScanEntry struct from the Buffer to the PORT Scanentry - - memcpy(&PORT->ScanEntry, buffptr->Data, sizeof(struct ScanEntry)); - - PORT->FreqPtr = &PORT->ScanEntry; // Block we are currently sending. - - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Manual Change Freq to %9.4f", PORT->FreqPtr->Freq/1000000.0); - - - memcpy(Poll, PORT->FreqPtr->Cmd1, PORT->FreqPtr->Cmd1Len); - - DoBandwidthandAntenna(RIG, &PORT->ScanEntry); - - if (PORT->FreqPtr->Freq > 0.0) - { - _gcvt((PORT->FreqPtr->Freq + RIG->rxOffset) / 1000000.0, 9, RIG->Valchar); // For MH - strcpy(RIG->WEB_FREQ, RIG->Valchar); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - } - - PORT->TXLen = PORT->FreqPtr->Cmd1Len; // First send the set Freq - RigWriteCommBlock(PORT); - PORT->Retries = 2; - - ReleaseBuffer(buffptr); - - PORT->AutoPoll = FALSE; - - return; - } - - - if (RIG->RIGOK && RIG->ScanStopped == 0 && RIG->NumberofBands && - RIG->ScanCounter && RIG->ScanCounter < 30) // no point in reading freq if we are about to change - return; - - if (RIG->PollCounter) - { - RIG->PollCounter--; - if (RIG->PollCounter) - return; - } - - // Need to make sure we don't poll multiple rigs on port at the same time - - if (RIG->RIGOK) - { - PORT->Retries = 2; - RIG->PollCounter = 10 / PORT->ConfiguredRigs; // Once Per Sec - } - else - { - PORT->Retries = 1; - RIG->PollCounter = 100 / PORT->ConfiguredRigs; // Slow Poll if down - } - - RIG->PollCounter += PORT->CurrentRig * 3; - - PORT->AutoPoll = TRUE; - - // Read Frequency - - Poll[0] = 0xFE; - Poll[1] = 0xFE; - Poll[2] = RIG->RigAddr; - Poll[3] = 0xE0; - Poll[4] = 0x3; // Get frequency command - Poll[5] = 0xFD; - - PORT->TXLen = 6; - - RigWriteCommBlock(PORT); - - PORT->Retries = 1; - PORT->Timeout = 10; - - return; -} - - -VOID ProcessFrame(struct RIGPORTINFO * PORT, UCHAR * Msg, int framelen) -{ - UCHAR * Poll = PORT->TXBuffer; - struct RIGINFO * RIG; - int i; - int cmdSent = PORT->TXBuffer[4]; - - if (Msg[0] != 0xfe || Msg[1] != 0xfe) - - // Duff Packet - return - - return; - - if (Msg[2] != 0xe0 && Msg[2] != 0) - { - // Echo - Proves a CI-V interface is attached - - if (PORT->PORTOK == FALSE) - { - // Just come up - PORT->PORTOK = TRUE; - Debugprintf("Cat Port OK"); - } - return; - } - - for (i=0; i< PORT->ConfiguredRigs; i++) - { - RIG = &PORT->Rigs[i]; - if (Msg[3] == RIG->RigAddr) - goto ok; - } - - return; - -ok: - - if (Msg[4] == 0xFB) - { - // Accept - - if (cmdSent == 0x1C && PORT->TXBuffer[5] == 1) // Tune - { - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Tune OK"); - - PORT->Timeout = 0; - return; - } - - if (cmdSent == 0x14 && PORT->TXBuffer[5] == 0x0A) // Power - { - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Set Power OK"); - - PORT->Timeout = 0; - return; - } - - // if it was the set freq, send the set mode - - if (RIG->ICF8101) - { - if (cmdSent == 0x1A && PORT->TXBuffer[5] == 0x35) - { - if (PORT->FreqPtr->Cmd2) - { - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd2, PORT->FreqPtr->Cmd2Len); - PORT->TXLen = PORT->FreqPtr->Cmd2Len; - RigWriteCommBlock(PORT); - PORT->Retries = 2; - } - else - { - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Frequency Set OK"); - - PORT->Timeout = 0; - } - return; - } - - if (cmdSent == 0x1a && PORT->TXBuffer[5] == 0x36) - { - // Set Mode Response - if scanning read freq, else return OK to user - - if (RIG->ScanStopped == 0) - { - ReleasePermission(RIG); // Release Perrmission - - Poll[0] = 0xFE; - Poll[1] = 0xFE; - Poll[2] = RIG->RigAddr; - Poll[3] = 0xE0; - Poll[4] = 0x3; // Get frequency command - Poll[5] = 0xFD; - - PORT->TXLen = 6; - RigWriteCommBlock(PORT); - PORT->Retries = 2; - return; - } - else - { - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Frequency and Mode Set OK"); - - RIG->PollCounter = 30 / RIG->PORT->ConfiguredRigs; // Dont read freq for 3 secs - } - } - - PORT->Timeout = 0; - return; - } - - if (cmdSent == 5 || cmdSent == 7) // Freq or VFO - { - if (PORT->FreqPtr && PORT->FreqPtr->Cmd2) - { - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd2, PORT->FreqPtr->Cmd2Len); - PORT->TXLen = PORT->FreqPtr->Cmd2Len; - RigWriteCommBlock(PORT); - PORT->Retries = 2; - } - else - { - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Frequency Set OK"); - - PORT->Timeout = 0; - } - return; - } - - if (cmdSent == 6) // Set Mode - { - if (PORT->FreqPtr && PORT->FreqPtr->Cmd3) - { - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd3, PORT->FreqPtr->Cmd3Len); - PORT->TXLen = PORT->FreqPtr->Cmd3Len; - RigWriteCommBlock(PORT); - PORT->Retries = 2; - return; - } - - goto SetFinished; - } - - if (cmdSent == 0x08) - { - // Memory Chan - - cmdSent = 0; // So we only do it once - - goto SetFinished; - } - - if (cmdSent == 0x12) - goto SetFinished; // Antenna always sent last - - - if (cmdSent == 0x0f || cmdSent == 0x01a) // Set DUP or Data - { - // These are send from cmd3. There may be a cmd4 - // for antenna switching - - if (PORT->FreqPtr && PORT->FreqPtr->Cmd4) - { - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd4, PORT->FreqPtr->Cmd4Len); - PORT->TXLen = PORT->FreqPtr->Cmd4Len; - RigWriteCommBlock(PORT); - PORT->Retries = 2; - return; - } - -SetFinished: - - // Set Mode Response - if scanning read freq, else return OK to user - - if (RIG->ScanStopped == 0) - { - ReleasePermission(RIG); // Release Perrmission - - Poll[0] = 0xFE; - Poll[1] = 0xFE; - Poll[2] = RIG->RigAddr; - Poll[3] = 0xE0; - Poll[4] = 0x3; // Get frequency command - Poll[5] = 0xFD; - - PORT->TXLen = 6; - RigWriteCommBlock(PORT); - PORT->Retries = 2; - return; - } - - else - { - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Frequency and Mode Set OK"); - - RIG->PollCounter = 30 / RIG->PORT->ConfiguredRigs; // Dont read freq for 3 secs - } - } - - PORT->Timeout = 0; - return; - } - - if (Msg[4] == 0xFA) - { - // Reject - - PORT->Timeout = 0; - - if (!PORT->AutoPoll) - { - if (cmdSent == 5) - SendResponse(RIG->Session, "Sorry - Set Frequency Command Rejected"); - else - if (cmdSent == 6) - SendResponse(RIG->Session, "Sorry - Set Mode Command Rejected"); - else - if (cmdSent == 0x0f) - SendResponse(RIG->Session, "Sorry - Set Shift Command Rejected"); - else - if (cmdSent == 0x12) - SendResponse(RIG->Session, "Sorry - Set Antenna Command Rejected"); - else - if (cmdSent == 0x1C && PORT->TXBuffer[5] == 1) // Tune - SendResponse(RIG->Session, "Sorry - Tune Command Rejected"); - else - if (cmdSent == 0x14 && PORT->TXBuffer[5] == 0x0a) // Power - SendResponse(RIG->Session, "Sorry - Power Command Rejected"); - else - SendResponse(RIG->Session, "Sorry - Command Rejected"); - - } - return; - } - - if (Msg[4] == PORT->TXBuffer[4]) - { - // Response to our command - - // Any valid frame is an ACK - - RIG->RIGOK = TRUE; - PORT->Timeout = 0; - - if (!PORT->AutoPoll) - { - // Manual response probably to CMD Query. Return response - - char reply[256] = "CMD Response "; - char * p1 = &reply[13]; - UCHAR * p2 = &Msg[4]; - int n = framelen - 4; - - while (n > 0) - { - sprintf(p1, "%02X ", *(p2)); - p1 += 3; - p2++; - n--; - } - - SendResponse(RIG->Session, reply); - - } - - } - else - return; // What does this mean?? - - - if (PORT->PORTOK == FALSE) - { - // Just come up -// char Status[80]; - - PORT->PORTOK = TRUE; -// sprintf(Status,"COM%d PORT link OK", PORT->IOBASE); -// SetWindowText(PORT->hStatus, Status); - } - - if (Msg[4] == 3) - { - // Rig Frequency - int n, j, decdigit; - long long Freq = 0; - int start = 9; - long long MHz, Hz; - char CharMHz[16] = ""; - char CharHz[16] = ""; - - int i; - - - if (RIG->IC735) - start = 8; // shorted msg - - for (j = start; j > 4; j--) - { - n = Msg[j]; - decdigit = (n >> 4); - decdigit *= 10; - decdigit += n & 0xf; - Freq = (Freq *100 ) + decdigit; - } - - Freq += RIG->rxOffset; - - RIG->RigFreq = Freq / 1000000.0; - - // If we convert to float to display we get rounding errors, so convert to MHz and Hz to display - - MHz = Freq / 1000000; - - Hz = Freq - MHz * 1000000; - - sprintf(CharMHz, "%lld", MHz); - sprintf(CharHz, "%06lld", Hz); - - for (i = 5; i > 2; i--) - { - if (CharHz[i] == '0') - CharHz[i] = 0; - else - break; - } - - sprintf(RIG->WEB_FREQ,"%lld.%s", MHz, CharHz); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - strcpy(RIG->Valchar, RIG->WEB_FREQ); - - - // Now get Mode - - Poll[0] = 0xFE; - Poll[1] = 0xFE; - Poll[2] = RIG->RigAddr; - Poll[3] = 0xE0; - - if (RIG->ICF8101) - { - Poll[4] = 0x1A; // Get Mode - Poll[5] = 0x34; - Poll[6] = 0xFD; - PORT->TXLen = 7; - } - else - { - Poll[4] = 0x4; // Get Mode - Poll[5] = 0xFD; - - PORT->TXLen = 6; - } - - RigWriteCommBlock(PORT); - PORT->Retries = 2; - return; - } - - if (RIG->ICF8101) - { - if (cmdSent == 0x1A && PORT->TXBuffer[5] == 0x34) - { - // Get Mode - - unsigned int Mode; - - Mode = (Msg[7] >> 4); - Mode *= 10; - Mode += Msg[7] & 0xf; - - if (Mode > 24) Mode = 24; - - sprintf(RIG->WEB_MODE,"%s", Modes[Mode]); - - strcpy(RIG->ModeString, Modes[Mode]); - SetWindowText(RIG->hMODE, RIG->WEB_MODE); - - return; - } - } - - - if (Msg[4] == 4) - { - // Mode - - unsigned int Mode; - - Mode = (Msg[5] >> 4); - Mode *= 10; - Mode += Msg[5] & 0xf; - - if (Mode > 24) Mode = 24; - - if (RIG->IC735) - sprintf(RIG->WEB_MODE,"%s", Modes[Mode]); - else - sprintf(RIG->WEB_MODE,"%s/%d", Modes[Mode], Msg[6]); - - strcpy(RIG->ModeString, Modes[Mode]); - SetWindowText(RIG->hMODE, RIG->WEB_MODE); - } -} - -int SendResponse(int Session, char * Msg) -{ - PDATAMESSAGE Buffer; - BPQVECSTRUC * VEC; - TRANSPORTENTRY * L4 = L4TABLE; - - if (Session == -1) - return 0; - - Buffer = GetBuff(); - - L4 += Session; - - Buffer->PID = 0xf0; - Buffer->LENGTH = MSGHDDRLEN + 1; // Includes PID - Buffer->LENGTH += sprintf(Buffer->L2DATA, "%s\r", Msg); - - VEC = L4->L4TARGET.HOST; - - C_Q_ADD(&L4->L4TX_Q, (UINT *)Buffer); - -#ifndef LINBPQ - - if (VEC) - PostMessage(VEC->HOSTHANDLE, BPQMsg, VEC->HOSTSTREAM, 2); -#endif - return 0; -} - -VOID ProcessFT100Frame(struct RIGPORTINFO * PORT) -{ - // Only one we should see is a Status Message - - UCHAR * Poll = PORT->TXBuffer; - UCHAR * Msg = PORT->RXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Yaseu - int Freq; - double FreqF; - unsigned int Mode; - - RIG->RIGOK = TRUE; - PORT->Timeout = 0; - - // Bytes 0 is Band - // 1 - 4 is Freq in binary in units of 1.25 HZ (!) - // Byte 5 is Mode - - Freq = (Msg[1] << 24) + (Msg[2] << 16) + (Msg[3] << 8) + Msg[4]; - - FreqF = (Freq * 1.25) / 1000000; - - if (PORT->YaesuVariant == FT1000MP) - FreqF = FreqF / 2; // No idea why! - - RIG->RigFreq = FreqF; - - _gcvt(FreqF, 9, RIG->Valchar); - - sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - - if (PORT->PortType == FT100) - { - Mode = Msg[5] & 15; - if (Mode > 8) Mode = 8; - sprintf(RIG->WEB_MODE,"%s", FT100Modes[Mode]); - } - else // FT1000 - { - Mode = Msg[7] & 7; - sprintf(RIG->WEB_MODE,"%s", FTRXModes[Mode]); - } - - strcpy(RIG->ModeString, RIG->WEB_MODE); - SetWindowText(RIG->hMODE, RIG->WEB_MODE); - - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Mode and Frequency Set OK"); - else - if (PORT->TXLen > 5) // Poll is 5 Change is more - ReleasePermission(RIG); // Release Perrmission to change -} - - - -VOID ProcessFT990Frame(struct RIGPORTINFO * PORT) -{ - // Only one we should see is a Status Message - - UCHAR * Poll = PORT->TXBuffer; - UCHAR * Msg = PORT->RXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Yaseu - int Freq; - double FreqF; - unsigned int Mode; - - RIG->RIGOK = TRUE; - PORT->Timeout = 0; - - // Bytes 0 is Band - // 1 - 4 is Freq in units of 10Hz (I think!) - // Byte 5 is Mode - - Freq = (Msg[1] << 16) + (Msg[2] << 8) + Msg[3]; - - FreqF = (Freq * 10.0) / 1000000; - - RIG->RigFreq = FreqF; - - _gcvt(FreqF, 9, RIG->Valchar); - - sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - - Mode = Msg[7] & 7; - sprintf(RIG->WEB_MODE,"%s", FTRXModes[Mode]); - - strcpy(RIG->ModeString, RIG->WEB_MODE); - SetWindowText(RIG->hMODE, RIG->WEB_MODE); - - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Mode and Frequency Set OK"); - else - if (PORT->TXLen > 5) // Poll is 5 change is more - ReleasePermission(RIG); // Release Perrmission to change -} - -VOID ProcessFT1000Frame(struct RIGPORTINFO * PORT) -{ - // Only one we should see is a Status Message - - UCHAR * Poll = PORT->TXBuffer; - UCHAR * Msg = PORT->RXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Yaseu - int Freq; - double FreqF; - unsigned int Mode; - - RIG->RIGOK = TRUE; - PORT->Timeout = 0; - - // I think the FT1000/1000D is same as 990 - // FT1000MP is similar to FT100, but steps on .625 Hz (despite manual) - // Bytes 0 is Band - // 1 - 4 is Freq in binary in units of 1.25 HZ (!) - // Byte 5 is Mode - - if (PORT->YaesuVariant == FT1000MP) - { - Freq = (Msg[1] << 24) + (Msg[2] << 16) + (Msg[3] << 8) + Msg[4]; - FreqF = (Freq * 1.25) / 1000000; - FreqF = FreqF / 2; // No idea why! - } - else - { - Freq = (Msg[1] << 16) + (Msg[2] << 8) + Msg[3]; - FreqF = (Freq * 10.0) / 1000000; - } - - RIG->RigFreq = FreqF; - - _gcvt(FreqF, 9, RIG->Valchar); - - sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - - if (PORT->PortType == FT100) - { - Mode = Msg[5] & 15; - if (Mode > 8) Mode = 8; - sprintf(RIG->WEB_MODE,"%s", FT100Modes[Mode]); - } - else // FT1000 - { - Mode = Msg[7] & 7; - sprintf(RIG->WEB_MODE,"%s", FTRXModes[Mode]); - } - - strcpy(RIG->ModeString, RIG->WEB_MODE); - SetWindowText(RIG->hMODE, RIG->WEB_MODE); - - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Mode and Frequency Set OK"); - else - if (PORT->TXLen > 5) // Poll is 5 change is more - ReleasePermission(RIG); // Release Perrmission to change -} - - - - - -VOID ProcessYaesuCmdAck(struct RIGPORTINFO * PORT) -{ - UCHAR * Poll = PORT->TXBuffer; - UCHAR * Msg = PORT->RXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Yaseu - - PORT->Timeout = 0; - PORT->RXLen = 0; // Ready for next frame - - if (PORT->CmdSent == 1) // Set Freq - { - ReleasePermission(RIG); // Release Perrmission - - if (Msg[0]) - { - // I think nonzero is a Reject - - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Sorry - Set Frequency Rejected"); - - return; - } - else - { - if (RIG->ScanStopped == 0) - { - // Send a Get Freq - We Don't Poll when scanning - - Poll[0] = Poll[1] = Poll[2] = Poll[3] = 0; - Poll[4] = 0x3; // Get frequency amd mode command - - RigWriteCommBlock(PORT); - PORT->Retries = 2; - PORT->CmdSent = 0; - } - else - - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Mode and Frequency Set OK"); - - return; - } - } - - if (PORT->CmdSent == 7) // Set Mode - { - if (Msg[0]) - { - // I think nonzero is a Reject - - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Sorry - Set Mode Rejected"); - - return; - } - else - { - // Send the Frequency - - memcpy(Poll, &Poll[5], 5); - RigWriteCommBlock(PORT); - PORT->CmdSent = Poll[4]; - PORT->Retries = 2; - - return; - } - } - -} -VOID ProcessYaesuFrame(struct RIGPORTINFO * PORT) -{ - UCHAR * Poll = PORT->TXBuffer; - UCHAR * Msg = PORT->RXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Yaseu - int n, j, Freq = 0, decdigit; - double FreqF; - unsigned int Mode; - - // I'm not sure we get anything but a Command Response, - // and the only command we send is Get Rig Frequency and Mode - - - RIG->RIGOK = TRUE; - PORT->Timeout = 0; - - for (j = 0; j < 4; j++) - { - n = Msg[j]; - decdigit = (n >> 4); - decdigit *= 10; - decdigit += n & 0xf; - Freq = (Freq *100 ) + decdigit; - } - - FreqF = Freq / 100000.0; - - RIG->RigFreq = FreqF; - -// Valchar = _fcvt(FreqF, 6, &dec, &sign); - _gcvt(FreqF, 9, RIG->Valchar); - - sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - - Mode = Msg[4]; - - if (Mode > 15) Mode = 15; - - sprintf(RIG->WEB_MODE,"%s", YaesuModes[Mode]); - strcpy(RIG->ModeString, RIG->WEB_MODE); - SetWindowText(RIG->hMODE, RIG->WEB_MODE); - - // FT847 Manual Freq Change response ends up here - - if (strcmp(RIG->RigName, "FT847") == 0) - { - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Mode and Frequency Set OK"); - - if (PORT->CmdSent == -1) - ReleasePermission(RIG); // Release Perrmission to change - } -} - -VOID YaesuPoll(struct RIGPORTINFO * PORT) -{ - UCHAR * Poll = PORT->TXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Yaseu - - if (RIG->ScanStopped == 0) - if (RIG->ScanCounter) - RIG->ScanCounter--; - - if (PORT->Timeout) - { - PORT->Timeout--; - - if (PORT->Timeout) // Still waiting - return; - - PORT->Retries--; - - if(PORT->Retries) - { - RigWriteCommBlock(PORT); // Retransmit Block - return; - } - - SetWindowText(RIG->hFREQ, "------------------"); - SetWindowText(RIG->hMODE, "----------"); - strcpy(RIG->WEB_FREQ, "-----------");; - strcpy(RIG->WEB_MODE, "------"); - - - PORT->Rigs[PORT->CurrentRig].RIGOK = FALSE; - - return; - - } - - // Send Data if avail, else send poll - - if (RIG->NumberofBands && (RIG->ScanStopped == 0)) - { - if (RIG->ScanCounter <= 0) - { - // Send Next Freq - - if (GetPermissionToChange(PORT, RIG)) - { - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); - - _gcvt(PORT->FreqPtr->Freq / 1000000.0, 9, RIG->Valchar); // For MH - - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd1, 24); - - if (PORT->PortType == YAESU) - { - if (strcmp(PORT->Rigs[0].RigName, "FT847") == 0) - { - PORT->TXLen = 15; // No Cmd ACK, so send Mode, Freq and Poll - PORT->CmdSent = -1; - } - else - { - PORT->TXLen = 5; - PORT->CmdSent = Poll[4]; - } - RigWriteCommBlock(PORT); - PORT->Retries = 2; - PORT->AutoPoll = TRUE; - return; - } - - // FT100 - - PORT->TXLen = 15; // Set Mode, Set Freq, Poll - RigWriteCommBlock(PORT); - PORT->Retries = 2; - PORT->AutoPoll = TRUE; - } - } - } - - if (RIG->RIGOK && RIG->BPQtoRADIO_Q) - { - struct MSGWITHOUTLEN * buffptr; - - buffptr = Q_REM(&RIG->BPQtoRADIO_Q); - - // Copy the ScanEntry struct from the Buffer to the PORT Scanentry - - memcpy(&PORT->ScanEntry, buffptr->Data, sizeof(struct ScanEntry)); - - PORT->FreqPtr = &PORT->ScanEntry; // Block we are currently sending. - - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); - - _gcvt(PORT->FreqPtr->Freq / 1000000.0, 9, RIG->Valchar); // For MH - - DoBandwidthandAntenna(RIG, &PORT->ScanEntry); - - memcpy(Poll, PORT->FreqPtr->Cmd1, PORT->FreqPtr->Cmd1Len); - - if (PORT->PortType == YAESU) - { - if (strcmp(PORT->Rigs[0].RigName, "FT847") == 0) - { - PORT->TXLen = 15; // Send all - PORT->CmdSent = -1; - } - else - { - PORT->TXLen = 5; // First send the set Freq - PORT->CmdSent = Poll[4]; - } - } - else - PORT->TXLen = 15; // Send all - - RigWriteCommBlock(PORT); - PORT->Retries = 2; - - ReleaseBuffer(buffptr); - PORT->AutoPoll = FALSE; - - return; - } - - if (RIG->RIGOK && RIG->ScanStopped == 0 && RIG->NumberofBands && - RIG->ScanCounter && RIG->ScanCounter < 30) // no point in reading freq if we are about to change - return; - - if (RIG->PollCounter) - { - RIG->PollCounter--; - if (RIG->PollCounter) - return; - } - - RIG->PollCounter = 10; // Once Per Sec - - // Read Frequency - - Poll[0] = 0; - Poll[1] = 0; - Poll[2] = 0; - - if (PORT->PortType == FT990 || PORT->PortType == YAESU || PORT->YaesuVariant == FT1000D) - Poll[3] = 3; - else - Poll[3] = 2; - - if (PORT->PortType == YAESU) - Poll[4] = 0x3; // Get frequency amd mode command - else - Poll[4] = 16; // FT100/990/1000 Get frequency amd mode command - - PORT->TXLen = 5; - RigWriteCommBlock(PORT); - PORT->Retries = 2; - PORT->CmdSent = 0; - - PORT->AutoPoll = TRUE; - - return; -} - -VOID ProcessNMEA(struct RIGPORTINFO * PORT, char * Msg, int Length) -{ - UCHAR * Poll = PORT->TXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Yaseu - - Msg[Length] = 0; - - if (PORT->PORTOK == FALSE) - { - // Just come up - PORT->PORTOK = TRUE; - } - - RIG->RIGOK = TRUE; - PORT->Timeout = 0; - - if (!PORT->AutoPoll) - { - // Response to a RADIO Command - - if (Msg[0] == '?') - SendResponse(RIG->Session, "Sorry - Command Rejected"); - else - SendResponse(RIG->Session, "Mode and Frequency Set OK"); - - PORT->AutoPoll = TRUE; - } - - if (memcmp(&Msg[13], "RXF", 3) == 0) - { - if (Length < 24) - return; - - RIG->RigFreq = atof(&Msg[17]); - - sprintf(RIG->WEB_FREQ,"%f", RIG->RigFreq); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - strcpy(RIG->Valchar, RIG->WEB_FREQ); - - return; - } - - if (memcmp(&Msg[13], "MODE", 3) == 0) - { - char * ptr; - - if (Length < 24) - return; - - ptr = strchr(&Msg[18], '*'); - if (ptr) *(ptr) = 0; - - SetWindowText(RIG->hMODE, &Msg[18]); - strcpy(RIG->WEB_MODE, &Msg[18]); - strcpy(RIG->ModeString, RIG->WEB_MODE); - return; - } - - -} - - -//FA00014103000;MD2; - -VOID ProcessKenwoodFrame(struct RIGPORTINFO * PORT, int Length) -{ - UCHAR * Poll = PORT->TXBuffer; - UCHAR * Msg = PORT->RXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Yaseu - UCHAR * ptr; - int CmdLen; - - Msg[Length] = 0; - - if (PORT->PORTOK == FALSE) - { - // Just come up - PORT->PORTOK = TRUE; - } - - RIG->RIGOK = TRUE; - - if (!PORT->AutoPoll) - { - // Response to a RADIO Command - - if (Msg[0] == '?') - SendResponse(RIG->Session, "Sorry - Command Rejected"); - else if (Msg[0] == 'A' && Msg[1] == 'C') - SendResponse(RIG->Session, "TUNE OK"); - else if (Msg[0] == 'P' && Msg[1] == 'C') - SendResponse(RIG->Session, "Power Set OK"); - else - SendResponse(RIG->Session, "Mode and Frequency Set OK"); - - PORT->AutoPoll = TRUE; - return; - } - - -Loop: - - if (PORT->PortType == FLEX) - { - Msg += 2; // Skip ZZ - Length -= 2; - } - - ptr = strchr(Msg, ';'); - CmdLen = (int)(ptr - Msg + 1); - - if (Msg[0] == 'F' && Msg[1] == 'A' && CmdLen > 9) - { - char CharMHz[16] = ""; - char CharHz[16] = ""; - - int i; - long long Freq; - long long MHz, Hz; - - Freq = strtoll(&Msg[2], NULL, 10) + RIG->rxOffset; - - RIG->RigFreq = Freq / 1000000.0; - - // If we convert to float to display we get rounding errors, so convert to MHz and Hz to display - - MHz = Freq / 1000000; - - Hz = Freq - MHz * 1000000; - - sprintf(CharMHz, "%lld", MHz); - sprintf(CharHz, "%06lld", Hz); - -/* - if (PORT->PortType == FT2000) - { - memcpy(FreqDecimal,&Msg[4], 6); - Msg[4] = 0; - } - else if (PORT->PortType == FT991A) - { - memcpy(FreqDecimal,&Msg[5], 6); - Msg[5] = 0; - } - - else - { - memcpy(FreqDecimal,&Msg[7], 6); - Msg[7] = 0; - } - FreqDecimal[6] = 0; -*/ - - for (i = 5; i > 2; i--) - { - if (CharHz[i] == '0') - CharHz[i] = 0; - else - break; - } - - - sprintf(RIG->WEB_FREQ,"%lld.%s", MHz, CharHz); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - strcpy(RIG->Valchar, RIG->WEB_FREQ); - - PORT->Timeout = 0; - } - else if (Msg[0] == 'M' && Msg[1] == 'D') - { - int Mode; - - if (PORT->PortType == FT2000) - { - Mode = Msg[3] - 48; - if (Mode > 13) Mode = 13; - SetWindowText(RIG->hMODE, FT2000Modes[Mode]); - strcpy(RIG->WEB_MODE, FT2000Modes[Mode]); - strcpy(RIG->ModeString, RIG->WEB_MODE); - } - else if (PORT->PortType == FT991A) - { - Mode = Msg[3] - 48; - if (Mode > 16) - Mode -= 7; - - if (Mode > 15) Mode = 13; - SetWindowText(RIG->hMODE, FT991AModes[Mode]); - strcpy(RIG->WEB_MODE, FT991AModes[Mode]); - strcpy(RIG->ModeString, RIG->WEB_MODE); - } - else if (PORT->PortType == FLEX) - { - Mode = atoi(&Msg[3]); - if (Mode > 12) Mode = 12; - SetWindowText(RIG->hMODE, FLEXModes[Mode]); - strcpy(RIG->WEB_MODE, FLEXModes[Mode]); - strcpy(RIG->ModeString, RIG->WEB_MODE); - } - else - { - Mode = Msg[2] - 48; - if (Mode > 7) Mode = 7; - SetWindowText(RIG->hMODE, KenwoodModes[Mode]); - strcpy(RIG->WEB_MODE, KenwoodModes[Mode]); - strcpy(RIG->ModeString, RIG->WEB_MODE); - } - } - - if (CmdLen < Length) - { - // Another Message in Buffer - - ptr++; - Length -= (int)(ptr - Msg); - - if (Length <= 0) - return; - - memmove(Msg, ptr, Length +1); - - goto Loop; - } -} - - -VOID KenwoodPoll(struct RIGPORTINFO * PORT) -{ - UCHAR * Poll = PORT->TXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Kenwood - - if (RIG->ScanStopped == 0) - if (RIG->ScanCounter) - RIG->ScanCounter--; - - if (PORT->Timeout) - { - PORT->Timeout--; - - if (PORT->Timeout) // Still waiting - return; - - PORT->Retries--; - - if(PORT->Retries) - { - RigWriteCommBlock(PORT); // Retransmit Block - return; - } - - SetWindowText(RIG->hFREQ, "------------------"); - SetWindowText(RIG->hMODE, "----------"); - strcpy(RIG->WEB_FREQ, "-----------");; - strcpy(RIG->WEB_MODE, "------"); - - RIG->RIGOK = FALSE; - - return; - } - - // Send Data if avail, else send poll - - if (RIG->NumberofBands && RIG->RIGOK && (RIG->ScanStopped == 0)) - { - if (RIG->ScanCounter <= 0) - { - // Send Next Freq - - if (GetPermissionToChange(PORT, RIG)) - { - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); - - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd1, PORT->FreqPtr->Cmd1Len); - PORT->TXLen = PORT->FreqPtr->Cmd1Len; - - _gcvt(PORT->FreqPtr->Freq / 1000000.0, 9, RIG->Valchar); // For MH - - RigWriteCommBlock(PORT); - PORT->CmdSent = 1; - PORT->Retries = 0; - PORT->Timeout = 0; - PORT->AutoPoll = TRUE; - - // There isn't a response to a set command, so clear Scan Lock here - - ReleasePermission(RIG); // Release Perrmission - - return; - } - } - } - - if (RIG->RIGOK && RIG->BPQtoRADIO_Q) - { - struct MSGWITHOUTLEN * buffptr; - - buffptr = Q_REM(&RIG->BPQtoRADIO_Q); - - // Copy the ScanEntry struct from the Buffer to the PORT Scanentry - - memcpy(&PORT->ScanEntry, buffptr->Data, sizeof(struct ScanEntry)); - - PORT->FreqPtr = &PORT->ScanEntry; // Block we are currently sending. - - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); - - DoBandwidthandAntenna(RIG, &PORT->ScanEntry); - - _gcvt(PORT->FreqPtr->Freq / 1000000.0, 9, RIG->Valchar); // For MH - - memcpy(Poll, PORT->FreqPtr->Cmd1, PORT->FreqPtr->Cmd1Len); - - PORT->TXLen = PORT->FreqPtr->Cmd1Len; - RigWriteCommBlock(PORT); - PORT->CmdSent = Poll[4]; - PORT->Timeout = 0; - RIG->PollCounter = 10; - - ReleaseBuffer(buffptr); - PORT->AutoPoll = FALSE; - - return; - } - - if (RIG->PollCounter) - { - RIG->PollCounter--; - if (RIG->PollCounter > 1) - return; - } - - if (RIG->RIGOK && RIG->ScanStopped == 0 && RIG->NumberofBands && - RIG->ScanCounter && RIG->ScanCounter < 30) - return; // no point in reading freq if we are about to change it - - RIG->PollCounter = 10; // Once Per Sec - - // Read Frequency - - PORT->TXLen = RIG->PollLen; - strcpy(Poll, RIG->Poll); - - RigWriteCommBlock(PORT); - PORT->Retries = 1; - PORT->Timeout = 10; - PORT->CmdSent = 0; - - PORT->AutoPoll = TRUE; - - return; -} - -VOID DummyPoll(struct RIGPORTINFO * PORT) -{ - UCHAR * Poll = PORT->TXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; - - if (RIG->ScanStopped == 0) - if (RIG->ScanCounter) - RIG->ScanCounter--; - - if (RIG->NumberofBands && RIG->RIGOK && (RIG->ScanStopped == 0)) - { - if (RIG->ScanCounter <= 0) - { - // Send Next Freq - - if (GetPermissionToChange(PORT, RIG)) - { - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); - - _gcvt(PORT->FreqPtr->Freq / 1000000.0, 9, RIG->Valchar); // For MH - - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd1, PORT->FreqPtr->Cmd1Len); - PORT->TXLen = PORT->FreqPtr->Cmd1Len; -/* - RigWriteCommBlock(PORT); - PORT->CmdSent = 1; - PORT->Retries = 0; - PORT->Timeout = 0; - PORT->AutoPoll = TRUE; -*/ - // There isn't a response to a set command, so clear Scan Lock here - - ReleasePermission(RIG); // Release Perrmission - - return; - } - } - } - - return; -} - -VOID SwitchAntenna(struct RIGINFO * RIG, char Antenna) -{ - struct RIGPORTINFO * PORT; - char Ant[3]=" "; - - if (RIG == NULL) return; - - PORT = RIG->PORT; - - Ant[1] = Antenna; - - SetWindowText(RIG->hPTT, Ant); - - switch (Antenna) - { - case '1': - COMClearDTR(PORT->hDevice); - COMClearRTS(PORT->hDevice); - break; - case '2': - COMSetDTR(PORT->hDevice); - COMClearRTS(PORT->hDevice); - break; - case '3': - COMClearDTR(PORT->hDevice); - COMSetRTS(PORT->hDevice); - break; - case '4': - COMSetDTR(PORT->hDevice); - COMSetRTS(PORT->hDevice); - break; - } -} - -BOOL DecodeModePtr(char * Param, double * Dwell, double * Freq, char * Mode, - char * PMinLevel, char * PMaxLevel, char * PacketMode, - char * RPacketMode, char * Split, char * Data, char * WinmorMode, - char * Antenna, BOOL * Supress, char * Filter, char * Appl, - char * MemoryBank, int * MemoryNumber, char * ARDOPMode, char * VARAMode, int * BandWidth, int * Power) -{ - char * Context; - char * ptr; - - *Filter = '1'; // Defaults - *PMinLevel = 1; - *MemoryBank = 0; - *MemoryNumber = 0; - *Mode = 0; - *ARDOPMode = 0; - *VARAMode = 0; - *Power = 0; - - - ptr = strtok_s(Param, ",", &Context); - - if (ptr == NULL) - return FALSE; - - // "New" format - Dwell, Freq, Params. - - // Each param is a 2 char pair, separated by commas - - // An - Antenna - // Pn - Pactor - // Wn - Winmor - // Pn - Packet - // Fn - Filter - // Sx - Split - - // 7.0770/LSB,F1,A3,WN,P1,R1 - - *Dwell = atof(ptr); - - ptr = strtok_s(NULL, ",", &Context); - - if (ptr == NULL) - return FALSE; - - - // May be a frequency or a Memory Bank/Channel - - if (_memicmp(ptr, "Chan", 4) == 0) - { - if (strchr(ptr, '/')) // Bank/Chan - { - memcpy(MemoryBank, &ptr[4], 1); - *MemoryNumber = atoi(&ptr[6]); - } - else - *MemoryNumber = atoi(&ptr[4]); // Just Chan - - *Freq = 0.0; - } - else - *Freq = atof(ptr); - - ptr = strtok_s(NULL, ",", &Context); - - if (ptr == NULL || strlen(ptr) > 8) - return FALSE; - - // If channel, dont need mode - - if (*MemoryNumber == 0) - { - strcpy(Mode, ptr); - ptr = strtok_s(NULL, ",", &Context); - } - - while (ptr) - { - if (isdigit(ptr[0])) - *BandWidth = atoi(ptr); - - else if (memcmp(ptr, "APPL=", 5) == 0) - strcpy(Appl, ptr + 5); - - else if (memcmp(ptr, "POWER=", 6) == 0) - *Power = atoi(ptr + 6); - - else if (ptr[0] == 'A' && (ptr[1] == 'S' || ptr[1] == '0') && strlen(ptr) < 7) - strcpy(ARDOPMode, "S"); - - else if (ptr[0] == 'A' && strlen(ptr) > 2 && strlen(ptr) < 7) - strcpy(ARDOPMode, &ptr[1]); - - else if (ptr[0] == 'A' && strlen(ptr) == 2) - *Antenna = ptr[1]; - - else if (ptr[0] == 'F') - *Filter = ptr[1]; - - else if (ptr[0] == 'R') - *RPacketMode = ptr[1]; - - else if (ptr[0] == 'H') - *PacketMode = ptr[1]; - - else if (ptr[0] == 'N') - *PacketMode = ptr[1]; - - else if (ptr[0] == 'P') - { - *PMinLevel = ptr[1]; - *PMaxLevel = ptr[strlen(ptr) - 1]; - } - else if (ptr[0] == 'W') - { - *WinmorMode = ptr[1]; - if (*WinmorMode == '0') - *WinmorMode = 'X'; - else if (*WinmorMode == '1') - *WinmorMode = 'N'; - else if (*WinmorMode == '2') - *WinmorMode = 'W'; - } - - else if (ptr[0] == 'V') - { - *VARAMode = ptr[1]; - // W N S T (skip) or 0 (also Skip) - if (ptr[1] == '0') - *VARAMode = 'S'; - } - else if (ptr[0] == '+') - *Split = '+'; - else if (ptr[0] == '-') - *Split = '-'; - else if (ptr[0] == 'S') - *Split = 'S'; - else if (ptr[0] == 'D') - *Data = 1; - else if (ptr[0] == 'X') - *Supress = TRUE; - - ptr = strtok_s(NULL, ",", &Context); - } - return TRUE; -} - -VOID AddNMEAChecksum(char * msg) -{ - UCHAR CRC = 0; - - msg++; // Skip $ - - while (*(msg) != '*') - { - CRC ^= *(msg++); - } - - sprintf(++msg, "%02X\r\n", CRC); -} - -void DecodeRemote(struct RIGPORTINFO * PORT, char * ptr) -{ - // Param is IPHOST:PORT for use with WINMORCONTROL - - struct sockaddr_in * destaddr = (SOCKADDR_IN * )&PORT->remoteDest; - UCHAR param = 1; - u_long ioparam = 1; - - char * port = strlop(ptr, ':'); - - PORT->remoteSock = socket(AF_INET,SOCK_DGRAM,0); - - if (PORT->remoteSock == INVALID_SOCKET) - return; - - setsockopt (PORT->remoteSock, SOL_SOCKET, SO_BROADCAST, ¶m, 1); - - if (port == NULL) - return; - - ioctl (PORT->remoteSock, FIONBIO, &ioparam); - - destaddr->sin_family = AF_INET; - destaddr->sin_addr.s_addr = inet_addr(ptr); - destaddr->sin_port = htons(atoi(port)); - - if (destaddr->sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - struct hostent * HostEnt = gethostbyname(ptr); - - if (!HostEnt) - return; // Resolve failed - - memcpy(&destaddr->sin_addr.s_addr,HostEnt->h_addr,4); - } - - return; -} - - -char * CM108Device = NULL; - -void DecodeCM108(int Port, char * ptr) -{ - // Called if Device Name or PTT = Param is CM108 - -#ifdef WIN32 - - // Next Param is VID and PID - 0xd8c:0x8 or Full device name - // On Windows device name is very long and difficult to find, so - // easier to use VID/PID, but allow device in case more than one needed - - char * next; - int32_t VID = 0, PID = 0; - char product[256]; - - struct hid_device_info *devs, *cur_dev; - const char *path_to_open = NULL; - hid_device *handle = NULL; - - if (strlen(ptr) > 16) - CM108Device = _strdup(ptr); - else - { - VID = strtol(ptr, &next, 0); - if (next) - PID = strtol(++next, &next, 0); - - // Look for Device - - devs = hid_enumerate(0,0); // so we list devices(USHORT)VID, (USHORT)PID); - cur_dev = devs; - while (cur_dev) - { - wcstombs(product, cur_dev->product_string, 255); - - if (product) - Debugprintf("HID Device %s VID %X PID %X %s", product, cur_dev->vendor_id, cur_dev->product_id, cur_dev->path); - else - Debugprintf("HID Device %s VID %X PID %X %s", "Missing Product", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path); - - if (cur_dev->vendor_id == VID && cur_dev->product_id == PID) - path_to_open = cur_dev->path; - - cur_dev = cur_dev->next; - } - - if (path_to_open) - { - handle = hid_open_path(path_to_open); - - if (handle) - { - hid_close(handle); - CM108Device = _strdup(path_to_open); - } - else - { - char msg[128]; - sprintf(msg,"Port %d Unable to open CM108 device %x %x", Port, VID, PID); - WritetoConsole(msg); - } - } - hid_free_enumeration(devs); - } -#else - - // Linux - Next Param HID Device, eg /dev/hidraw0 - - CM108Device = _strdup(ptr); -#endif -} - - - -// Called by Port Driver .dll to add/update rig info - -// RIGCONTROL COM60 19200 ICOM IC706 5e 4 14.103/U1w 14.112/u1 18.1/U1n 10.12/l1 - - -struct RIGINFO * RigConfig(struct TNCINFO * TNC, char * buf, int Port) -{ - int i; - char * ptr; - char * COMPort = NULL; - char * RigName; - int RigAddr; - struct RIGPORTINFO * PORT; - struct RIGINFO * RIG; - struct ScanEntry ** FreqPtr; - char * CmdPtr; - char * Context; - struct TimeScan * SaveBand; - char PTTRigName[] = "PTT"; - double ScanFreq; - double Dwell; - char MemoryBank; // For Memory Scanning - int MemoryNumber; - BOOL RIG_DEBUG = FALSE; - - BOOL PTTControlsInputMUX = FALSE; - BOOL DataPTT = FALSE; - int DataPTTOffMode = 1; // ACC - int ICF8101Mode = 8; // USB (as in upper sideband) - - char onString[256] = ""; - char offString[256] = ""; - int onLen = 0; - int offLen = 0; - - CM108Device = NULL; - Debugprintf("Processing RIG line %s", buf); - - // Starts RADIO Interlockgroup - - ptr = strtok_s(&buf[5], " \t\n\r", &Context); // Skip Interlock - if (ptr == NULL) return FALSE; - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL) return FALSE; - - if (_memicmp(ptr, "DEBUG", 5) == 0) - { - ptr = strtok_s(NULL, " \t\n\r", &Context); - RIG_DEBUG = TRUE; - } - - if (_memicmp(ptr, "AUTH", 4) == 0) - { - ptr = strtok_s(NULL, " \t\n\r", &Context); - if (ptr == NULL) return FALSE; - if (strlen(ptr) > 100) return FALSE; - - strcpy(AuthPassword, ptr); - ptr = strtok_s(NULL, " \t\n\r", &Context); - } - - if (ptr == NULL || ptr[0] == 0) - return FALSE; - - if (_memicmp(ptr, "DUMMY", 5) == 0) - { - // Dummy to allow PTC application scanning - - PORT = PORTInfo[NumberofPorts++] = zalloc(sizeof(struct RIGPORTINFO)); - PORT->PortType = DUMMY; - PORT->ConfiguredRigs = 1; - RIG = &PORT->Rigs[0]; - RIG->RIGOK = TRUE; - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - goto CheckScan; - } - - if (_memicmp(ptr, "FLRIG", 5) == 0) - { - // Use FLRIG - - // Need parameter - Host:Port - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL || strlen(ptr) > 79) return FALSE; - - // Have a parameter to define port. Will decode it later - - PORT = PORTInfo[NumberofPorts++] = zalloc(sizeof(struct RIGPORTINFO)); - PORT->PortType = FLRIG; - PORT->ConfiguredRigs = 1; - RIG = &PORT->Rigs[0]; - RIG->RIGOK = TRUE; - RIG->PORT = PORT; - - strcpy(PORT->IOBASE, ptr); - strcpy(RIG->RigName, "FLRIG"); - - // Decode host - - DecodeHAMLIBAddr(PORT, ptr); - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - // look for other config statementes and scan params - - goto CheckOtherParams; - } - - if (_memicmp(ptr, "HAMLIB", 5) == 0) - { - // Use rigctld - - // Need parameter - Host:Port - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL || strlen(ptr) > 79) return FALSE; - - // Have a parameter to define port. Will decode it later - - PORT = PORTInfo[NumberofPorts++] = zalloc(sizeof(struct RIGPORTINFO)); - PORT->PortType = HAMLIB; - PORT->ConfiguredRigs = 1; - RIG = &PORT->Rigs[0]; - RIG->RIGOK = TRUE; - RIG->PORT = PORT; - - strcpy(PORT->IOBASE, ptr); - strcpy(RIG->RigName, "HAMLIB"); - - // Decode host - - DecodeHAMLIBAddr(PORT, ptr); - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - // look for scan params - - goto CheckOtherParams; - } - - if (_memicmp(ptr, "rtludp", 5) == 0) - { - // rtl_fm with udp freq control - - // Need parameter - Host:Port - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL || strlen(ptr) > 79) return FALSE; - - // Have a parameter to define port. Will decode it later - - PORT = PORTInfo[NumberofPorts++] = zalloc(sizeof(struct RIGPORTINFO)); - PORT->PortType = RTLUDP; - PORT->ConfiguredRigs = 1; - RIG = &PORT->Rigs[0]; - RIG->RIGOK = TRUE; - RIG->PORT = PORT; - - strcpy(PORT->IOBASE, ptr); - strcpy(RIG->RigName, "RTLUDP"); - - // Decode host - - DecodeHAMLIBAddr(PORT, ptr); - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - // look for scan params - - goto CheckOtherParams; - } - - - if ((_memicmp(ptr, "VCOM", 4) == 0) && TNC->Hardware == H_SCS) // Using Radio Port on PTC - COMPort = 0; - else if (_memicmp(ptr, "PTCPORT", 7) == 0) - COMPort = 0; - else - COMPort = ptr; - - // See if port is already defined. We may be adding another radio (ICOM only) or updating an existing one - - // Unless CM108 - they must be on separate Ports - - if (COMPort && _stricmp("CM108", COMPort) != 0) - { - for (i = 0; i < NumberofPorts; i++) - { - PORT = PORTInfo[i]; - - if (COMPort) - if (strcmp(PORT->IOBASE, COMPort) == 0) - goto PortFound; - - if (COMPort == 0) - if (PORT->IOBASE == COMPort) - goto PortFound; - } - } - - // Allocate a new one - - PORT = PORTInfo[NumberofPorts++] = zalloc(sizeof(struct RIGPORTINFO)); - - if (COMPort) - strcpy(PORT->IOBASE, COMPort); - -PortFound: - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL) return (FALSE); - - if (_stricmp(PORT->IOBASE, "RAWHID") == 0) // HID Addr instead of Speed - { - DecodeCM108(Port, ptr); - if (CM108Device) - PORT->HIDDevice = CM108Device; - else - PORT->HIDDevice = _strdup ("MissingHID"); - - CM108Device = 0; - } - - if ( _stricmp(PORT->IOBASE, "CM108") == 0) // HID Addr instead of Speed - { - DecodeCM108(Port, ptr); - } - - if (_stricmp(PORT->IOBASE, "REMOTE") == 0) // IP Addr/Port - DecodeRemote(PORT, ptr); - else - PORT->SPEED = atoi(ptr); - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL) return (FALSE); - - if (_memicmp(ptr, "PTTCOM", 6) == 0 || _memicmp(ptr, "PTT=", 4) == 0) - { - if (_stricmp(ptr, "PTT=CM108") == 0) - { - // PTT on CM108 GPIO - - ptr = strtok_s(NULL, " \t\n\r", &Context); - if (ptr == NULL) return (FALSE); - - DecodeCM108(Port, ptr); - } - else - { - strcpy(PORT->PTTIOBASE, ptr); - } - ptr = strtok_s(NULL, " \t\n\r", &Context); - if (ptr == NULL) return (FALSE); - - } - - // if (strcmp(ptr, "ICOM") == 0 || strcmp(ptr, "YAESU") == 0 - // || strcmp(ptr, "KENWOOD") == 0 || strcmp(ptr, "PTTONLY") == 0 || strcmp(ptr, "ANTENNA") == 0) - - // RADIO IC706 4E 5 14.103/U1 14.112/u1 18.1/U1 10.12/l1 - // Read RADIO Lines - - _strupr(ptr); - - - if (strcmp(ptr, "ICOM") == 0) - PORT->PortType = ICOM; - else if (strcmp(ptr, "YAESU") == 0) - PORT->PortType = YAESU; - else if (strcmp(ptr, "KENWOOD") == 0) - PORT->PortType = KENWOOD; - else if (strcmp(ptr, "FLEX") == 0) - PORT->PortType = FLEX; - else if (strcmp(ptr, "NMEA") == 0) - PORT->PortType = NMEA; - else if (strcmp(ptr, "PTTONLY") == 0) - PORT->PortType = PTT; - else if (strcmp(ptr, "ANTENNA") == 0) - PORT->PortType = ANT; - else - return FALSE; - - Debugprintf("Port type = %d", PORT->PortType); - - _strupr(Context); - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr && memcmp(ptr, "HAMLIB=", 7) == 0) - { - // HAMLIB Emulator - param is port to listen on - - if (PORT->PortType == PTT) - { - RIG = &PORT->Rigs[PORT->ConfiguredRigs++]; - strcpy(RIG->RigName, PTTRigName); - - RIG->HAMLIBPORT = atoi(&ptr[7]); - ptr = strtok_s(NULL, " \t\n\r", &Context); - - } - } - - if (ptr && strcmp(ptr, "PTTMUX") == 0) - { - if (PORT->PortType == PTT) - { - RIG = &PORT->Rigs[PORT->ConfiguredRigs++]; - strcpy(RIG->RigName, PTTRigName); - goto domux; // PTTONLY with PTTMUX - } - } - - - if (ptr == NULL) - { - if (PORT->PortType == PTT) - ptr = PTTRigName; - else - return FALSE; - } - - if (strlen(ptr) > 9) return FALSE; - - RigName = ptr; - - Debugprintf("Rigname = *%s*", RigName); - - // FT100 seems to be different to most other YAESU types - - if (strcmp(RigName, "FT100") == 0 && PORT->PortType == YAESU) - { - PORT->PortType = FT100; - } - - // FT990 seems to be different to most other YAESU types - - if (strcmp(RigName, "FT990") == 0 && PORT->PortType == YAESU) - { - PORT->PortType = FT990; - } - - // FT1000 seems to be different to most other YAESU types - - if (strstr(RigName, "FT1000") && PORT->PortType == YAESU) - { - PORT->PortType = FT1000; - - // Subtypes need different code. D and no suffix are same - - if (strstr(RigName, "FT1000MP")) - PORT->YaesuVariant = FT1000MP; - else - PORT->YaesuVariant = FT1000D; - } - - // FT2000 seems to be different to most other YAESU types - - if (strcmp(RigName, "FT2000") == 0 && PORT->PortType == YAESU) - { - PORT->PortType = FT2000; - } - - // FT991A seems to be different to most other YAESU types - - if (strcmp(RigName, "FT991A") == 0 && PORT->PortType == YAESU) - { - PORT->PortType = FT991A; - } - - - // If ICOM, we may be adding a new Rig - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (PORT->PortType == ICOM || PORT->PortType == NMEA) - { - if (ptr == NULL) return (FALSE); - sscanf(ptr, "%x", &RigAddr); - - // See if already defined - - for (i = 0; i < PORT->ConfiguredRigs; i++) - { - RIG = &PORT->Rigs[i]; - - if (RIG->RigAddr == RigAddr) - goto RigFound; - } - - // Allocate a new one - - RIG = &PORT->Rigs[PORT->ConfiguredRigs++]; - RIG->RigAddr = RigAddr; - -RigFound: - - ptr = strtok_s(NULL, " \t\n\r", &Context); - // if (ptr == NULL) return (FALSE); - } - else - { - // Only allows one RIG - - PORT->ConfiguredRigs = 1; - RIG = &PORT->Rigs[0]; - } - - RIG->RIG_DEBUG = RIG_DEBUG; - RIG->PORT = PORT; - - strcpy(RIG->RigName, RigName); - - RIG->TSMenu = 63; // Default to TS590S - - // IC735 uses shorter freq message - - if (strcmp(RigName, "IC735") == 0 && PORT->PortType == ICOM) - RIG->IC735 = TRUE; - - // IC-F8101 uses a different set of commands - - if (strstr(RigName, "F8101") && PORT->PortType == ICOM) - RIG->ICF8101 = TRUE; - - if (PORT->PortType == KENWOOD) - { - RIG->TSMenu = 63; // Default to TS590S - - if (strcmp(RigName, "TS590SG") == 0) - RIG->TSMenu = 69; - } - - if (PORT->PortType == FT991A) - RIG->TSMenu = 72; //Menu for Data/USB siwtching - -domux: - - RIG->CM108Device = CM108Device; - -CheckOtherParams: - - while (ptr) - { - if (strcmp(ptr, "PTTMUX") == 0) - { - // Ports whose RTS/DTR will be converted to CAT commands (for IC7100/IC7200 etc) - - int PIndex = 0; - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - while (memcmp(ptr, "COM", 3) == 0) - { - char * tncport = strlop(ptr, '/'); - - strcpy(RIG->PTTCATPort[PIndex], &ptr[3]); - - if (tncport) - RIG->PTTCATTNC[PIndex] = TNCInfo[atoi(tncport)]; - - if (PIndex < 3) - PIndex++; - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL) - break; - } - if (ptr == NULL) - break; - else - continue; - } - else if (strcmp(ptr, "PTT_SETS_INPUT") == 0) - { - // Send Select Soundcard as mod source with PTT commands - - PTTControlsInputMUX = TRUE; - - // See if following param is an PTT Off Mode - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL) - break; - - if (strcmp(ptr, "MIC") == 0) - DataPTTOffMode = 0; - else if (strcmp(ptr, "AUX") == 0) - DataPTTOffMode = 1; - else if (strcmp(ptr, "MICAUX") == 0) - DataPTTOffMode = 2; - else if (RIG->ICF8101 && strcmp(ptr, "LSB") == 0) - ICF8101Mode = 0x7; - else if (RIG->ICF8101 && strcmp(ptr, "USB") == 0) - ICF8101Mode = 0x8; - else if (RIG->ICF8101 && strcmp(ptr, "LSBD1") == 0) - ICF8101Mode = 0x18; - else if (RIG->ICF8101 && strcmp(ptr, "USBD1") == 0) - ICF8101Mode = 0x19; - else if (RIG->ICF8101 && strcmp(ptr, "LSBD2") == 0) - ICF8101Mode = 0x20; - else if (RIG->ICF8101 && strcmp(ptr, "USBD2") == 0) - ICF8101Mode = 0x21; - else if (RIG->ICF8101 && strcmp(ptr, "LSBD3") == 0) - ICF8101Mode = 0x22; - else if (RIG->ICF8101 && strcmp(ptr, "USBD3") == 0) - ICF8101Mode = 0x23; - else - continue; - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - continue; - - } - else if (strcmp(ptr, "PTT_SETS_FREQ") == 0) - { - // Send Select Soundcard as mod source with PTT commands - - RIG->PTTSetsFreq = TRUE; - ptr = strtok_s(NULL, " \t\n\r", &Context); - - continue; - - } - - else if (strcmp(ptr, "DATAPTT") == 0) - { - // Send Select Soundcard as mod source with PTT commands - - DataPTT = TRUE; - } - - else if (memcmp(ptr, "PTTONHEX=", 9) == 0) - { - // Hex String to use for PTT on - - char * ptr1 = ptr; - char * ptr2 = onString ; - int i, j, len; - - ptr1 += 9; - onLen = len = strlen(ptr1) / 2; - - if (len < 240) - { - while ((len--) > 0) - { - i = *(ptr1++); - i -= '0'; - if (i > 9) - i -= 7; - - j = i << 4; - - i = *(ptr1++); - i -= '0'; - if (i > 9) - i -= 7; - - *(ptr2++) = j | i; - } - } - - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL) - break; - } - - else if (memcmp(ptr, "PTTOFFHEX=", 10) == 0) - { - // Hex String to use for PTT off - - char * ptr2 = offString ; - int i, j, len; - - ptr += 10; - offLen = len = strlen(ptr) / 2; - - if (len < 240) - { - while ((len--) > 0) - { - i = *(ptr++); - i -= '0'; - if (i > 9) - i -= 7; - - j = i << 4; - - i = *(ptr++); - i -= '0'; - if (i > 9) - i -= 7; - - *(ptr2++) = j | i; - } - } - ptr = strtok_s(NULL, " \t\n\r", &Context); - - if (ptr == NULL) - break; - - } - - else if (memcmp(ptr, "HAMLIB=", 7) == 0) - { - // HAMLIB Emulator - param is port to listen on - - RIG->HAMLIBPORT = atoi(&ptr[7]); - } - - else if (memcmp(ptr, "TXOFFSET", 8) == 0) - { - RIG->txOffset = strtoll(&ptr[9], NULL, 10); - } - - else if (memcmp(ptr, "RXOFFSET", 8) == 0) - { - RIG->rxOffset = strtoll(&ptr[9], NULL, 10); - } - - else if (memcmp(ptr, "PTTOFFSET", 9) == 0) - { - RIG->pttOffset = strtoll(&ptr[10], NULL, 10); - } - - else if (memcmp(ptr, "RXERROR", 7) == 0) - { - RIG->rxError = atoi(&ptr[8]); - } - - else if (memcmp(ptr, "TXERROR", 7) == 0) - { - RIG->txError = atoi(&ptr[8]); - } - - else if (memcmp(ptr, "REPORTFREQS", 11) == 0) - { - RIG->reportFreqs = _strdup(&ptr[12]); - } - - else if (memcmp(ptr, "DEFAULTFREQ", 11) == 0) - { - RIG->defaultFreq = atoi(&ptr[12]); - } - - else if (atoi(ptr)) - break; // Not scan freq oe timeband, so see if another param - - ptr = strtok_s(NULL, " \t\n\r", &Context); - } - - if (PORT->PortType == PTT || PORT->PortType == ANT) - return RIG; - - // Set up PTT and Poll Strings - - if (PORT->PortType == ICOM) - { - char * Poll; - Poll = &RIG->PTTOn[0]; - - if (onLen && offLen) - { - memcpy(RIG->PTTOn, onString, onLen); - RIG->PTTOnLen = onLen; - memcpy(RIG->PTTOff, offString, offLen); - RIG->PTTOffLen = offLen; - } - - else if (RIG->ICF8101) - { - // Need to send ACC PTT command (1A 37 0002), not normal ICOM IC 00 - - if (PTTControlsInputMUX) - { - *(Poll++) = 0xFE; - *(Poll++) = 0xFE; - *(Poll++) = RIG->RigAddr; - *(Poll++) = 0xE0; - *(Poll++) = 0x1a; - *(Poll++) = 0x05; - *(Poll++) = ICF8101Mode; - *(Poll++) = 0x03; // USB Data Mode Source - *(Poll++) = 0x00; - *(Poll++) = 0x01; // Soundcard - *(Poll++) = 0xFD; - } - *(Poll++) = 0xFE; - *(Poll++) = 0xFE; - *(Poll++) = RIG->RigAddr; - *(Poll++) = 0xE0; - *(Poll++) = 0x1A; - *(Poll++) = 0x37; // Send/read the TX status - *(Poll++) = 0x00; - *(Poll++) = 0x02; // ACC PTT - *(Poll++) = 0xFD; - - RIG->PTTOnLen = (int)(Poll - &RIG->PTTOn[0]); - - Poll = &RIG->PTTOff[0]; - - *(Poll++) = 0xFE; - *(Poll++) = 0xFE; - *(Poll++) = RIG->RigAddr; - *(Poll++) = 0xE0; - *(Poll++) = 0x1A; - *(Poll++) = 0x37; // Send/read the TX status - *(Poll++) = 0x00; - *(Poll++) = 0x00; // RX - *(Poll++) = 0xFD; - - if (PTTControlsInputMUX) - { - *(Poll++) = 0xFE; - *(Poll++) = 0xFE; - *(Poll++) = RIG->RigAddr; - *(Poll++) = 0xE0; - *(Poll++) = 0x1a; - - *(Poll++) = 0x05; - *(Poll++) = ICF8101Mode; - *(Poll++) = 0x03; // USB Data Mode Source - *(Poll++) = 0x00; - *(Poll++) = 0x02; // ACC - *(Poll++) = 0xFD; - } - RIG->PTTOffLen = (int)(Poll - &RIG->PTTOff[0]); - } - else - { - if (PTTControlsInputMUX) - { - *(Poll++) = 0xFE; - *(Poll++) = 0xFE; - *(Poll++) = RIG->RigAddr; - *(Poll++) = 0xE0; - *(Poll++) = 0x1a; - - if (strcmp(RIG->RigName, "IC7100") == 0) - { - *(Poll++) = 0x05; - *(Poll++) = 0x00; - *(Poll++) = 0x91; // Data Mode Source - } - else if (strcmp(RIG->RigName, "IC7200") == 0) - { - *(Poll++) = 0x03; - *(Poll++) = 0x24; // Data Mode Source - } - else if (strcmp(RIG->RigName, "IC7300") == 0) - { - *(Poll++) = 0x05; - *(Poll++) = 0x00; - *(Poll++) = 0x67; // Data Mode Source - } - else if (strcmp(RIG->RigName, "IC7600") == 0) - { - *(Poll++) = 0x05; - *(Poll++) = 0x00; - *(Poll++) = 0x31; // Data1 Mode Source - } - else if (strcmp(RIG->RigName, "IC7610") == 0) - { - *(Poll++) = 0x05; - *(Poll++) = 0x00; - *(Poll++) = 0x92; // Data1 Mode Source - } - else if (strcmp(RIG->RigName, "IC7410") == 0) - { - *(Poll++) = 0x03; - *(Poll++) = 0x39; // Data Mode Source - } - - *(Poll++) = 0x03; // USB Soundcard - *(Poll++) = 0xFD; - } - - *(Poll++) = 0xFE; - *(Poll++) = 0xFE; - *(Poll++) = RIG->RigAddr; - *(Poll++) = 0xE0; - *(Poll++) = 0x1C; // RIG STATE - *(Poll++) = 0x00; // PTT - *(Poll++) = 1; // ON - *(Poll++) = 0xFD; - - RIG->PTTOnLen = (int)(Poll - &RIG->PTTOn[0]); - - Poll = &RIG->PTTOff[0]; - - *(Poll++) = 0xFE; - *(Poll++) = 0xFE; - *(Poll++) = RIG->RigAddr; - *(Poll++) = 0xE0; - *(Poll++) = 0x1C; // RIG STATE - *(Poll++) = 0x00; // PTT - *(Poll++) = 0; // OFF - *(Poll++) = 0xFD; - - if (PTTControlsInputMUX) - { - *(Poll++) = 0xFE; - *(Poll++) = 0xFE; - *(Poll++) = RIG->RigAddr; - *(Poll++) = 0xE0; - *(Poll++) = 0x1a; - - if (strcmp(RIG->RigName, "IC7100") == 0) - { - *(Poll++) = 0x05; - *(Poll++) = 0x00; - *(Poll++) = 0x91; // Data Mode Source - } - else if (strcmp(RIG->RigName, "IC7200") == 0) - { - *(Poll++) = 0x03; - *(Poll++) = 0x24; // Data Mode Source - } - else if (strcmp(RIG->RigName, "IC7300") == 0) - { - *(Poll++) = 0x05; - *(Poll++) = 0x00; - *(Poll++) = 0x67; // Data Mode Source - } - else if (strcmp(RIG->RigName, "IC7410") == 0) - { - *(Poll++) = 0x03; - *(Poll++) = 0x39; // Data Mode Source - } - else if (strcmp(RIG->RigName, "IC7600") == 0) - { - *(Poll++) = 0x05; - *(Poll++) = 0x00; - *(Poll++) = 0x31; // Data1 Mode Source - } - else if (strcmp(RIG->RigName, "IC7610") == 0) - { - *(Poll++) = 0x05; - *(Poll++) = 0x00; - *(Poll++) = 0x92; // Data1 Mode Source - } - - *(Poll++) = DataPTTOffMode; - *(Poll++) = 0xFD; - } - RIG->PTTOffLen = (int)(Poll - &RIG->PTTOff[0]); - } - } - else if (PORT->PortType == KENWOOD) - { - RIG->PollLen = 6; - strcpy(RIG->Poll, "FA;MD;"); - - if (PTTControlsInputMUX) - { - sprintf(RIG->PTTOn, "EX%03d00001;TX1;", RIG->TSMenu); // Select USB before PTT - sprintf(RIG->PTTOff, "RX;EX%03d00000;", RIG->TSMenu); // Select ACC after dropping PTT - } - else - { - strcpy(RIG->PTTOff, "RX;"); - - if (DataPTT) - strcpy(RIG->PTTOn, "TX1;"); - else - strcpy(RIG->PTTOn, "TX;"); - } - - RIG->PTTOnLen = (int)strlen(RIG->PTTOn); - RIG->PTTOffLen = (int)strlen(RIG->PTTOff); - - } - else if (PORT->PortType == FLEX) - { - RIG->PollLen = 10; - strcpy(RIG->Poll, "ZZFA;ZZMD;"); - - strcpy(RIG->PTTOn, "ZZTX1;"); - RIG->PTTOnLen = 6; - strcpy(RIG->PTTOff, "ZZTX0;"); - RIG->PTTOffLen = 6; - } - else if (PORT->PortType == FT2000) - { - RIG->PollLen = 6; - strcpy(RIG->Poll, "FA;MD;"); - - strcpy(RIG->PTTOn, "TX1;"); - RIG->PTTOnLen = 4; - strcpy(RIG->PTTOff, "TX0;"); - RIG->PTTOffLen = 4; - } - else if (PORT->PortType == FT991A) - { - RIG->PollLen = 7; - strcpy(RIG->Poll, "FA;MD0;"); - - if (PTTControlsInputMUX) - { - RIG->PTTOnLen = sprintf(RIG->PTTOn, "EX0721;TX1;"); // Select USB before PTT - RIG->PTTOffLen = sprintf(RIG->PTTOff, "TX0;EX0720;"); // Select DATA after dropping PTT - } - else - { - strcpy(RIG->PTTOn, "TX1;"); - RIG->PTTOnLen = 4; - strcpy(RIG->PTTOff, "TX0;"); - RIG->PTTOffLen = 4; - } - } - else if (PORT->PortType == NMEA) - { - int Len; - - i = sprintf(RIG->Poll, "$PICOA,90,%02x,RXF*xx\r\n", RIG->RigAddr); - AddNMEAChecksum(RIG->Poll); - Len = i; - i = sprintf(RIG->Poll + Len, "$PICOA,90,%02x,MODE*xx\r\n", RIG->RigAddr); - AddNMEAChecksum(RIG->Poll + Len); - RIG->PollLen = Len + i; - - i = sprintf(RIG->PTTOn, "$PICOA,90,%02x,TRX,TX*xx\r\n", RIG->RigAddr); - AddNMEAChecksum(RIG->PTTOn); - RIG->PTTOnLen = i; - - i = sprintf(RIG->PTTOff, "$PICOA,90,%02x,TRX,RX*xx\r\n", RIG->RigAddr); - AddNMEAChecksum(RIG->PTTOff); - RIG->PTTOffLen = i; - } - - if (ptr == NULL) return RIG; // No Scanning, just Interactive control - - if (strchr(ptr, ',') == 0 && strchr(ptr, ':') == 0) // Old Format - { - ScanFreq = atof(ptr); - -#pragma warning(push) -#pragma warning(disable : 4244) - - RIG->ScanFreq = ScanFreq * 10; - -#pragma warning(push) - - ptr = strtok_s(NULL, " \t\n\r", &Context); - } - - // Frequency List - -CheckScan: - - if (ptr) - if (ptr[0] == ';' || ptr[0] == '#') - ptr = NULL; - - if (ptr != NULL) - { - // Create Default Timeband - - struct TimeScan * Band; - - RIG->TimeBands = zalloc(sizeof(void *)); - - Band = AllocateTimeRec(RIG); - SaveBand = Band; - - Band->Start = 0; - Band->End = 84540; //23:59 - FreqPtr = Band->Scanlist = RIG->FreqPtr = malloc(1000); - memset(FreqPtr, 0, 1000); - } - - while(ptr) - { - int ModeNo; - BOOL Supress; - double Freq = 0.0; - int FreqInt = 0; - char FreqString[80]=""; - char * Modeptr = NULL; - char Split, Data, PacketMode, RPacketMode, PMinLevel, PMaxLevel, Filter; - char Mode[10] = ""; - char WinmorMode, Antenna; - char ARDOPMode[6] = ""; - char VARAMode[6] = ""; - char Appl[13]; - char * ApplCall; - int BandWidth; - int Power; - - if (ptr[0] == ';' || ptr[0] == '#') - break; - - Filter = PMinLevel = PMaxLevel = PacketMode = RPacketMode = Split = - Data = WinmorMode = Antenna = ModeNo = Supress = - MemoryBank = MemoryNumber = BandWidth = 0; - - Appl[0] = 0; - ARDOPMode[0] = 0; - VARAMode[0] = 0; - Dwell = 0.0; - - while (strchr(ptr, ':')) - { - // New TimeBand - - struct TimeScan * Band; - - Band = AllocateTimeRec(RIG); - - *FreqPtr = (struct ScanEntry *)0; // Terminate Last Band - - Band->Start = (atoi(ptr) * 3600) + (atoi(&ptr[3]) * 60); - Band->End = 84540; //23:59 - SaveBand->End = Band->Start - 60; - - SaveBand = Band; - - FreqPtr = Band->Scanlist = RIG->FreqPtr = malloc(1000); - memset(FreqPtr, 0, 1000); - - ptr = strtok_s(NULL, " \t\n\r", &Context); - } - - if (strchr(ptr, ',')) // New Format - { - DecodeModePtr(ptr, &Dwell, &Freq, Mode, &PMinLevel, &PMaxLevel, &PacketMode, - &RPacketMode, &Split, &Data, &WinmorMode, &Antenna, &Supress, &Filter, &Appl[0], - &MemoryBank, &MemoryNumber, ARDOPMode, VARAMode, &BandWidth, &Power); - } - else - { - Modeptr = strchr(ptr, '/'); - - if (Modeptr) - *Modeptr++ = 0; - - Freq = atof(ptr); - - if (Modeptr) - { - // Mode can include 1/2/3 for Icom Filers. W/N for Winmor/Pactor Bandwidth, and +/-/S for Repeater Shift (S = Simplex) - // First is always Mode - // First char is Mode (USB, LSB etc) - - Mode[0] = Modeptr[0]; - Filter = Modeptr[1]; - - if (strchr(&Modeptr[1], '+')) - Split = '+'; - else if (strchr(&Modeptr[1], '-')) - Split = '-'; - else if (strchr(&Modeptr[1], 'S')) - Split = 'S'; - else if (strchr(&Modeptr[1], 'D')) - Data = 1; - - if (strchr(&Modeptr[1], 'W')) - { - WinmorMode = 'W'; - PMaxLevel = '3'; - PMinLevel = '1'; - } - else if (strchr(&Modeptr[1], 'N')) - { - WinmorMode = 'N'; - PMaxLevel = '2'; - PMinLevel = '1'; - } - - if (strchr(&Modeptr[1], 'R')) // Robust Packet - RPacketMode = '2'; // R600 - else if (strchr(&Modeptr[1], 'H')) // HF Packet on Tracker - PacketMode = '1'; // 300 - - if (strchr(&Modeptr[1], 'X')) // Dont Report to WL2K - Supress = 1; - - if (strstr(&Modeptr[1], "A1")) - Antenna = '1'; - else if (strstr(&Modeptr[1], "A2")) - Antenna = '2'; - else if (strstr(&Modeptr[1], "A3")) - Antenna = '3'; - else if (strstr(&Modeptr[1], "A4")) - Antenna = '4'; - else if (strstr(&Modeptr[1], "A5")) - Antenna = '5'; - else if (strstr(&Modeptr[1], "A6")) - Antenna = '6'; - } - } - - switch(PORT->PortType) - { - case ICOM: - - for (ModeNo = 0; ModeNo < 24; ModeNo++) - { - if (strlen(Mode) == 1) - { - if (Modes[ModeNo][0] == Mode[0]) - break; - } - else - { - if (_stricmp(Modes[ModeNo], Mode) == 0) - break; - } - } - break; - - case YAESU: - - for (ModeNo = 0; ModeNo < 16; ModeNo++) - { - if (strlen(Mode) == 1) - { - if (YaesuModes[ModeNo][0] == Mode[0]) - break; - } - else - { - if (_stricmp(YaesuModes[ModeNo], Mode) == 0) - break; - } - } - break; - - case KENWOOD: - - for (ModeNo = 0; ModeNo < 8; ModeNo++) - { - if (strlen(Mode) == 1) - { - if (KenwoodModes[ModeNo][0] == Mode[0]) - break; - } - else - { - if (_stricmp(KenwoodModes[ModeNo], Mode) == 0) - break; - } - } - break; - - case FLEX: - - for (ModeNo = 0; ModeNo < 12; ModeNo++) - { - if (strlen(Mode) == 1) - { - if (FLEXModes[ModeNo][0] == Mode[0]) - break; - } - else - { - if (_stricmp(FLEXModes[ModeNo], Mode) == 0) - break; - } - } - break; - - case FT2000: - - if (Modeptr) - { - if (strstr(Modeptr, "PL")) - { - ModeNo = 8; - break; - } - if (strstr(Modeptr, "PU")) - { - ModeNo = 12; - break; - } - } - for (ModeNo = 0; ModeNo < 14; ModeNo++) - { - if (strlen(Mode) == 1) - { - if (FT2000Modes[ModeNo][0] == Mode[0]) - break; - } - else - { - if (_stricmp(FT2000Modes[ModeNo], Mode) == 0) - break; - } - } - break; - - case FT991A: - -/* if (Modeptr) - { - if (strstr(Modeptr, "PL")) - { - ModeNo = 8; - break; - } - if (strstr(Modeptr, "PU")) - { - ModeNo = 12; - break; - } - } -*/ - for (ModeNo = 0; ModeNo < 15; ModeNo++) - { - if (strlen(Mode) == 1) - { - if (FT991AModes[ModeNo][0] == Mode[0]) - break; - } - else - { - if (_stricmp(FT991AModes[ModeNo], Mode) == 0) - break; - } - } - break; - - - case FT100: - - for (ModeNo = 0; ModeNo < 8; ModeNo++) - { - if (strlen(Mode) == 1) - { - if (FT100Modes[ModeNo][0] == Mode[0]) - break; - } - else - { - if (_stricmp(FT100Modes[ModeNo], Mode) == 0) - break; - } - } - break; - - case FT990: - - for (ModeNo = 0; ModeNo < 12; ModeNo++) - { - if (strlen(Mode) == 1) - { - if (FT990Modes[ModeNo][0] == Mode[0]) - break; - } - else - { - if (_stricmp(FT990Modes[ModeNo], Mode) == 0) - break; - } - } - break; - - case FT1000: - - for (ModeNo = 0; ModeNo < 12; ModeNo++) - { - if (strlen(Mode) == 1) - { - if (FT1000Modes[ModeNo][0] == Mode[0]) - break; - } - else - { - if (_stricmp(FT1000Modes[ModeNo], Mode) == 0) - break; - } - } - break; - } - - Freq = Freq * 1000000.0; - - sprintf(FreqString, "%09.0f", Freq); - - FreqInt = Freq; - - FreqPtr[0] = malloc(sizeof(struct ScanEntry)); - memset(FreqPtr[0], 0, sizeof(struct ScanEntry)); - -#pragma warning(push) -#pragma warning(disable : 4244) - - if (Dwell == 0.0) - FreqPtr[0]->Dwell = ScanFreq * 10; - else - FreqPtr[0]->Dwell = Dwell * 10; - -#pragma warning(pop) - - FreqPtr[0]->Freq = Freq; - FreqPtr[0]->Bandwidth = WinmorMode; - FreqPtr[0]->RPacketMode = RPacketMode; - FreqPtr[0]->HFPacketMode = PacketMode; - FreqPtr[0]->PMaxLevel = PMaxLevel; - FreqPtr[0]->PMinLevel = PMinLevel; - FreqPtr[0]->Antenna = Antenna; - strcpy(FreqPtr[0]->ARDOPMode, ARDOPMode); - FreqPtr[0]->VARAMode = VARAMode[0]; - - strcpy(FreqPtr[0]->APPL, Appl); - - ApplCall = GetApplCallFromName(Appl); - - if (strcmp(Appl, "NODE") == 0) - { - memcpy(FreqPtr[0]->APPLCALL, TNC->NodeCall, 9); - strlop(FreqPtr[0]->APPLCALL, ' '); - } - else - { - if (ApplCall && ApplCall[0] > 32) - { - memcpy(FreqPtr[0]->APPLCALL, ApplCall, 9); - strlop(FreqPtr[0]->APPLCALL, ' '); - } - } - - CmdPtr = FreqPtr[0]->Cmd1 = malloc(100); - - if (PORT->PortType == ICOM) - { - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - - if (RIG->ICF8101) - { - // Set Freq is 1A 35 and set Mode 1A 36 - - - *(CmdPtr++) = 0x1A; - *(CmdPtr++) = 0x35; // Set frequency command - - // Need to convert two chars to bcd digit - - *(CmdPtr++) = (FreqString[8] - 48) | ((FreqString[7] - 48) << 4); - *(CmdPtr++) = (FreqString[6] - 48) | ((FreqString[5] - 48) << 4); - *(CmdPtr++) = (FreqString[4] - 48) | ((FreqString[3] - 48) << 4); - *(CmdPtr++) = (FreqString[2] - 48) | ((FreqString[1] - 48) << 4); - *(CmdPtr++) = (FreqString[0] - 48); - *(CmdPtr++) = 0xFD; - FreqPtr[0]->Cmd1Len = 12; - - CmdPtr = FreqPtr[0]->Cmd2 = malloc(10); - FreqPtr[0]->Cmd2Len = 9; - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x1A; - *(CmdPtr++) = 0x36; // Set mode command - *(CmdPtr++) = 0; - if (ModeNo > 10) - *(CmdPtr++) = ModeNo + 6; - else - *(CmdPtr++) = ModeNo; - - *(CmdPtr++) = 0xFD; - } - else - { - if (MemoryNumber) - { - // Set Memory Channel instead of Freq, Mode, etc - - char ChanString[5]; - - // Send Set Memory, then Channel - - *(CmdPtr++) = 0x08; - *(CmdPtr++) = 0xFD; - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - - sprintf(ChanString, "%04d", MemoryNumber); - - *(CmdPtr++) = 0x08; - *(CmdPtr++) = (ChanString[1] - 48) | ((ChanString[0] - 48) << 4); - *(CmdPtr++) = (ChanString[3] - 48) | ((ChanString[2] - 48) << 4); - *(CmdPtr++) = 0xFD; - - FreqPtr[0]->Cmd1Len = 14; - - if (MemoryBank) - { - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x08; - *(CmdPtr++) = 0xA0; - *(CmdPtr++) = MemoryBank - 0x40; - *(CmdPtr++) = 0xFD; - - FreqPtr[0]->Cmd1Len += 8; - } - } - else - { - *(CmdPtr++) = 0x5; // Set frequency command - - // Need to convert two chars to bcd digit - - *(CmdPtr++) = (FreqString[8] - 48) | ((FreqString[7] - 48) << 4); - *(CmdPtr++) = (FreqString[6] - 48) | ((FreqString[5] - 48) << 4); - *(CmdPtr++) = (FreqString[4] - 48) | ((FreqString[3] - 48) << 4); - *(CmdPtr++) = (FreqString[2] - 48) | ((FreqString[1] - 48) << 4); - if (RIG->IC735) - { - *(CmdPtr++) = 0xFD; - FreqPtr[0]->Cmd1Len = 10; - } - else - { - *(CmdPtr++) = (FreqString[0] - 48); - *(CmdPtr++) = 0xFD; - FreqPtr[0]->Cmd1Len = 11; - } - - // Send Set VFO in case last chan was memory - - // *(CmdPtr++) = 0xFE; - // *(CmdPtr++) = 0xFE; - // *(CmdPtr++) = RIG->RigAddr; - // *(CmdPtr++) = 0xE0; - - // *(CmdPtr++) = 0x07; - // *(CmdPtr++) = 0xFD; - - // FreqPtr[0]->Cmd1Len = 17; - - if (Filter) - { - CmdPtr = FreqPtr[0]->Cmd2 = malloc(10); - FreqPtr[0]->Cmd2Len = 8; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x6; // Set Mode - *(CmdPtr++) = ModeNo; - *(CmdPtr++) = Filter - '0'; //Filter - *(CmdPtr++) = 0xFD; - - if (Split) - { - CmdPtr = FreqPtr[0]->Cmd3 = malloc(10); - FreqPtr[0]->Cmd3Len = 7; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0xF; // Set Mode - if (Split == 'S') - *(CmdPtr++) = 0x10; - else - if (Split == '+') - *(CmdPtr++) = 0x12; - else - if (Split == '-') - *(CmdPtr++) = 0x11; - - *(CmdPtr++) = 0xFD; - } - else - { - if (Data) - { - CmdPtr = FreqPtr[0]->Cmd3 = malloc(10); - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x1a; - - - if ((strcmp(RIG->RigName, "IC7100") == 0) || - (strcmp(RIG->RigName, "IC7410") == 0) || - (strcmp(RIG->RigName, "IC7600") == 0) || - (strcmp(RIG->RigName, "IC7610") == 0) || - (strcmp(RIG->RigName, "IC7300") == 0)) - { - FreqPtr[0]->Cmd3Len = 9; - *(CmdPtr++) = 0x6; // Send/read DATA mode with filter set - *(CmdPtr++) = 0x1; // Data On - *(CmdPtr++) = Filter - '0'; //Filter - } - else if (strcmp(RIG->RigName, "IC7200") == 0) - { - FreqPtr[0]->Cmd3Len = 9; - *(CmdPtr++) = 0x4; // Send/read DATA mode with filter set - *(CmdPtr++) = 0x1; // Data On - *(CmdPtr++) = Filter - '0'; //Filter - } - else - { - FreqPtr[0]->Cmd3Len = 8; - *(CmdPtr++) = 0x6; // Set Data - *(CmdPtr++) = 0x1; //On - } - - *(CmdPtr++) = 0xFD; - } - } - } - - if (Antenna == '5' || Antenna == '6') - { - // Antenna select for 746 and maybe others - - // Could be going in cmd2 3 or 4 - - if (FreqPtr[0]->Cmd2 == NULL) - { - CmdPtr = FreqPtr[0]->Cmd2 = malloc(10); - FreqPtr[0]->Cmd2Len = 7; - } - else if (FreqPtr[0]->Cmd3 == NULL) - { - CmdPtr = FreqPtr[0]->Cmd3 = malloc(10); - FreqPtr[0]->Cmd3Len = 7; - } - else - { - CmdPtr = FreqPtr[0]->Cmd4 = malloc(10); - FreqPtr[0]->Cmd4Len = 7; - } - - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = 0xFE; - *(CmdPtr++) = RIG->RigAddr; - *(CmdPtr++) = 0xE0; - *(CmdPtr++) = 0x12; // Set Antenna - *(CmdPtr++) = Antenna - '5'; // 0 for A5 1 for A6 - *(CmdPtr++) = 0xFD; - } - } - } - } - else if (PORT->PortType == YAESU) - { - //Send Mode first - changing mode can change freq - - *(CmdPtr++) = ModeNo; - *(CmdPtr++) = 0; - *(CmdPtr++) = 0; - *(CmdPtr++) = 0; - *(CmdPtr++) = 7; - - *(CmdPtr++) = (FreqString[1] - 48) | ((FreqString[0] - 48) << 4); - *(CmdPtr++) = (FreqString[3] - 48) | ((FreqString[2] - 48) << 4); - *(CmdPtr++) = (FreqString[5] - 48) | ((FreqString[4] - 48) << 4); - *(CmdPtr++) = (FreqString[7] - 48) | ((FreqString[6] - 48) << 4); - *(CmdPtr++) = 1; - - // FT847 Needs a Poll Here. Set up anyway, but only send if 847 - - *(CmdPtr++) = 0; - *(CmdPtr++) = 0; - *(CmdPtr++) = 0; - *(CmdPtr++) = 0; - *(CmdPtr++) = 3; - - - } - else if (PORT->PortType == KENWOOD) - { - if (Power == 0) - { - if (Antenna == '5' || Antenna == '6') - FreqPtr[0]->Cmd1Len = sprintf(CmdPtr, "FA00%s;MD%d;AN%c;FA;MD;", FreqString, ModeNo, Antenna - 4); - else - FreqPtr[0]->Cmd1Len = sprintf(CmdPtr, "FA00%s;MD%d;FA;MD;", FreqString, ModeNo); - } - else - { - if (Antenna == '5' || Antenna == '6') - FreqPtr[0]->Cmd1Len = sprintf(CmdPtr, "FA00%s;MD%d;AN%c;PC%03d;FA;MD;PC;", FreqString, ModeNo, Antenna - 4, Power); - else - FreqPtr[0]->Cmd1Len = sprintf(CmdPtr, "FA00%s;MD%d;PC%03d;FA;MD;PC;", FreqString, ModeNo, Power); - } - } - else if (PORT->PortType == FLEX) - { - FreqPtr[0]->Cmd1Len = sprintf(CmdPtr, "ZZFA00%s;ZZMD%02d;ZZFA;ZZMD;", FreqString, ModeNo); - } - else if (PORT->PortType == FT2000) - { - FreqPtr[0]->Cmd1Len = sprintf(CmdPtr, "FA%s;MD0%X;FA;MD;", &FreqString[1], ModeNo); - } - else if (PORT->PortType == FT991A) - { - FreqPtr[0]->Cmd1Len = sprintf(CmdPtr, "FA%s;MD0%X;FA;MD0;", &FreqString, ModeNo); - } - else if (PORT->PortType == FT100 || PORT->PortType == FT990 - || PORT->PortType == FT1000) - { - // Allow Mode = "LEAVE" to suppress mode change - - //Send Mode first - changing mode can change freq - - if (strcmp(Mode, "LEAVE") == 0) - { - // we can't easily change the string length, - // so just set freq twice - - *(CmdPtr++) = (FreqString[7] - 48) | ((FreqString[6] - 48) << 4); - *(CmdPtr++) = (FreqString[5] - 48) | ((FreqString[4] - 48) << 4); - *(CmdPtr++) = (FreqString[3] - 48) | ((FreqString[2] - 48) << 4); - *(CmdPtr++) = (FreqString[1] - 48) | ((FreqString[0] - 48) << 4); - *(CmdPtr++) = 10; - } - else - { - *(CmdPtr++) = 0; - *(CmdPtr++) = 0; - *(CmdPtr++) = 0; - *(CmdPtr++) = ModeNo; - *(CmdPtr++) = 12; - } - - *(CmdPtr++) = (FreqString[7] - 48) | ((FreqString[6] - 48) << 4); - *(CmdPtr++) = (FreqString[5] - 48) | ((FreqString[4] - 48) << 4); - *(CmdPtr++) = (FreqString[3] - 48) | ((FreqString[2] - 48) << 4); - *(CmdPtr++) = (FreqString[1] - 48) | ((FreqString[0] - 48) << 4); - *(CmdPtr++) = 10; - - // Send Get Status, as these types doesn't ack commands - - *(CmdPtr++) = 0; - *(CmdPtr++) = 0; - *(CmdPtr++) = 0; - - if (PORT->PortType == FT990 || PORT->YaesuVariant == FT1000D) - *(CmdPtr++) = 3; - else - *(CmdPtr++) = 2; // F100 or FT1000MP - - *(CmdPtr++) = 16; // Get Status - } - else if (PORT->PortType == NMEA) - { - int Len; - - i = sprintf(CmdPtr, "$PICOA,90,%02x,RXF,%.6f*xx\r\n", RIG->RigAddr, Freq/1000000.); - AddNMEAChecksum(CmdPtr); - Len = i; - i = sprintf(CmdPtr + Len, "$PICOA,90,%02x,TXF,%.6f*xx\r\n", RIG->RigAddr, Freq/1000000.); - AddNMEAChecksum(CmdPtr + Len); - Len += i; - i = sprintf(CmdPtr + Len, "$PICOA,90,%02x,MODE,%s*xx\r\n", RIG->RigAddr, Mode); - AddNMEAChecksum(CmdPtr + Len); - FreqPtr[0]->Cmd1Len = Len + i; - - i = sprintf(RIG->Poll, "$PICOA,90,%02x,RXF*xx\r\n", RIG->RigAddr); - AddNMEAChecksum(RIG->Poll); - Len = i; - i = sprintf(RIG->Poll + Len, "$PICOA,90,%02x,MODE*xx\r\n", RIG->RigAddr); - AddNMEAChecksum(RIG->Poll + Len); - RIG->PollLen = Len + i; - } - else if (PORT->PortType == HAMLIB) - { - FreqPtr[0]->Cmd1Len = sprintf(CmdPtr, "F %s\n+f\nM %s %d\n+m\n", FreqString, Mode, BandWidth); - } - - else if (PORT->PortType == FLRIG) - { - sprintf(FreqPtr[0]->Cmd1Msg, "%.0f", Freq); - sprintf(FreqPtr[0]->Cmd2Msg, "%s", Mode); - sprintf(FreqPtr[0]->Cmd3Msg, "%d", BandWidth); - } - - else if (PORT->PortType == RTLUDP) - { - int FM = 0; - int AM = 1; - int USB = 2; - int LSB = 3; - - CmdPtr[0] = 0; - memcpy(&CmdPtr[1], &FreqInt, 4); - - CmdPtr[1] = FreqInt & 0xff; - CmdPtr[2] = (FreqInt >> 8) & 0xff; - CmdPtr[3] = (FreqInt >> 16) & 0xff; - CmdPtr[4] = (FreqInt >> 24) & 0xff; - - FreqPtr[0]->Cmd1Len = 5; - - if (Mode[0]) - { - CmdPtr[5] = 1; - FreqPtr[0]->Cmd1Len = 10; - - if (strcmp(Mode, "FM") == 0) - memcpy(&CmdPtr[6], &FM, 4); - else if (strcmp(Mode, "AM") == 0) - memcpy(&CmdPtr[6], &AM, 4); - else if (strcmp(Mode, "USB") == 0) - memcpy(&CmdPtr[6], &USB, 4); - else if (strcmp(Mode, "LSB") == 0) - memcpy(&CmdPtr[6], &LSB, 4); - } - - } - - FreqPtr++; - - RIG->ScanCounter = 20; - - ptr = strtok_s(NULL, " \t\n\r", &Context); // Next Freq - } - - - - if (RIG->NumberofBands) - { - CheckTimeBands(RIG); // Set initial FreqPtr; - PORT->FreqPtr = RIG->FreqPtr[0]; - } - - return RIG; -} - -VOID SetupScanInterLockGroups(struct RIGINFO *RIG) -{ - struct PORTCONTROL * PortRecord; - struct TNCINFO * TNC; - int port; - int Interlock = RIG->Interlock; - char PortString[128] = ""; - char TxPortString[128] = ""; - - // Find TNC ports in this Rig's scan group - - for (port = 1; port < 33; port++) - { - TNC = TNCInfo[port]; - - if (TNC == NULL) - continue; - - PortRecord = &TNC->PortRecord->PORTCONTROL; - - if (TNC->RXRadio == Interlock) - { - int p = PortRecord->PORTNUMBER; - RIG->BPQPort |= (1 << p); - sprintf(PortString, "%s,%d", PortString, p); - TNC->RIG = RIG; - - if (RIG->PTTMode == 0 && TNC->PTTMode) - RIG->PTTMode = TNC->PTTMode; - } - if (TNC->TXRadio == Interlock && TNC->TXRadio != TNC->RXRadio) - { - int p = PortRecord->PORTNUMBER; - RIG->BPQPort |= (1 << p); - sprintf(TxPortString, "%s,%d", TxPortString, p); - TNC->TXRIG = RIG; - - if (RIG->PTTMode == 0 && TNC->PTTMode) - RIG->PTTMode = TNC->PTTMode; - } - } - - if (RIG->PTTMode == 0 && (RIG->PTTCATPort[0] || RIG->HAMLIBPORT)) // PTT Mux Implies CAT - RIG->PTTMode = PTTCI_V; - - if (PortString[0] && TxPortString[0]) // Have both - sprintf(RIG->WEB_PORTS, "Rx: %s Tx: %s", &PortString[1], &TxPortString[1]); - else if (PortString[0]) - strcpy(RIG->WEB_PORTS, &PortString[1]); - else if (TxPortString[0]) - sprintf(RIG->WEB_PORTS, "Tx: %s", &TxPortString[1]); - - SetWindowText(RIG->hPORTS, RIG->WEB_PORTS); -} - -VOID SetupPortRIGPointers() -{ - struct TNCINFO * TNC; - int port; - - for (port = 1; port < 33; port++) - { - TNC = TNCInfo[port]; - - if (TNC == NULL) - continue; - - if (TNC->RIG == NULL) - TNC->RIG = &TNC->DummyRig; // Not using Rig control, so use Dummy - } -} - -#ifdef WIN32 - -VOID PTTCATThread(struct RIGINFO *RIG) -{ - DWORD dwLength = 0; - int Length, ret, i; - UCHAR * ptr1; - UCHAR * ptr2; - UCHAR c; - UCHAR Block[4][80]; - UCHAR CurrentState[4] = {0}; -#define RTS 2 -#define DTR 4 - HANDLE Event; - HANDLE Handle[4]; - DWORD EvtMask[4]; - OVERLAPPED Overlapped[4]; - char Port[32]; - int PIndex = 0; - int HIndex = 0; - int rc; - - EndPTTCATThread = FALSE; - - while (PIndex < 4 && RIG->PTTCATPort[PIndex][0]) - { - RIG->RealMux[HIndex] = 0; - - sprintf(Port, "\\\\.\\pipe\\BPQCOM%s", RIG->PTTCATPort[PIndex]); - - Handle[HIndex] = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - - if (Handle[HIndex] == (HANDLE) -1) - { - int Err = GetLastError(); - Consoleprintf("PTTMUX port BPQCOM%s Open failed code %d - trying real com port", RIG->PTTCATPort[PIndex], Err); - - // See if real com port - - sprintf(Port, "\\\\.\\\\COM%s", RIG->PTTCATPort[PIndex]); - - Handle[HIndex] = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - - RIG->RealMux[HIndex] = 1; - - if (Handle[HIndex] == (HANDLE) -1) - { - int Err = GetLastError(); - Consoleprintf("PTTMUX port COM%s Open failed code %d", RIG->PTTCATPort[PIndex], Err); - } - else - { - rc = SetCommMask(Handle[HIndex], EV_CTS | EV_DSR); // Request notifications - HIndex++; - } - } - else - HIndex++; - - PIndex++; - - } - - if (PIndex == 0) - return; // No ports - - Event = CreateEvent(NULL, TRUE, FALSE, NULL); - - for (i = 0; i < HIndex; i ++) - { - memset(&Overlapped[i], 0, sizeof(OVERLAPPED)); - Overlapped[i].hEvent = Event; - - if (RIG->RealMux[i]) - { - // Request Interface change notifications - - rc = WaitCommEvent(Handle[i], &EvtMask[i], &Overlapped[i]); - rc = GetLastError(); - - } - else - { - - // Prime a read on each handle - - ReadFile(Handle[i], Block[i], 80, &Length, &Overlapped[i]); - } - } - - while (EndPTTCATThread == FALSE) - { - -WaitAgain: - - ret = WaitForSingleObject(Event, 1000); - - if (ret == WAIT_TIMEOUT) - { - if (EndPTTCATThread) - { - for (i = 0; i < HIndex; i ++) - { - CancelIo(Handle[i]); - CloseHandle(Handle[i]); - Handle[i] = INVALID_HANDLE_VALUE; - } - CloseHandle(Event); - return; - } - goto WaitAgain; - } - - ResetEvent(Event); - - // See which request(s) have completed - - for (i = 0; i < HIndex; i ++) - { - ret = GetOverlappedResult(Handle[i], &Overlapped[i], &Length, FALSE); - - if (ret) - { - if (RIG->RealMux[i]) - { - // Request Interface change notifications - - DWORD Mask; - - GetCommModemStatus(Handle[i], &Mask); - - if (Mask & MS_CTS_ON) - Rig_PTTEx(RIG, TRUE, RIG->PTTCATTNC[i]); - else - Rig_PTTEx(RIG, FALSE, RIG->PTTCATTNC[i]); - - memset(&Overlapped[i], 0, sizeof(OVERLAPPED)); - Overlapped[i].hEvent = Event; - WaitCommEvent(Handle[i], &EvtMask[i], &Overlapped[i]); - - } - else - { - - ptr1 = Block[i]; - ptr2 = Block[i]; - - while (Length > 0) - { - c = *(ptr1++); - - Length--; - - if (c == 0xff) - { - c = *(ptr1++); - Length--; - - if (c == 0xff) // ff ff means ff - { - Length--; - } - else - { - // This is connection / RTS/DTR statua from other end - // Convert to CAT Command - - if (c == CurrentState[i]) - continue; - - if (c & RTS) - Rig_PTTEx(RIG, TRUE, RIG->PTTCATTNC[i]); - else - Rig_PTTEx(RIG, FALSE, RIG->PTTCATTNC[i]); - - CurrentState[i] = c; - continue; - } - } - } - - memset(&Overlapped[i], 0, sizeof(OVERLAPPED)); - Overlapped[i].hEvent = Event; - - ReadFile(Handle[i], Block[i], 80, &Length, &Overlapped[i]); - } - } - } - } - EndPTTCATThread = FALSE; -} - -/* - memset(&Overlapped, 0, sizeof(Overlapped)); - Overlapped.hEvent = Event; - ResetEvent(Event); - - ret = ReadFile(Handle, Block, 80, &Length, &Overlapped); - - if (ret == 0) - { - ret = GetLastError(); - - if (ret != ERROR_IO_PENDING) - { - if (ret == ERROR_BROKEN_PIPE || ret == ERROR_INVALID_HANDLE) - { - CloseHandle(Handle); - RIG->PTTCATHandles[0] = INVALID_HANDLE_VALUE; - return; - } - } - } -*/ -#endif - -// HAMLIB Support Code - -VOID HAMLIBPoll(struct RIGPORTINFO * PORT) -{ - UCHAR * Poll = PORT->TXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on HAMLIB - char cmd[80]; - int len; - - if (RIG->ScanStopped == 0) - if (RIG->ScanCounter) - RIG->ScanCounter--; - - if (PORT->Timeout) - { - PORT->Timeout--; - - if (PORT->Timeout) // Still waiting - return; - - SetWindowText(RIG->hFREQ, "------------------"); - SetWindowText(RIG->hMODE, "----------"); - strcpy(RIG->WEB_FREQ, "-----------");; - strcpy(RIG->WEB_MODE, "------"); - - RIG->RIGOK = FALSE; - return; - } - - // Send Data if avail, else send poll - - if (RIG->NumberofBands && RIG->RIGOK && (RIG->ScanStopped == 0)) - { - if (RIG->ScanCounter <= 0) - { - // Send Next Freq - - if (GetPermissionToChange(PORT, RIG)) - { - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); - - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd1, PORT->FreqPtr->Cmd1Len); - PORT->TXLen = PORT->FreqPtr->Cmd1Len; - - _gcvt(PORT->FreqPtr->Freq / 1000000.0, 9, RIG->Valchar); // For MH - - send(PORT->remoteSock, PORT->TXBuffer, PORT->TXLen, 0); - PORT->CmdSent = 1; - PORT->Retries = 0; - PORT->Timeout = 0; - PORT->AutoPoll = TRUE; - - // There isn't a response to a set command, so clear Scan Lock here - - ReleasePermission(RIG); // Release Perrmission - return; - } - } - } - - if (RIG->PollCounter) - { - RIG->PollCounter--; - if (RIG->PollCounter > 1) - return; - } - - if (RIG->RIGOK && (RIG->ScanStopped == 0) && RIG->NumberofBands) - return; // no point in reading freq if we are about to change it - - RIG->PollCounter = 10; // Once Per Sec - - // Read Frequency - - len = sprintf(cmd, "+f\n+m\n"); - - send(PORT->remoteSock, cmd, len, 0); - - PORT->Timeout = 10; - PORT->CmdSent = 0; - - PORT->AutoPoll = TRUE; - - return; -} - - -void HAMLIBProcessMessage(struct RIGPORTINFO * PORT) -{ - // Called from Background thread - - int InputLen = recv(PORT->remoteSock, &PORT->RXBuffer[PORT->RXLen], 500 - PORT->RXLen, 0); - - if (InputLen == 0 || InputLen == SOCKET_ERROR) - { - if (PORT->remoteSock) - closesocket(PORT->remoteSock); - - PORT->remoteSock = 0; - - PORT->CONNECTED = FALSE; - PORT->hDevice = 0; - return; - } - - PORT->RXLen += InputLen; -} - -void FLRIGProcessMessage(struct RIGPORTINFO * PORT) -{ - // Called from Background thread - - int InputLen = recv(PORT->remoteSock, &PORT->RXBuffer[PORT->RXLen], 500 - PORT->RXLen, 0); - - if (InputLen == 0 || InputLen == SOCKET_ERROR) - { - if (PORT->remoteSock) - closesocket(PORT->remoteSock); - - PORT->remoteSock = 0; - - PORT->CONNECTED = FALSE; - PORT->hDevice = 0; - return; - } - - PORT->RXLen += InputLen; - ProcessFLRIGFrame(PORT); -} - -void ProcessHAMLIBFrame(struct RIGPORTINFO * PORT, int Length) -{ - char * msg = PORT->RXBuffer; - char * rest; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on Yaseu - msg[Length] = 0; - - PORT->Timeout = 0; - RIG->RIGOK = 1; - - // extract lines from input - - while (msg && msg[0]) - { - rest = strlop(msg, 10); - - if (memcmp(msg, "Frequency:", 10) == 0) - { - RIG->RigFreq = atof(&msg[11]) / 1000000.0; - - _gcvt(RIG->RigFreq, 9, RIG->Valchar); - - sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - } - - else if (memcmp(msg, "Mode:", 5) == 0) - { - if (strlen(&msg[6]) < 15) - strcpy(RIG->ModeString, &msg[6]); - } - - else if (memcmp(msg, "Passband:", 9) == 0) - { - RIG->Passband = atoi(&msg[10]); - sprintf(RIG->WEB_MODE, "%s/%d", RIG->ModeString, RIG->Passband); - SetWindowText(RIG->hMODE, RIG->WEB_MODE); - } - - msg = rest; - } -} - - -void ProcessFLRIGFrame(struct RIGPORTINFO * PORT) -{ - char * msg; - int Length; - - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one - char * ptr1, * ptr2, * val; - int Len, TotalLen; - char cmd[80]; - char ReqBuf[256]; - char SendBuff[256]; - - while (PORT->RXLen > 0) - { - int b1 = 0, b2 = 0; - - msg = PORT->RXBuffer; - Length = PORT->RXLen; - - msg[Length] = 0; - ptr1 = strstr(msg, "Content-length:"); - - if (ptr1 == NULL) - return; - - Len = atoi(&ptr1[15]); - ptr2 = strstr(ptr1, "\r\n\r\n"); - if (ptr2) - { - TotalLen = ptr2 +4 + Len - msg; - - if (TotalLen > Length) // Don't have it all - return; - } - else - return; - - val = strstr(ptr2, ""); - - if (val) - { - val += 7; - - RIG->RIGOK = 1; - PORT->RXLen -= TotalLen; - - memmove(PORT->RXBuffer, &PORT->RXBuffer[TotalLen], PORT->RXLen); - - // It is quite difficult to corrolate responses with commands, but we only poll for freq, mode and bandwidth - // and the responses can be easily identified - - if (strstr(val, "") || memcmp(val, "", 8) == 0) - { - // Reply to set command - may need to send next in set or use to send OK if interactive - - if (PORT->ScanEntry.Cmd2Msg[0]) - { - sprintf(cmd, "%s", PORT->ScanEntry.Cmd2Msg); - FLRIGSendCommand(PORT, "rig.set_mode", cmd); - PORT->ScanEntry.Cmd2Msg[0] = 0; - } - - else if (PORT->ScanEntry.Cmd3Msg[0] && strcmp(PORT->ScanEntry.Cmd3Msg, "0") != 0) - { - sprintf(cmd, "%s", PORT->ScanEntry.Cmd3Msg); - FLRIGSendCommand(PORT, "rig.set_bandwidth", cmd); - PORT->ScanEntry.Cmd3Msg[0] = 0; - } - - else if (!PORT->AutoPoll) - { - GetSemaphore(&Semaphore, 61); - SendResponse(RIG->Session, "Set OK"); - FreeSemaphore(&Semaphore); - PORT->AutoPoll = 1; // So we dond send another - } - } - else if(strstr(val, "")) - { - // Reply to get BW - - char * p1, * p2; - - p1 = strstr(val, ""); - - if (p1) - { - p1 += 7; - b1 = atoi(p1); - - p2 = strstr(p1, ""); - - if (p2) - { - p2 +=7; - b2 = atoi(p2); - } - } - - if (b1) - { - if (b2) - sprintf(RIG->WEB_MODE, "%s/%d:%d", RIG->ModeString, b1, b2); - else - sprintf(RIG->WEB_MODE, "%s/%d", RIG->ModeString, b1); - - MySetWindowText(RIG->hMODE, RIG->WEB_MODE); - } - } - else - { - // Either freq or mode. See if numeric - - double freq; - - strlop(val, '<'); - - freq = atof(val) / 1000000.0; - - if (freq > 0.0) - { - RIG->RigFreq = freq; - _gcvt(RIG->RigFreq, 9, RIG->Valchar); - - sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); - MySetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - - // Read Mode - - Len = sprintf(ReqBuf, Req, "rig.get_mode", ""); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - send(PORT->remoteSock, SendBuff, Len, 0); - - } - else - { - if (strlen(val)> 1) - { - strcpy(RIG->ModeString, val); - - if (b1) - { - if (b2) - sprintf(RIG->WEB_MODE, "%s/%d:%d", RIG->ModeString, b1, b2); - else - sprintf(RIG->WEB_MODE, "%s/%d", RIG->ModeString, b1); - } - else - SetWindowText(RIG->hMODE, RIG->WEB_MODE); - - MySetWindowText(RIG->hMODE, RIG->WEB_MODE); - - Len = sprintf(ReqBuf, Req, "rig.get_bw", ""); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - - send(PORT->remoteSock, SendBuff, Len, 0); - } - } - } - - - - // We now send all setting commands at once - - /* - - - if (memcmp(PORT->TXBuffer, "rig.set_vfo", 11) == 0) - { - // Set Freq - Send Set Mode if needed - - if (PORT->ScanEntry.Cmd2Msg[0]) - { - sprintf(cmd, "%s", PORT->ScanEntry.Cmd2Msg); - FLRIGSendCommand(PORT, "rig.set_mode", cmd); - if (strcmp(PORT->ScanEntry.Cmd3Msg, "0") != 0) - { - sprintf(cmd, "%s", PORT->ScanEntry.Cmd3Msg); - FLRIGSendCommand(PORT, "rig.set_bandwidth", cmd); - } - strcpy(RIG->ModeString, PORT->ScanEntry.Cmd2Msg); - } - else - { - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Set Freq OK"); - - strcpy(PORT->TXBuffer, "rig.get_vfo"); - Len = sprintf(ReqBuf, Req, "rig.get_vfo", ""); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - strcpy(PORT->TXBuffer, "rig.get_bw"); - Len = sprintf(ReqBuf, Req, "rig.get_bw", ""); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - - send(PORT->remoteSock, SendBuff, Len, 0); - } - continue; - } - - if (memcmp(PORT->TXBuffer, "rig.set_mode", 11) == 0) - { - strcpy(PORT->TXBuffer, "rig.get_vfo"); - Len = sprintf(ReqBuf, Req, "rig.get_vfo", ""); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - - send(PORT->remoteSock, SendBuff, Len, 0); - - if (!PORT->AutoPoll) - SendResponse(RIG->Session, "Set Freq and Mode OK"); - - continue; - } - - if (memcmp(PORT->TXBuffer, "rig.get_vfo", 11) == 0) - { - RIG->RigFreq = atof(val) / 1000000.0; - - _gcvt(RIG->RigFreq, 9, RIG->Valchar); - - sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); - MySetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - - strcpy(PORT->TXBuffer, "rig.get_mode"); - Len = sprintf(ReqBuf, Req, "rig.get_mode", ""); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - send(PORT->remoteSock, SendBuff, Len, 0); - - Len = sprintf(ReqBuf, Req, "rig.get_bw", ""); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - send(PORT->remoteSock, SendBuff, Len, 0); - continue; - } - - if (memcmp(PORT->TXBuffer, "rig.get_mode", 11) == 0) - { - strlop(val, '<'); - sprintf(RIG->WEB_MODE, "%s", val); - MySetWindowText(RIG->hMODE, RIG->WEB_MODE); - } - } - - */ - } - - PORT->Timeout = 0; - } - - /* - POST /RPC2 HTTP/1.1 - User-Agent: XMLRPC++ 0.8 - Host: 127.0.0.1:12345 - Content-type: text/xml - Content-length: 89 - - - rig.get_vfoA - - HTTP/1.1 200 OK - Server: XMLRPC++ 0.8 - Content-Type: text/xml - Content-length: 118 - - - - 14070000 - - */ - - -} - - - - - -void HLSetMode(SOCKET Sock, struct RIGINFO * RIG, unsigned char * Msg, char sep) -{ - char Resp[80]; - int Len; - char mode[80] = ""; - int filter = 0; - int n = sscanf(&Msg[1], "%s %d", mode, &filter); - - // Send to RIGCommand. Can't set Mode without Freq so need to use current - - // ?? Should be try to convert bandwidth to filter ?? - - RIG->Passband = filter; - - if (RIG->PORT->PortType == ICOM) // Needs a Filter - sprintf(Resp, "%d %s %s 1\n", 0, RIG->Valchar, mode); - else - sprintf(Resp, "%d %s %s\n", 0, RIG->Valchar, mode); - - GetSemaphore(&Semaphore, 60); - Rig_CommandEx(RIG->PORT, RIG, -1, Resp); - FreeSemaphore(&Semaphore); - - if (sep) - Len = sprintf(Resp, "set_mode: %s %d%cRPRT 0\n", mode, filter, sep); - else - Len = sprintf(Resp, "RPRT 0\n"); - - send(Sock, Resp, Len, 0); -} - - -void HLSetFreq(SOCKET Sock, struct RIGINFO * RIG, unsigned char * Msg, char sep) -{ - char Resp[80]; - int Len; - int freq = atoi(&Msg[1]); - - // Send to RIGCommand - - sprintf(Resp, "%d %f\n", 0, freq/1000000.0); - GetSemaphore(&Semaphore, 60); - Rig_CommandEx(RIG->PORT, RIG, -1, Resp); - FreeSemaphore(&Semaphore); - - if (sep) - Len = sprintf(Resp, "set_freq: %d%cRPRT 0\n", freq, sep); - else - Len = sprintf(Resp, "RPRT 0\n"); - - send(Sock, Resp, Len, 0); -} - - -void HLGetPTT(SOCKET Sock, struct RIGINFO * RIG, char sep) -{ - char Resp[80]; - int Len; - int ptt = 0; - - if (RIG->PTTTimer) - ptt = 1; - - if (sep) - Len = sprintf(Resp, "get_ptt:%cPTT: %d%cRPRT 0\n", sep, ptt, sep); - else - Len = sprintf(Resp, "%d\n", ptt); - - send(Sock, Resp, Len, 0); -} - -void HLSetPTT(SOCKET Sock, struct RIGINFO * RIG, unsigned char * Msg, char sep) -{ - char Resp[80]; - int Len; - int ptt = atoi(&Msg[1]); - - if (ptt) - Rig_PTTEx(RIG, 1, NULL); - else - Rig_PTTEx(RIG, 0, NULL); - - if (sep) - Len = sprintf(Resp, "set_ptt: %d%cRPRT 0\n", ptt, sep); - else - Len = sprintf(Resp, "RPRT 0\n"); - - send(Sock, Resp, Len, 0); -} - -void HLGetMode(SOCKET Sock, struct RIGINFO * RIG, char sep) -{ - char Resp[80]; - int Len; - - if (sep) - Len = sprintf(Resp, "get_mode:%cMode: %s%cPassband: %d%cRPRT 0\n", sep, RIG->ModeString, sep, RIG->Passband, sep); - else - Len = sprintf(Resp, "%s\n%d\n", RIG->ModeString, RIG->Passband); - - send(Sock, Resp, Len, 0); - -} - -void HLGetFreq(SOCKET Sock, struct RIGINFO * RIG, char sep) -{ - char Resp[80]; - int Len; - char freqval[64]; - double freq = atof(RIG->Valchar) * 1000000.0; - - sprintf(freqval, "%f", freq); - strlop(freqval, '.'); - - if (sep) - Len = sprintf(Resp, "get_freq:%cFrequency: %s%cRPRT 0\n", sep, freqval, sep); - else - Len = sprintf(Resp, "%s\n", freqval); - - send(Sock, Resp, Len, 0); -} - -void HLGetVFO(SOCKET Sock, struct RIGINFO * RIG, char sep) -{ - char Resp[80]; - int Len; - - if (sep) - Len = sprintf(Resp, "get_vfo:%s%cRPRT 0\n", "VFOA", sep); - else - Len = sprintf(Resp, "%s\n", "VFOA"); - - send(Sock, Resp, Len, 0); -} - -void HLGetSplit(SOCKET Sock, struct RIGINFO * RIG, char sep) -{ - char Resp[80]; - int Len; - - if (sep) - Len = sprintf(Resp, "get_vfo:%s%cRPRT 0\n", "VFOA", sep); - else - Len = sprintf(Resp, "0\n%s\n", "VFOA"); - - send(Sock, Resp, Len, 0); - -} - - - -int ProcessHAMLIBSlaveMessage(SOCKET Sock, struct RIGINFO * RIG, unsigned char * Msg, int MsgLen) -{ - // We only process a pretty small subset of rigctl messages - - // commands are generally a single character, upper case for set - // and lower case for get. If preceeded by + ; | or , response will - // be in extended form. + adds an LF between field, other values the - // supplied char is used as seperator. - - // At the moments we support freq (F) mode (m) and PTT (T) - - char sep = 0; - - if (Msg[0] == '#') - return 0; // Comment - - strlop(Msg, 13); - strlop(Msg, 10); - - // \ on front is used for long mode. Hopefully not used much - - // WSJT seems ro need \chk_vfo and \dump_state - - if (Msg[0] == '\\') - { - if (strcmp(&Msg[1], "chk_vfo") == 0) - { - char Reply[80]; - int Len = sprintf(Reply, "CHKVFO 0\n"); - send(Sock, Reply, Len, 0); - return 0; - } - - if (strcmp(&Msg[1], "dump_state") == 0) - { - char Reply[4096]; - int Len = sprintf(Reply, - "0\n" - "1\n" - "2\n" - "150000.000000 1500000000.000000 0x1ff -1 -1 0x10000003 0x3\n" - "0 0 0 0 0 0 0\n" - "0 0 0 0 0 0 0\n" - "0x1ff 1\n" - "0x1ff 0\n" - "0 0\n" - "0x1e 2400\n" - "0x2 500\n" - "0x1 8000\n" - "0x1 2400\n" - "0x20 15000\n" - "0x20 8000\n" - "0x40 230000\n" - "0 0\n" - "9990\n" - "9990\n" - "10000\n" - "0\n" - "10 \n" - "10 20 30 \n" - "0xffffffff\n" - "0xffffffff\n" - "0xf7ffffff\n" - "0x83ffffff\n" - "0xffffffff\n" - "0xffffffbf\n"); - - send(Sock, Reply, Len, 0); - return 0; - } - } - - if (Msg[0] == 'q' || Msg[0] == 'Q') - { - // close connection - - return 1; - } - - if (Msg[0] == '+') - { - sep = 10; - Msg++; - MsgLen --; - } - else if (Msg[0] == '_' || Msg[0] == '?') - { - } - else if (ispunct(Msg[0])) - { - sep = Msg[0]; - Msg++; - MsgLen --; - } - - switch (Msg[0]) - { - case 'f': // Get Freqency - - HLGetFreq(Sock, RIG, sep); - return 0; - - case 'm': // Get Mode - - HLGetMode(Sock, RIG, sep); - return 0; - - case 't': // Get PTT - - HLGetPTT(Sock, RIG, sep); - return 0; - - case 'v': // Get VFO - - HLGetVFO(Sock, RIG, sep); - return 0; - - case 's': // Get Split - - HLGetSplit(Sock, RIG, sep); - return 0; - - case 'F': - - HLSetFreq(Sock, RIG, Msg, sep); - return 0; - - case 'M': - - HLSetMode(Sock, RIG, Msg, sep); - return 0; - - case 'T': - - HLSetPTT(Sock, RIG, Msg, sep); - return 0; - } - return 0; -} - -int DecodeHAMLIBAddr(struct RIGPORTINFO * PORT, char * ptr) -{ - // Param is IPADDR:PORT. Only Allow numeric addresses - - struct sockaddr_in * destaddr = (SOCKADDR_IN *)&PORT->remoteDest; - - char * port = strlop(ptr, ':'); - - if (port == NULL) - return 0; - - destaddr->sin_family = AF_INET; - destaddr->sin_addr.s_addr = inet_addr(ptr); - destaddr->sin_port = htons(atoi(port)); - - return 1; -} - -VOID HAMLIBThread(struct RIGPORTINFO * PORT); - -VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT) -{ - if (HAMLIBMasterRunning) - _beginthread(HAMLIBThread, 0, (void *)PORT); - - return ; -} - -VOID HAMLIBThread(struct RIGPORTINFO * PORT) -{ - // Opens sockets and looks for data - - char Msg[255]; - int err, i, ret; - u_long param=1; - BOOL bcopt=TRUE; - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - - if (PORT->remoteSock) - { - closesocket(PORT->remoteSock); - } - - PORT->remoteSock = 0; - PORT->remoteSock = socket(AF_INET,SOCK_STREAM,0); - - if (PORT->remoteSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for HAMLIB socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - PORT->CONNECTING = FALSE; - return; - } - - setsockopt(PORT->remoteSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(PORT->remoteSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - if (connect(PORT->remoteSock,(LPSOCKADDR) &PORT->remoteDest,sizeof(PORT->remoteDest)) == 0) - { - // - // Connected successful - // - - ioctl(PORT->remoteSock, FIONBIO, ¶m); - } - else - { - if (PORT->Alerted == FALSE) - { - struct sockaddr_in * destaddr = (SOCKADDR_IN * )&PORT->remoteDest; - - err = WSAGetLastError(); - - sprintf(Msg, "Connect Failed for HAMLIB socket - error code = %d Addr %s\r\n", err, PORT->IOBASE); - - WritetoConsole(Msg); - PORT->Alerted = TRUE; - } - - closesocket(PORT->remoteSock); - - PORT->remoteSock = 0; - PORT->CONNECTING = FALSE; - return; - } - - PORT->CONNECTED = TRUE; - PORT->hDevice = (HANDLE)1; // simplifies check code - - PORT->Alerted = TRUE; - - while (PORT->CONNECTED) - { - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - FD_SET(PORT->remoteSock,&readfs); - FD_SET(PORT->remoteSock,&errorfs); - - timeout.tv_sec = 5; - timeout.tv_usec = 0; - - ret = select((int)PORT->remoteSock + 1, &readfs, NULL, &errorfs, &timeout); - - if (HAMLIBMasterRunning == 0) - return; - - if (ret == SOCKET_ERROR) - { - Debugprintf("HAMLIB Select failed %d ", WSAGetLastError()); - goto Lost; - } - - if (ret > 0) - { - // See what happened - - if (FD_ISSET(PORT->remoteSock, &readfs)) - { - HAMLIBProcessMessage(PORT); - } - - if (FD_ISSET(PORT->remoteSock, &errorfs)) - { -Lost: - sprintf(Msg, "HAMLIB Connection lost for Addr %s\r\n", PORT->IOBASE); - WritetoConsole(Msg); - - PORT->CONNECTED = FALSE; - PORT->Alerted = FALSE; - PORT->hDevice = 0; // simplifies check code - - closesocket(PORT->remoteSock); - PORT->remoteSock = 0; - return; - } - - - continue; - } - else - { - } - } - sprintf(Msg, "HAMLIB Thread Terminated Addr %s\r\n", PORT->IOBASE); - WritetoConsole(Msg); -} - - - -void HAMLIBSlaveThread(struct RIGINFO * RIG) -{ - // Wait for connections and messages from HAMLIB Clients - - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - int ret; - unsigned int maxsock; - - HAMLIBSlaveRunning = 1; - - Consoleprintf("HAMLIB Slave Thread %d Running", RIG->HAMLIBPORT); - - while (HAMLIBSlaveRunning) - { - struct HAMLIBSOCK * Entry = RIG->Sockets; - struct HAMLIBSOCK * Prev; - - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - FD_SET(RIG->ListenSocket, &readfs); - FD_SET(RIG->ListenSocket, &errorfs); - - maxsock = RIG->ListenSocket; - - while (Entry && HAMLIBSlaveRunning) - { - FD_SET(Entry->Sock, &readfs); - FD_SET(Entry->Sock, &errorfs); - - if (Entry->Sock > maxsock) - maxsock = Entry->Sock; - - Entry = Entry->Next; - } - - timeout.tv_sec = 5; - timeout.tv_usec = 0; - - ret = select(maxsock + 1, &readfs, NULL, &errorfs, &timeout); - - if (HAMLIBSlaveRunning == 0) - return; - - if (ret == -1) - { - perror("listen select"); - continue; - } - - if (ret) - { - if (FD_ISSET(RIG->ListenSocket, &readfs)) - { - // Connection. Accept it and create a socket enty - - int addrlen = sizeof(struct sockaddr_in6); - struct sockaddr_in6 sin6; - struct HAMLIBSOCK * Entry = zalloc(sizeof(struct HAMLIBSOCK)); - - Entry->Sock = accept(RIG->ListenSocket, (struct sockaddr *)&sin6, &addrlen); - - if (RIG->Sockets) - Entry->Next = RIG->Sockets; - - RIG->Sockets = Entry; - } - - // See if any Data Sockets - - Entry = RIG->Sockets; - Prev = 0; - - while (Entry) - { - unsigned char MsgBuf[256]; - unsigned char * Msg = MsgBuf; - int MsgLen; - - if (FD_ISSET(Entry->Sock, &readfs)) - { - MsgLen = recv(Entry->Sock, Msg, 256, 0); - - if (MsgLen <= 0) - { - // Closed - close socket and remove from chain - - closesocket(Entry->Sock); - - if (Prev == 0) - RIG->Sockets = Entry->Next; - else - Prev->Next = Entry->Next; - - free (Entry); - break; - } - else - { - // Could have multiple messages in packet - // Terminator can be CR LF or CRLF - - char * ptr; - int Len; - - Msg[MsgLen] = 0; -Loop: - ptr = strlop(Msg, 10); - if (ptr == NULL) - strlop(Msg, 13); - - Len = strlen(Msg); - - if (ProcessHAMLIBSlaveMessage(Entry->Sock, RIG, Msg, Len) == 1) - { - // close request - - closesocket(Entry->Sock); - - if (Prev == 0) - RIG->Sockets = Entry->Next; - else - Prev->Next = Entry->Next; - - free (Entry); - break; - } - Msg = ptr; - - if (Msg) - { - while (Msg[0] == 10 || Msg[0] == 13) - Msg++; - - if (Msg[0]) - goto Loop; - } - } - } - - if (FD_ISSET(Entry->Sock, &errorfs)) - { - // Closed - close socket and remove from chai - - closesocket(Entry->Sock); - - if (Prev == 0) - RIG->Sockets = Entry->Next; - else - Prev->Next = Entry->Next; - - free (Entry); - break; - } - - // Check Next Client - - Prev = Entry; - Entry = Entry->Next; - } - } - } - Consoleprintf("HAMLIB Slave Thread %d Exited", RIG->HAMLIBPORT); -} - - -VOID FLRIGPoll(struct RIGPORTINFO * PORT) -{ - UCHAR * Poll = PORT->TXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; - int Len; - char ReqBuf[256]; - char SendBuff[256]; - - if (RIG->ScanStopped == 0) - if (RIG->ScanCounter) - RIG->ScanCounter--; - - if (PORT->Timeout) - { - PORT->Timeout--; - - if (PORT->Timeout) // Still waiting - return; - - SetWindowText(RIG->hFREQ, "------------------"); - SetWindowText(RIG->hMODE, "----------"); - strcpy(RIG->WEB_FREQ, "-----------");; - strcpy(RIG->WEB_MODE, "------"); - - RIG->RIGOK = FALSE; - return; - } - - // Send Data if avail, else send poll - - if (RIG->NumberofBands && RIG->RIGOK && (RIG->ScanStopped == 0)) - { - if (RIG->ScanCounter <= 0) - { - // Send Next Freq - - if (GetPermissionToChange(PORT, RIG)) - { - char cmd[80]; - double freq; - - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); - - _gcvt(PORT->FreqPtr->Freq / 1000000.0, 9, RIG->Valchar); // For MH - - // Send the Set Freq here, send set mode when we get a response - - memcpy(&PORT->ScanEntry, PORT->FreqPtr, sizeof(struct ScanEntry)); - - sprintf(cmd, "%s", PORT->FreqPtr->Cmd1Msg); - FLRIGSendCommand(PORT, "rig.set_vfo", cmd); - - // Update display as we don't get a response - - freq = atof(PORT->FreqPtr->Cmd1Msg) / 1000000.0; - - if (freq > 0.0) - { - RIG->RigFreq = freq; - _gcvt(RIG->RigFreq, 9, RIG->Valchar); - - sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); - MySetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - } - - - PORT->CmdSent = 1; - PORT->Retries = 0; - PORT->Timeout = 10; - PORT->AutoPoll = TRUE; - - // There isn't a response to a set command, so clear Scan Lock here - - ReleasePermission(RIG); // Release Perrmission - return; - } - } - } - - if (RIG->PollCounter) - { - RIG->PollCounter--; - if (RIG->PollCounter > 1) - return; - } - - if (RIG->RIGOK && (RIG->ScanStopped == 0) && RIG->NumberofBands) - return; // no point in reading freq if we are about to change it - - RIG->PollCounter = 10; // Once Per Sec - - // Read Frequency - - strcpy(Poll, "rig.get_vfo"); - - Len = sprintf(ReqBuf, Req, Poll, ""); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - - if (PORT->CONNECTED) - { - if (send(PORT->remoteSock, SendBuff, Len, 0) != Len) - { - if (PORT->remoteSock) - closesocket(PORT->remoteSock); - - PORT->remoteSock = 0; - PORT->CONNECTED = FALSE; - PORT->hDevice = 0; - return; - } - } - - PORT->Timeout = 10; - PORT->CmdSent = 0; - - PORT->AutoPoll = TRUE; - - return; -} - -VOID FLRIGSendCommand(struct RIGPORTINFO * PORT, char * Command, char * Value) -{ - int Len; - char ReqBuf[512]; - char SendBuff[512]; - char ValueString[256] =""; - - if (!PORT->CONNECTED) - return; - - sprintf(ValueString, "%s", Value); - - strcpy(PORT->TXBuffer, Command); - Len = sprintf(ReqBuf, Req, PORT->TXBuffer, ValueString); - Len = sprintf(SendBuff, MsgHddr, Len, ReqBuf); - if (send(PORT->remoteSock, SendBuff, Len, 0) != Len) - { - if (PORT->remoteSock) - closesocket(PORT->remoteSock); - - PORT->remoteSock = 0; - PORT->CONNECTED = FALSE; - PORT->hDevice = 0; - } - - return; -} - - - -VOID FLRIGThread(struct RIGPORTINFO * PORT); - -VOID ConnecttoFLRIG(struct RIGPORTINFO * PORT) -{ - if (FLRIGRunning) - _beginthread(FLRIGThread, 0, (void *)PORT); - return ; -} - -VOID FLRIGThread(struct RIGPORTINFO * PORT) -{ - // Opens sockets and looks for data - - char Msg[255]; - int err, i, ret; - u_long param=1; - BOOL bcopt=TRUE; - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - - if (PORT->remoteSock) - { - closesocket(PORT->remoteSock); - } - - PORT->remoteSock = 0; - PORT->remoteSock = socket(AF_INET,SOCK_STREAM,0); - - if (PORT->remoteSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for FLRIG socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - PORT->CONNECTING = FALSE; - return; - } - - setsockopt(PORT->remoteSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(PORT->remoteSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - if (connect(PORT->remoteSock,(LPSOCKADDR) &PORT->remoteDest,sizeof(PORT->remoteDest)) == 0) - { - // - // Connected successful - // - - ioctl(PORT->remoteSock, FIONBIO, ¶m); - } - else - { - if (PORT->Alerted == FALSE) - { - struct sockaddr_in * destaddr = (SOCKADDR_IN * )&PORT->remoteDest; - - err = WSAGetLastError(); - - sprintf(Msg, "Connect Failed for FLRIG socket - error code = %d Port %d\r\n", - err, htons(destaddr->sin_port)); - - WritetoConsole(Msg); - PORT->Alerted = TRUE; - } - - closesocket(PORT->remoteSock); - - PORT->remoteSock = 0; - PORT->CONNECTING = FALSE; - return; - } - - PORT->CONNECTED = TRUE; - PORT->hDevice = (HANDLE)1; // simplifies check code - - PORT->Alerted = TRUE; - - while (PORT->CONNECTED && FLRIGRunning) - { - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - FD_SET(PORT->remoteSock,&readfs); - FD_SET(PORT->remoteSock,&errorfs); - - timeout.tv_sec = 5; - timeout.tv_usec = 0; - - ret = select((int)PORT->remoteSock + 1, &readfs, NULL, &errorfs, &timeout); - - if (FLRIGRunning == 0) - return; - - if (ret == SOCKET_ERROR) - { - Debugprintf("FLRIG Select failed %d ", WSAGetLastError()); - goto Lost; - } - - if (ret > 0) - { - // See what happened - - if (FD_ISSET(PORT->remoteSock, &readfs)) - { - FLRIGProcessMessage(PORT); - } - - if (FD_ISSET(PORT->remoteSock, &errorfs)) - { -Lost: - sprintf(Msg, "FLRIG Connection lost for Port %s\r\n", PORT->IOBASE); - WritetoConsole(Msg); - - PORT->CONNECTED = FALSE; - PORT->Alerted = FALSE; - PORT->hDevice = 0; // simplifies check code - - closesocket(PORT->remoteSock); - PORT->remoteSock = 0; - return; - } - continue; - } - else - { - } - } - sprintf(Msg, "FLRIG Thread Terminated Port %s\r\n", PORT->IOBASE); - WritetoConsole(Msg); -} - - - - -// HID Support Code - -int HID_Read_Block(struct RIGPORTINFO * PORT) -{ - int Len; - unsigned char Msg[65] = ""; - - if (PORT->RXLen > 400) - PORT->RXLen = 0; - - // Don't try to read more than 64 - -#ifdef WIN32 - Len = rawhid_recv(0, Msg, 64, 100); -#else - Len = read(PORT->hDevice, Msg, 64); -#endif - - if (Len <= 0) - return 0; - - // First byte is actual length - - Len = Msg[0]; - - if (Len > 0) - { - if (Len < 64) // Max in HID Packet - { - memcpy(&PORT->RXBuffer[PORT->RXLen], Msg + 1, Len); - return Len; - } - } - return 0; -} - -void rawhid_close(int num); - -BOOL HID_Write_Block(struct RIGPORTINFO * PORT) -{ - int n = PORT->TXLen; - UCHAR * ptr = PORT->TXBuffer; - UCHAR Msg[64] = ""; - int ret, i; - - while (n) - { - i = n; - if (i > 63) - i = 63; - - Msg[0] = i; // Length on front - memcpy(&Msg[1], ptr, i); - ptr += i; - n -= i; - // n = hid_write(PORT->hDevice, PORT->TXBuffer, PORT->TXLen); -#ifdef WIN32 - ret = rawhid_send(0, Msg, 64, 100); // Always send 64 - - if (ret < 0) - { - Debugprintf("Rigcontrol HID Write Failed %d", errno); - rawhid_close(0); - PORT->hDevice = NULL; - return FALSE; - } -#else - ret = write(PORT->hDevice, Msg, 64); - - if (ret != 64) - { - printf ("Write to %s failed, n=%d, errno=%d\n", PORT->HIDDevice, ret, errno); - close (PORT->hDevice); - PORT->hDevice = 0; - return FALSE; - } - -// printf("HID Write %d\n", i); -#endif - } - return TRUE; -} - - -BOOL OpenHIDPort(struct RIGPORTINFO * PORT, VOID * Port, int Speed) -{ -#ifdef WIN32 - - if (PORT->HIDDevice== NULL) - return FALSE; - - PORT->hDevice = rawhid_open(PORT->HIDDevice); - - if (PORT->hDevice) - Debugprintf("Rigcontrol HID Device %s opened", PORT->HIDDevice); - - /* - handle = hid_open_path(PORT->HIDDevice); - - if (handle) - hid_set_nonblocking(handle, 1); - - PORT->hDevice = handle; - */ -#else - int fd; - unsigned int param = 1; - - if (PORT->HIDDevice== NULL) - return FALSE; - - fd = open (PORT->HIDDevice, O_RDWR); - - if (fd == -1) - { - printf ("Could not open %s, errno=%d\n", PORT->HIDDevice, errno); - return FALSE; - } - - ioctl(fd, FIONBIO, ¶m); - printf("Rigcontrol HID Device %s opened", PORT->HIDDevice); - - PORT->hDevice = fd; -#endif - if (PORT->hDevice == 0) - return (FALSE); - - return TRUE; -} - - -void CM108_set_ptt(struct RIGINFO *RIG, int PTTState) -{ - char io[5]; - hid_device *handle; - int n; - - io[0] = 0; - io[1] = 0; - io[2] = 1 << (3 - 1); - io[3] = PTTState << (3 - 1); - io[4] = 0; - - if (RIG->CM108Device == NULL) - return; - -#ifdef WIN32 - handle = hid_open_path(RIG->CM108Device); - - if (!handle) { - printf("unable to open device\n"); - return; - } - - n = hid_write(handle, io, 5); - if (n < 0) - { - Debugprintf("Unable to write()\n"); - Debugprintf("Error: %ls\n", hid_error(RIG->PORT->hDevice)); - } - - hid_close(handle); - -#else - - int fd; - - fd = open (RIG->CM108Device, O_WRONLY); - - if (fd == -1) - { - printf ("Could not open %s for write, errno=%d\n", RIG->CM108Device, errno); - return; - } - - io[0] = 0; - io[1] = 0; - io[2] = 1 << (3 - 1); - io[3] = PTTState << (3 - 1); - io[4] = 0; - - n = write (fd, io, 5); - if (n != 5) - { - printf ("Write to %s failed, n=%d, errno=%d\n", RIG->CM108Device, n, errno); - } - - close (fd); -#endif - return; - -} - -/* -int CRow; - -HANDLE hComPort, hSpeed, hRigType, hButton, hAddr, hLabel, hTimes, hFreqs, hBPQPort; - -VOID CreateRigConfigLine(HWND hDlg, struct RIGPORTINFO * PORT, struct RIGINFO * RIG) -{ - char Port[10]; - - hButton = CreateWindow(WC_BUTTON , "", WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_TABSTOP, - 10, CRow+5, 10,10, hDlg, NULL, hInstance, NULL); - - if (PORT->PortType == ICOM) - { - char Addr[10]; - - sprintf(Addr, "%X", RIG->RigAddr); - - hAddr = CreateWindow(WC_EDIT , Addr, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER, - 305, CRow, 30,20, hDlg, NULL, hInstance, NULL); - - } - hLabel = CreateWindow(WC_EDIT , RIG->RigName, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER, - 340, CRow, 60,20, hDlg, NULL, hInstance, NULL); - - sprintf(Port, "%d", RIG->PortRecord->PORTCONTROL.PORTNUMBER); - hBPQPort = CreateWindow(WC_EDIT , Port, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL, - 405, CRow, 20, 20, hDlg, NULL, hInstance, NULL); - - hTimes = CreateWindow(WC_COMBOBOX , "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | - WS_VSCROLL | WS_TABSTOP, - 430, CRow, 100,80, hDlg, NULL, hInstance, NULL); - - hFreqs = CreateWindow(WC_EDIT , RIG->FreqText, WS_CHILD | WS_VISIBLE| WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL, - 535, CRow, 300, 20, hDlg, NULL, hInstance, NULL); - - SendMessage(hTimes, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "0000:1159"); - SendMessage(hTimes, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "1200:2359"); - SendMessage(hTimes, CB_SETCURSEL, 0, 0); - - CRow += 30; - -} - -VOID CreatePortConfigLine(HWND hDlg, struct RIGPORTINFO * PORT) -{ - char Port[20]; - int i; - - hComPort = CreateWindow(WC_COMBOBOX , "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | - WS_VSCROLL | WS_TABSTOP, - 30, CRow, 90, 160, hDlg, NULL, hInstance, NULL); - - for (i = 1; i < 256; i++) - { - sprintf(Port, "COM%d", i); - SendMessage(hComPort, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) Port); - } - - sprintf(Port, "COM%d", PORT->IOBASE); - - i = SendMessage(hComPort, CB_FINDSTRINGEXACT, 0,(LPARAM) Port); - - SendMessage(hComPort, CB_SETCURSEL, i, 0); - - - hSpeed = CreateWindow(WC_COMBOBOX , "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | - WS_VSCROLL | WS_TABSTOP, - 120, CRow, 75, 80, hDlg, NULL, hInstance, NULL); - - SendMessage(hSpeed, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "1200"); - SendMessage(hSpeed, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "2400"); - SendMessage(hSpeed, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "4800"); - SendMessage(hSpeed, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "9600"); - SendMessage(hSpeed, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "19200"); - SendMessage(hSpeed, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "38400"); - - sprintf(Port, "%d", PORT->SPEED); - - i = SendMessage(hSpeed, CB_FINDSTRINGEXACT, 0, (LPARAM)Port); - - SendMessage(hSpeed, CB_SETCURSEL, i, 0); - - hRigType = CreateWindow(WC_COMBOBOX , "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP, - 200, CRow, 100,80, hDlg, NULL, hInstance, NULL); - - SendMessage(hRigType, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "ICOM"); - SendMessage(hRigType, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "YAESU"); - SendMessage(hRigType, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) "KENWOOD"); - - SendMessage(hRigType, CB_SETCURSEL, PORT->PortType -1, 0); - -} - -INT_PTR CALLBACK ConfigDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - int Cmd = LOWORD(wParam); - - switch (message) - { - case WM_INITDIALOG: - { - struct RIGPORTINFO * PORT; - struct RIGINFO * RIG; - int i, p; - - CRow = 40; - - for (p = 0; p < NumberofPorts; p++) - { - PORT = PORTInfo[p]; - - CreatePortConfigLine(hDlg, PORT); - - for (i=0; i < PORT->ConfiguredRigs; i++) - { - RIG = &PORT->Rigs[i]; - CreateRigConfigLine(hDlg, PORT, RIG); - } - } - - - -// CreateWindow(WC_STATIC , "", WS_CHILD | WS_VISIBLE, -// 90, Row, 40,20, hDlg, NULL, hInstance, NULL); - -// CreateWindow(WC_STATIC , "", WS_CHILD | WS_VISIBLE, -// 135, Row, 100,20, hDlg, NULL, hInstance, NULL); - -return TRUE; - } - - case WM_SIZING: - { - return TRUE; - } - - case WM_ACTIVATE: - -// SendDlgItemMessage(hDlg, IDC_MESSAGE, EM_SETSEL, -1, 0); - - break; - - - case WM_COMMAND: - - if (Cmd == IDCANCEL) - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - - return (INT_PTR)TRUE; - - break; - } - return (INT_PTR)FALSE; -} - -*/ - -#ifdef WIN32 - -/* Simple Raw HID functions for Windows - for use with Teensy RawHID example - * http://www.pjrc.com/teensy/rawhid.html - * Copyright (c) 2009 PJRC.COM, LLC - * - * rawhid_open - open 1 or more devices - * rawhid_recv - receive a packet - * rawhid_send - send a packet - * rawhid_close - close a device - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above description, website URL and copyright notice and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * Version 1.0: Initial Release - */ - -#include -#include -//#include -//#include -#include -//#include -//#include - -typedef USHORT USAGE; - - -typedef struct _HIDD_CONFIGURATION { - PVOID cookie; - ULONG size; - ULONG RingBufferSize; -} HIDD_CONFIGURATION, *PHIDD_CONFIGURATION; - -typedef struct _HIDD_ATTRIBUTES { - ULONG Size; - USHORT VendorID; - USHORT ProductID; - USHORT VersionNumber; -} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; - - -typedef struct _HIDP_CAPS { - USAGE Usage; - USAGE UsagePage; - USHORT InputReportByteLength; - USHORT OutputReportByteLength; - USHORT FeatureReportByteLength; - USHORT Reserved[17]; - USHORT NumberLinkCollectionNodes; - USHORT NumberInputButtonCaps; - USHORT NumberInputValueCaps; - USHORT NumberInputDataIndices; - USHORT NumberOutputButtonCaps; - USHORT NumberOutputValueCaps; - USHORT NumberOutputDataIndices; - USHORT NumberFeatureButtonCaps; - USHORT NumberFeatureValueCaps; - USHORT NumberFeatureDataIndices; -} HIDP_CAPS, *PHIDP_CAPS; - - -typedef struct _HIDP_PREPARSED_DATA * PHIDP_PREPARSED_DATA; - - - -// a list of all opened HID devices, so the caller can -// simply refer to them by number -typedef struct hid_struct hid_t; -static hid_t *first_hid = NULL; -static hid_t *last_hid = NULL; -struct hid_struct { - HANDLE handle; - int open; - struct hid_struct *prev; - struct hid_struct *next; -}; -static HANDLE rx_event=NULL; -static HANDLE tx_event=NULL; -static CRITICAL_SECTION rx_mutex; -static CRITICAL_SECTION tx_mutex; - - -// private functions, not intended to be used from outside this file -static void add_hid(hid_t *h); -static hid_t * get_hid(int num); -static void free_all_hid(void); -void print_win32_err(void); - - - - -// rawhid_recv - receive a packet -// Inputs: -// num = device to receive from (zero based) -// buf = buffer to receive packet -// len = buffer's size -// timeout = time to wait, in milliseconds -// Output: -// number of bytes received, or -1 on error -// -int rawhid_recv(int num, void *buf, int len, int timeout) -{ - hid_t *hid; - unsigned char tmpbuf[516]; - OVERLAPPED ov; - DWORD r; - int n; - - if (sizeof(tmpbuf) < len + 1) return -1; - hid = get_hid(num); - if (!hid || !hid->open) return -1; - EnterCriticalSection(&rx_mutex); - ResetEvent(&rx_event); - memset(&ov, 0, sizeof(ov)); - ov.hEvent = rx_event; - if (!ReadFile(hid->handle, tmpbuf, len + 1, NULL, &ov)) { - if (GetLastError() != ERROR_IO_PENDING) goto return_error; - r = WaitForSingleObject(rx_event, timeout); - if (r == WAIT_TIMEOUT) goto return_timeout; - if (r != WAIT_OBJECT_0) goto return_error; - } - if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) goto return_error; - LeaveCriticalSection(&rx_mutex); - if (n <= 0) return -1; - n--; - if (n > len) n = len; - memcpy(buf, tmpbuf + 1, n); - return n; -return_timeout: - CancelIo(hid->handle); - LeaveCriticalSection(&rx_mutex); - return 0; -return_error: - print_win32_err(); - LeaveCriticalSection(&rx_mutex); - return -1; -} - -// rawhid_send - send a packet -// Inputs: -// num = device to transmit to (zero based) -// buf = buffer containing packet to send -// len = number of bytes to transmit -// timeout = time to wait, in milliseconds -// Output: -// number of bytes sent, or -1 on error -// -int rawhid_send(int num, void *buf, int len, int timeout) -{ - hid_t *hid; - unsigned char tmpbuf[516]; - OVERLAPPED ov; - DWORD n, r; - - if (sizeof(tmpbuf) < len + 1) return -1; - hid = get_hid(num); - if (!hid || !hid->open) return -1; - EnterCriticalSection(&tx_mutex); - ResetEvent(&tx_event); - memset(&ov, 0, sizeof(ov)); - ov.hEvent = tx_event; - tmpbuf[0] = 0; - memcpy(tmpbuf + 1, buf, len); - if (!WriteFile(hid->handle, tmpbuf, len + 1, NULL, &ov)) { - if (GetLastError() != ERROR_IO_PENDING) goto return_error; - r = WaitForSingleObject(tx_event, timeout); - if (r == WAIT_TIMEOUT) goto return_timeout; - if (r != WAIT_OBJECT_0) goto return_error; - } - if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) goto return_error; - LeaveCriticalSection(&tx_mutex); - if (n <= 0) return -1; - return n - 1; -return_timeout: - CancelIo(hid->handle); - LeaveCriticalSection(&tx_mutex); - return 0; -return_error: - print_win32_err(); - LeaveCriticalSection(&tx_mutex); - return -1; -} - -HANDLE rawhid_open(char * Device) -{ - DWORD index=0; - HANDLE h; - hid_t *hid; - int count=0; - - if (first_hid) free_all_hid(); - - if (!rx_event) - { - rx_event = CreateEvent(NULL, TRUE, TRUE, NULL); - tx_event = CreateEvent(NULL, TRUE, TRUE, NULL); - InitializeCriticalSection(&rx_mutex); - InitializeCriticalSection(&tx_mutex); - } - h = CreateFile(Device, GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - - if (h == INVALID_HANDLE_VALUE) - return 0; - - hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); - if (!hid) - { - CloseHandle(h); - return 0; - } - hid->handle = h; - hid->open = 1; - add_hid(hid); - - return h; -} - - -// rawhid_close - close a device -// -// Inputs: -// num = device to close (zero based) -// Output -// (nothing) -// -void rawhid_close(int num) -{ - hid_t *hid; - - hid = get_hid(num); - if (!hid || !hid->open) return; - - CloseHandle(hid->handle); - hid->handle = NULL; - hid->open = FALSE; -} - - - - -static void add_hid(hid_t *h) -{ - if (!first_hid || !last_hid) { - first_hid = last_hid = h; - h->next = h->prev = NULL; - return; - } - last_hid->next = h; - h->prev = last_hid; - h->next = NULL; - last_hid = h; -} - - -static hid_t * get_hid(int num) -{ - hid_t *p; - for (p = first_hid; p && num > 0; p = p->next, num--) ; - return p; -} - - -static void free_all_hid(void) -{ - hid_t *p, *q; - - for (p = first_hid; p; p = p->next) - { - CloseHandle(p->handle); - p->handle = NULL; - p->open = FALSE; - } - p = first_hid; - while (p) { - q = p; - p = p->next; - free(q); - } - first_hid = last_hid = NULL; -} - - - -void print_win32_err(void) -{ - char buf[256]; - DWORD err; - - err = GetLastError(); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, - 0, buf, sizeof(buf), NULL); - Debugprintf("err %ld: %s\n", err, buf); -} - -#endif - -// RTL_SDR support code - -char RTLModes[5][6] = {"FM", "AM", "USB", "LSB", "????"}; - - -void CheckAndProcessRTLUDP(struct RIGPORTINFO * PORT) -{ - int Length; - struct sockaddr_in rxaddr; - int addrlen = sizeof(struct sockaddr_in); - int Freq; - unsigned char RXBuffer[16]; - - struct RIGINFO * RIG = &PORT->Rigs[0]; - - Length = recvfrom(PORT->remoteSock, RXBuffer, 16, 0, (struct sockaddr *)&rxaddr, &addrlen); - - if (Length == 6) - { - long long MHz, Hz; - char CharMHz[16] = ""; - char CharHz[16] = ""; - int i; - int Mode; - - PORT->Timeout = 0; - RIG->RIGOK = TRUE; - - Freq = (RXBuffer[4] << 24) + (RXBuffer[3] << 16) + (RXBuffer[2] << 8) + RXBuffer[1]; - Mode = RXBuffer[5]; - - Freq += RIG->rxOffset; - - RIG->RigFreq = Freq / 1000000.0; - - // If we convert to float to display we get rounding errors, so convert to MHz and Hz to display - - MHz = Freq / 1000000; - - Hz = Freq - MHz * 1000000; - - sprintf(CharMHz, "%lld", MHz); - sprintf(CharHz, "%06lld", Hz); - - for (i = 5; i > 2; i--) - { - if (CharHz[i] == '0') - CharHz[i] = 0; - else - break; - } - - sprintf(RIG->WEB_FREQ,"%lld.%s", MHz, CharHz); - SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); - strcpy(RIG->Valchar, RIG->WEB_FREQ); - - sprintf(RIG->WEB_MODE,"%s", RTLModes[Mode]); - - strcpy(RIG->ModeString, Modes[Mode]); - SetWindowText(RIG->hMODE, RIG->WEB_MODE); - - } -} - -VOID RTLUDPPoll(struct RIGPORTINFO * PORT) -{ - UCHAR * Poll = PORT->TXBuffer; - struct RIGINFO * RIG = &PORT->Rigs[0]; // Only one on HAMLIB - char cmd[80]; - int len; - - if (RIG->ScanStopped == 0) - if (RIG->ScanCounter) - RIG->ScanCounter--; - - if (PORT->Timeout) - { - PORT->Timeout--; - - if (PORT->Timeout) // Still waiting - return; - - SetWindowText(RIG->hFREQ, "------------------"); - SetWindowText(RIG->hMODE, "----------"); - strcpy(RIG->WEB_FREQ, "-----------");; - strcpy(RIG->WEB_MODE, "------"); - - RIG->RIGOK = FALSE; - return; - } - - // Send Data if avail, else send poll - - if (RIG->NumberofBands && RIG->RIGOK && (RIG->ScanStopped == 0)) - { - if (RIG->ScanCounter <= 0) - { - // Send Next Freq - - if (GetPermissionToChange(PORT, RIG)) - { - int n; - - if (RIG->RIG_DEBUG) - Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); - - memcpy(PORT->TXBuffer, PORT->FreqPtr->Cmd1, PORT->FreqPtr->Cmd1Len); - PORT->TXLen = PORT->FreqPtr->Cmd1Len; - - _gcvt(PORT->FreqPtr->Freq / 1000000.0, 9, RIG->Valchar); // For MH - - n = sendto(PORT->remoteSock, PORT->TXBuffer, 5, 0, &PORT->remoteDest, sizeof(struct sockaddr)); - - if (PORT->TXLen == 10) - n = sendto(PORT->remoteSock, PORT->TXBuffer + 5, 5, 0, &PORT->remoteDest, sizeof(struct sockaddr)); - - PORT->TXBuffer[0] = 'P'; // Send Poll - - n = sendto(PORT->remoteSock, PORT->TXBuffer, 5, 0, &PORT->remoteDest, sizeof(struct sockaddr)); - - PORT->CmdSent = 1; - PORT->Retries = 0; - PORT->Timeout = 0; - PORT->AutoPoll = TRUE; - - // There isn't a response to a set command, so clear Scan Lock here - - ReleasePermission(RIG); // Release Perrmission - return; - } - } - } - - if (RIG->PollCounter) - { - RIG->PollCounter--; - if (RIG->PollCounter > 1) - return; - } - - if (RIG->RIGOK && (RIG->ScanStopped == 0) && RIG->NumberofBands) - return; // no point in reading freq if we are about to change it - - RIG->PollCounter = 10; // Once Per Sec - - // Read Frequency - - cmd[0] = 'P'; - - len = sendto(PORT->remoteSock, cmd, 5, 0, &PORT->remoteDest, sizeof(struct sockaddr)); - - PORT->Timeout = 10; - PORT->CmdSent = 0; - - PORT->AutoPoll = TRUE; - - return; -} - -VOID ConnecttoRTLUDP(struct RIGPORTINFO * PORT) -{ - char Msg[255]; - int i; - u_long param=1; - BOOL bcopt=TRUE; - struct sockaddr_in sinx; - - if (PORT->remoteSock) - { - closesocket(PORT->remoteSock); - } - - PORT->remoteSock = 0; - PORT->remoteSock = socket(AF_INET,SOCK_DGRAM,0); - - if (PORT->remoteSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for RTLUDP socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - PORT->CONNECTING = FALSE; - return; - } - - ioctl(PORT->remoteSock, FIONBIO, ¶m); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - - PORT->CONNECTED = TRUE; - PORT->hDevice = (HANDLE)1; // simplifies check code - PORT->Alerted = TRUE; -} - - - - - - diff --git a/TNCEmulators-HPLaptop.c b/TNCEmulators-HPLaptop.c deleted file mode 100644 index 7497419..0000000 --- a/TNCEmulators-HPLaptop.c +++ /dev/null @@ -1,6261 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - - -// TNC Emulator Module for BPQ32 switch - -// Supports TNC2 and WA8DED Hostmode interfaces - - -#define _CRT_SECURE_NO_DEPRECATE - -#include "CHeaders.h" - -#define LF 10 -#define CR 13 - -#define Connect(stream) SessionControl(stream,1,0) -#define Disconnect(stream) SessionControl(stream,2,0) -#define ReturntoNode(stream) SessionControl(stream,3,0) -#define ConnectUsingAppl(stream, appl) SessionControl(stream, 0, appl) - -int APIENTRY SendMsg(int stream, char * msg, int len); - -VOID SENDPACKET(struct TNCDATA * TNC); -VOID CHECKCTS(struct TNCDATA * TNC); -VOID SETCOMMANDMODE(struct TNCDATA * TNC); -VOID SETCOMM00(struct TNCDATA * TNC); -VOID SENDREPLY(struct TNCDATA * TNC, char * Msg, int Len); -VOID TNCCOMMAND(struct TNCDATA * TNC); -VOID TNC2PutChar(struct TNCDATA * TNC, int Char); -VOID KBECHO(struct TNCDATA * TNC, int Char); -VOID KBNORM(struct TNCDATA * TNC, int Char); -VOID PUTCHARINBUFFER(struct TNCDATA * TNC, int Char); -VOID TNC2GetChar(struct TNCDATA * TNC, int * returnedchar, int * moretocome); -VOID CONNECTTONODE(struct TNCDATA * TNC); -DllImport int APIENTRY ChangeSessionCallsign(int Stream, unsigned char * AXCall); -DllImport int APIENTRY GetCallsign(int stream, char * callsign); -VOID GETDATA(struct TNCDATA * TNC); -VOID DOCONMODECHANGE(struct TNCDATA * TNC, int Stream); -VOID SEND_CONNECTED(struct TNCDATA * TNC, int ToStream); -VOID READCHANGE(int Stream); -VOID DOMONITORING(int NeedTrace); -int APIENTRY DecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp); -time_t APIENTRY GetRaw(int stream, char * msg, int * len, int * count); -BOOL TfPut(struct TNCDATA * TNC, UCHAR character); -int IntDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, unsigned long long Mask, BOOL APRS, BOOL MCTL); -int DATAPOLL(struct TNCDATA * TNC, struct StreamInfo * Channel); -int STATUSPOLL(struct TNCDATA * TNC, struct StreamInfo * Channel); -int DEDPROCESSHOSTPACKET(struct StreamInfo * Channel, struct TNCDATA * TNC); -VOID ProcessKPacket(struct TNCDATA * conn, UCHAR * rxbuffer, int Len); -VOID ProcessPacket(struct TNCDATA * conn, UCHAR * rxbuffer, int Len);; -int KANTConnected(struct TNCDATA * conn, struct StreamInfo * channel, int Stream); -int KANTDisconnected(struct TNCDATA * conn, struct StreamInfo * channel, int Stream); -VOID SendKISSData(struct TNCDATA * conn, UCHAR * txbuffer, int Len); -VOID ProcessSCSPacket(struct TNCDATA * conn, UCHAR * rxbuffer, int Length); -VOID TNCPoll(); -VOID DisableAppl(struct TNCDATA * TNC); -int BPQSerialSetPollDelay(HANDLE hDevice, int PollDelay); -int BPQSerialSendData(struct TNCDATA * TNC, UCHAR * Message,int MsgLen); -int BPQSerialGetData(struct TNCDATA * TNC, UCHAR * Message, unsigned int BufLen, ULONG * MsgLen); - -extern struct TNCDATA * TNCCONFIGTABLE; - -struct TNCDATA * TNC2TABLE; // malloc'ed -extern int NUMBEROFTNCPORTS; - -// MODEFLAG DEFINITIONS - -#define COMMAND 1 -#define TRANS 2 -#define CONV 4 - -// APPLFLAGS BITS - -//CMD_TO_APPL EQU 1B ; PASS COMMAND TO APPLICATION -//MSG_TO_USER EQU 10B ; SEND "CONNECTED" TO USER -//MSG_TO_APPL EQU 100B ; SEND "CONECTED" TO APPL - -extern char pgm[256]; - -int CloseDelay = 10; // Close after connect fail delay - -MESSAGE MONITORDATA; // RAW FRAME FROM NODE - -char NEWCALL[11]; - -//TABLELEN DW TYPE TNCDATA - -char LNKSTATEMSG[] = "Link state is: "; -char CONNECTEDMSG[] = "CONNECTED to "; -char WHATMSG[] = "Eh?\rcmd:"; -char CMDMSG[] = "cmd:"; - - -char DISCONNMSG[] = "\r*** DISCONNECTED\r"; - -char CONMSG1[] = "\r*** CONNECTED to "; -char CONCALL[10]; - - -char SIGNON[] = "\r\rG8BPQ TNC2 EMULATOR\r\r"; - -char CONMSG[] ="\r*** CONNECTED to "; -char SWITCH[] = "SWITCH\r"; -char SWITCHSP[] = "SWITCH "; - -char WAS[] = " was "; -char VIA[] = " via "; -char OFF[] = "OFF\r"; -char ON[] = "ON \r"; - -// BPQ Serial Device Support - -// On W2K and above, BPQVIrtualCOM.sys provides a pair of cross-connected devices, and a control channel -// to enumerate, add and delete devices. - -// On Win98 BPQVCOMM.VXD provides a single IOCTL interface, over which calls for each COM device are multiplexed - -#ifdef WIN32 - -#define IOCTL_SERIAL_SET_BAUD_RATE CTL_CODE(FILE_DEVICE_SERIAL_PORT, 1,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_QUEUE_SIZE CTL_CODE(FILE_DEVICE_SERIAL_PORT, 2,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_LINE_CONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT, 3,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_BREAK_ON CTL_CODE(FILE_DEVICE_SERIAL_PORT, 4,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_BREAK_OFF CTL_CODE(FILE_DEVICE_SERIAL_PORT, 5,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_IMMEDIATE_CHAR CTL_CODE(FILE_DEVICE_SERIAL_PORT, 6,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_TIMEOUTS CTL_CODE(FILE_DEVICE_SERIAL_PORT, 7,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_TIMEOUTS CTL_CODE(FILE_DEVICE_SERIAL_PORT, 8,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_DTR CTL_CODE(FILE_DEVICE_SERIAL_PORT, 9,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_CLR_DTR CTL_CODE(FILE_DEVICE_SERIAL_PORT,10,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_RESET_DEVICE CTL_CODE(FILE_DEVICE_SERIAL_PORT,11,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_RTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,12,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_CLR_RTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,13,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_XOFF CTL_CODE(FILE_DEVICE_SERIAL_PORT,14,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_XON CTL_CODE(FILE_DEVICE_SERIAL_PORT,15,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_WAIT_MASK CTL_CODE(FILE_DEVICE_SERIAL_PORT,16,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_WAIT_MASK CTL_CODE(FILE_DEVICE_SERIAL_PORT,17,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_WAIT_ON_MASK CTL_CODE(FILE_DEVICE_SERIAL_PORT,18,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_PURGE CTL_CODE(FILE_DEVICE_SERIAL_PORT,19,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_BAUD_RATE CTL_CODE(FILE_DEVICE_SERIAL_PORT,20,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_LINE_CONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,21,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_CHARS CTL_CODE(FILE_DEVICE_SERIAL_PORT,22,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_CHARS CTL_CODE(FILE_DEVICE_SERIAL_PORT,23,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_HANDFLOW CTL_CODE(FILE_DEVICE_SERIAL_PORT,24,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_HANDFLOW CTL_CODE(FILE_DEVICE_SERIAL_PORT,25,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_MODEMSTATUS CTL_CODE(FILE_DEVICE_SERIAL_PORT,26,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_COMMSTATUS CTL_CODE(FILE_DEVICE_SERIAL_PORT,27,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_XOFF_COUNTER CTL_CODE(FILE_DEVICE_SERIAL_PORT,28,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_PROPERTIES CTL_CODE(FILE_DEVICE_SERIAL_PORT,29,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GET_DTRRTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,30,METHOD_BUFFERED,FILE_ANY_ACCESS) - - -#define IOCTL_SERIAL_IS_COM_OPEN CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_GETDATA CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SETDATA CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x802,METHOD_BUFFERED,FILE_ANY_ACCESS) - -#define IOCTL_SERIAL_SET_CTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x803,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_DSR CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x804,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_SET_DCD CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x805,METHOD_BUFFERED,FILE_ANY_ACCESS) - -#define IOCTL_SERIAL_CLR_CTS CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x806,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_CLR_DSR CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x807,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_SERIAL_CLR_DCD CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x808,METHOD_BUFFERED,FILE_ANY_ACCESS) - -#define IOCTL_BPQ_ADD_DEVICE CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x809,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_BPQ_DELETE_DEVICE CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x80a,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_BPQ_LIST_DEVICES CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x80b,METHOD_BUFFERED,FILE_ANY_ACCESS) - -#define IOCTL_BPQ_SET_POLLDELAY CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x80c,METHOD_BUFFERED,FILE_ANY_ACCESS) -#define IOCTL_BPQ_SET_DEBUGMASK CTL_CODE(FILE_DEVICE_SERIAL_PORT,0x80d,METHOD_BUFFERED,FILE_ANY_ACCESS) - -#define W98_SERIAL_IS_COM_OPEN 0x800 -#define W98_SERIAL_GETDATA 0x801 -#define W98_SERIAL_SETDATA 0x802 - -#define W98_SERIAL_SET_CTS 0x803 -#define W98_SERIAL_SET_DSR 0x804 -#define W98_SERIAL_SET_DCD 0x805 - -#define W98_SERIAL_CLR_CTS 0x806 -#define W98_SERIAL_CLR_DSR 0x807 -#define W98_SERIAL_CLR_DCD 0x808 - -#define W98_BPQ_ADD_DEVICE 0x809 -#define W98_BPQ_DELETE_DEVICE 0x80a -#define W98_BPQ_LIST_DEVICES 0x80b - -#define W98_BPQ_SET_POLLDELAY 0x80c -#define W98_BPQ_SET_DEBUGMASK 0x80d - -#define W98_SERIAL_GET_COMMSTATUS 27 -#define W98_SERIAL_GET_DTRRTS 30 - -#define DebugModemStatus 1 -#define DebugCOMStatus 2 -#define DebugWaitCompletion 4 -#define DebugReadCompletion 8 - - -HANDLE hControl; - -BOOL Win98; - -typedef struct _SERIAL_STATUS { - ULONG Errors; - ULONG HoldReasons; - ULONG AmountInInQueue; - ULONG AmountInOutQueue; - BOOL EofReceived; - BOOL WaitForImmediate; -} SERIAL_STATUS,*PSERIAL_STATUS; - -#endif - -#ifndef WIN32 -// #include - -extern int posix_openpt (int __oflag); -extern int grantpt (int __fd); -extern int unlockpt (int __fd); -extern char *ptsname (int __fd); -extern int ptsname_r (int __fd, char *__buf, size_t __buflen); -extern int getpt (void); - -HANDLE LinuxOpenPTY(char * Name) -{ - // Open a Virtual COM Port - - HANDLE hDevice, slave;; - char slavedevice[80]; - int ret; - u_long param=1; - struct termios term; - -#ifdef MACBPQ - - // Create a pty pair - - openpty(&hDevice, &slave, &slavedevice[0], NULL, NULL); - close(slave); - -#else - - hDevice = posix_openpt(O_RDWR|O_NOCTTY); - - if (hDevice == -1) - { - perror("posix_openpt Create PTY pair failed"); - return -1; - } - if (grantpt (hDevice) == -1) - { - perror("grantpt Create PTY pair failed"); - return -1; - } - if (unlockpt (hDevice) == -1) - { - perror("unlockpt Create PTY pair failed"); - return -1; - } - if (ptsname_r(hDevice, slavedevice, 80) != 0) - { - perror("ptsname_r Create PTY pair failed"); - return -1; - } - -#endif - - printf("slave device: %s. ", slavedevice); - - if (tcgetattr(hDevice, &term) == -1) - { - perror("tty_speed: tcgetattr"); - return FALSE; - } - - cfmakeraw(&term); - - if (tcsetattr(hDevice, TCSANOW, &term) == -1) - { - perror("tcsetattr"); - return -1; - } - - ioctl(hDevice, FIONBIO, ¶m); - - chmod(slavedevice, S_IRUSR|S_IRGRP|S_IWUSR|S_IWGRP|S_IROTH|S_IWOTH); - - unlink (Name); - - ret = symlink (slavedevice, Name); - - if (ret == 0) - printf ("symlink to %s created\n", Name); - else - printf ("symlink to %s failed\n", Name); - - return hDevice; -} -#else - -HANDLE BPQOpenSerialPort(struct TNCDATA * TNC, DWORD * lasterror) -{ - // Open a Virtual COM Port - - int port = TNC->ComPort; - char szPort[80]; - HANDLE hDevice; - int Err; - - *lasterror=0; - - if (Win98) - { - sprintf( szPort, "\\\\.\\COM%d",port) ; - - hDevice = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (hDevice == (HANDLE) -1 ) - { - // If In Use(5) ok, else fail - - if (GetLastError() == 5) - return (HANDLE)(ptrdiff_t)(port<<16); // Port Number is a pseudohandle to the device - - return (HANDLE)(ptrdiff_t) - 1; - } - - CloseHandle(hDevice); - - return (HANDLE)(ptrdiff_t)(port<<16); // Port Number is a pseudohandle to the device - } - - // Try New Style VCOM firsrt - - sprintf( szPort, "\\\\.\\pipe\\BPQCOM%d", port ) ; - - hDevice = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - Err = GetLastError(); - - if (hDevice != (HANDLE) -1) - { - TNC->NewVCOM = TRUE; - TNC->PortEnabled = TRUE; - Err = GetFileType(hDevice); - } - else - { - - // Try old style - - sprintf(szPort, "\\\\.\\BPQ%d", port ) ; - - - hDevice = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (TNC->PollDelay) - BPQSerialSetPollDelay(hDevice, TNC->PollDelay); - - } - if (hDevice == (HANDLE) -1 ) - { - *lasterror=GetLastError(); - } - - return hDevice; -} -#endif - -int BPQSerialSetCTS(HANDLE hDevice) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - if (Win98) - return DeviceIoControl(hControl,(DWORD)hDevice | W98_SERIAL_SET_CTS,NULL,0,NULL,0, &bytesReturned,NULL); - else - return DeviceIoControl(hDevice,IOCTL_SERIAL_SET_CTS,NULL,0,NULL,0, &bytesReturned,NULL); - -#endif -} - -int BPQSerialSetDSR(HANDLE hDevice) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_SET_DSR,NULL,0,NULL,0, &bytesReturned,NULL); - else - return DeviceIoControl(hDevice,IOCTL_SERIAL_SET_DSR, NULL,0,NULL,0, &bytesReturned,NULL); -#endif -} - -int BPQSerialSetDCD(HANDLE hDevice) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_SET_DCD,NULL,0,NULL,0, &bytesReturned,NULL); - else - return DeviceIoControl(hDevice,IOCTL_SERIAL_SET_DCD,NULL,0,NULL,0, &bytesReturned,NULL); -#endif -} - -int BPQSerialClrCTS(HANDLE hDevice) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_CLR_CTS,NULL,0,NULL,0, &bytesReturned,NULL); - else - return DeviceIoControl(hDevice,IOCTL_SERIAL_CLR_CTS,NULL,0,NULL,0, &bytesReturned,NULL); -#endif -} -int BPQSerialClrDSR(HANDLE hDevice) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_CLR_DSR,NULL,0,NULL,0, &bytesReturned,NULL); - else - return DeviceIoControl(hDevice,IOCTL_SERIAL_CLR_DSR,NULL,0,NULL,0, &bytesReturned,NULL); -#endif -} - -int BPQSerialClrDCD(HANDLE hDevice) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_CLR_DCD,NULL,0,NULL,0, &bytesReturned,NULL); - else - return DeviceIoControl(hDevice,IOCTL_SERIAL_CLR_DCD, NULL,0,NULL,0, &bytesReturned,NULL); -#endif -} - -static int SendDataToTNC(struct TNCDATA * TNC, UCHAR * TXMsg, int n) -{ - // Used for all port types - -#ifdef WIN32 - - // WIN32 VCOM Used one of my Drivers - - if (TNC->VCOM) - BPQSerialSendData(TNC, TXMsg, n); - -#endif - - // Linux VCOM uses SOCAT Pairs and normal write - - return WriteCOMBlock(TNC->hDevice, TXMsg, n); -} - -int BPQSerialSendData(struct TNCDATA * TNC, UCHAR * Message,int MsgLen) -{ - HANDLE hDevice = TNC->hDevice; - ULONG bytesReturned; - - // Host Mode code calls BPQSerialSendData for all ports, so it a real port, pass on to real send routine - - if (!TNC->VCOM) - return WriteCOMBlock(TNC->hDevice, Message, MsgLen); - -#ifndef WIN32 - - // Linux usies normal IO for all ports - return WriteCOMBlock(TNC->hDevice, Message, MsgLen); - -#else - - if (MsgLen > 4096 ) return ERROR_INVALID_PARAMETER; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_SETDATA,Message,MsgLen,NULL,0, &bytesReturned,NULL); - else - { - if (TNC->NewVCOM) - { - // Have to escape all oxff chars, as these are used to get status info - - UCHAR NewMessage[1000]; - UCHAR * ptr1 = Message; - UCHAR * ptr2 = NewMessage; - UCHAR c; - - int Length = MsgLen; - - while (Length != 0) - { - c = *(ptr1++); - *(ptr2++) = c; - - if (c == 0xff) - { - *(ptr2++) = c; - MsgLen++; - } - Length--; - } - - return WriteFile(hDevice, NewMessage, MsgLen, &bytesReturned, NULL); - } - else - return DeviceIoControl(hDevice,IOCTL_SERIAL_SETDATA,Message,MsgLen,NULL,0, &bytesReturned,NULL); - } -#endif -} - -int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error); - -int GetDataFromTNC(struct TNCDATA * TNC, UCHAR * Message, unsigned int BufLen, ULONG * MsgLen) -{ - // Used for all port types - -#ifdef WIN32 - - // WIN32 VCOM Used one of my Drivers - - if (TNC->VCOM) - return BPQSerialGetData(TNC, Message, BufLen, MsgLen); - - *MsgLen = ReadCOMBlock(TNC->hDevice, Message, BufLen); - return 0; - -#else - - int Error = 0; - - if (TNC->VCOM == 0) - { - *MsgLen = ReadCOMBlock(TNC->hDevice, Message, BufLen); - return 0; - } - - // Linux VCOM uses SOCAT Pairs and normal Read - - // If the slave closes connection read returns 5. Need to trap and - // close/reopen. So use ReadCOMBlockEx - - *MsgLen = ReadCOMBlockEx(TNC->hDevice, Message, BufLen, &Error); - - if (Error == 5) - { - printf("Read error on TNCPORT %s - Restarting\n", TNC->PORTNAME); - close(TNC->hDevice); - TNC->hDevice = LinuxOpenPTY(TNC->PORTNAME); - } - return 0; - -#endif -} - - -int BPQSerialGetData(struct TNCDATA * TNC, UCHAR * Message, unsigned int BufLen, ULONG * MsgLen) -{ -#ifdef WIN32 - DWORD dwLength = 0; - DWORD Available = 0; - HANDLE hDevice = TNC->hDevice; - int Length, RealLen = 0; - - if (BufLen > 4096 ) return ERROR_INVALID_PARAMETER; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_GETDATA,NULL,0,Message,BufLen,MsgLen,NULL); - - if (TNC->NewVCOM) - { - int ret = PeekNamedPipe(hDevice, NULL, 0, NULL, &Available, NULL); - - if (ret == 0) - { - ret = GetLastError(); - - if (ret == ERROR_BROKEN_PIPE) - { - CloseHandle(hDevice); - hDevice = INVALID_HANDLE_VALUE; - return 0; - } - } - - if (Available > BufLen) - Available = BufLen; - - if (Available) - { - UCHAR * ptr1 = Message; - UCHAR * ptr2 = Message; - UCHAR c; - - ReadFile(hDevice, Message, Available, &Length, NULL); - - // Have to look for FF escape chars - - RealLen = Length; - - while (Length != 0) - { - c = *(ptr1++); - Length--; - - if (c == 0xff) - { - c = c = *(ptr1++); - Length--; - - if (c == 0xff) // ff ff means ff - { - RealLen--; - } - else - { - // This is connection statua from other end - - RealLen -= 2; -// TNC->PortEnabled = c; - continue; - } - } - *(ptr2++) = c; - } - } - *MsgLen = RealLen; - return 0; - } - - return DeviceIoControl(hDevice,IOCTL_SERIAL_GETDATA,NULL,0,Message,BufLen,MsgLen,NULL); -} -#else - return 0; -} -#endif - -int BPQSerialGetQCounts(HANDLE hDevice,ULONG * RXCount, ULONG * TXCount) -{ -#ifndef WIN32 - return 0; -#else - - SERIAL_STATUS Resp; - int MsgLen; - int ret; - - if (Win98) - ret = DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_GET_COMMSTATUS,NULL,0,&Resp,sizeof(SERIAL_STATUS),&MsgLen,NULL); - else - ret = DeviceIoControl(hDevice,IOCTL_SERIAL_GET_COMMSTATUS,NULL,0,&Resp,sizeof(SERIAL_STATUS),&MsgLen,NULL); - - *RXCount=Resp.AmountInInQueue; - *TXCount=Resp.AmountInOutQueue; - - return ret; -#endif -} - -int BPQSerialGetDeviceList(HANDLE hDevice,ULONG * Slot,ULONG * Port) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - return DeviceIoControl (hDevice,IOCTL_BPQ_LIST_DEVICES,Slot,4,Port,4,&bytesReturned,NULL); -#endif -} - -int BPQSerialIsCOMOpen(HANDLE hDevice,ULONG * Count) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_IS_COM_OPEN,NULL,0,Count,4,&bytesReturned,NULL); - else - return DeviceIoControl(hDevice,IOCTL_SERIAL_IS_COM_OPEN,NULL,0,Count,4,&bytesReturned,NULL); -#endif -} - -int BPQSerialGetDTRRTS(HANDLE hDevice, ULONG * Flags) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_SERIAL_GET_DTRRTS,NULL,0,Flags,4,&bytesReturned,NULL); - else - return DeviceIoControl(hDevice,IOCTL_SERIAL_GET_DTRRTS,NULL,0,Flags,4,&bytesReturned,NULL); -#endif -} - -int BPQSerialSetPollDelay(HANDLE hDevice, int PollDelay) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - if (Win98) - return DeviceIoControl(hControl, (UINT)hDevice | W98_BPQ_SET_POLLDELAY,&PollDelay,4,NULL,0, &bytesReturned,NULL); - else - return DeviceIoControl(hDevice,IOCTL_BPQ_SET_POLLDELAY,&PollDelay,4,NULL,0, &bytesReturned,NULL); - -#endif -} - -int BPQSerialSetDebugMask(HANDLE hDevice, int DebugMask) -{ -#ifndef WIN32 - return 0; -#else - - ULONG bytesReturned; - - return DeviceIoControl(hDevice, IOCTL_BPQ_SET_DEBUGMASK, &DebugMask, 4, NULL, 0, &bytesReturned,NULL); -#endif -} - -void CheckForStreamChange(struct TNCDATA * TNC, int ToStream) -{ - // Send Stream Switched Message if changed - - char Msg[80]; - int Len; - - if (ToStream == TNC->RXStream) - return; - - TNC->RXStream = ToStream; - - // Send Message - - // |B:WA7GXD: - - if (TNC->StreamCall) - Len = sprintf(Msg, "%c%c:%s:", TNC->StreamSW, ToStream + 'A', TNC->TNC2Stream[ToStream]->RemoteCall); - else - Len = sprintf(Msg, "%c%c", TNC->StreamSW, ToStream + 'A'); - - SENDREPLY(TNC, Msg, Len); -} - -int LocalSessionState(int stream, int * state, int * change, BOOL ACK) -{ - // Get current Session State. Any state changed is ACK'ed - // automatically. See BPQHOST functions 4 and 5. - - // Local version without semaphore or checktimer - - BPQVECSTRUC * HOST = &BPQHOSTVECTOR[stream -1]; // API counts from 1 - - // CX = 0 if stream disconnected or CX = 1 if stream connected - // DX = 0 if no change of state since last read, or DX = 1 if - // the connected/disconnected state has changed since - // last read (ie. delta-stream status). - - // HOSTFLAGS = Bit 80 = Allocated - // Bit 40 = Disc Request - // Bit 20 = Stay Flag - // Bit 02 and 01 State Change Bits - - if ((HOST->HOSTFLAGS & 3) == 0) - // No Chaange - *change = 0; - else - *change = 1; - - if (HOST->HOSTSESSION) // LOCAL SESSION - // Connected - *state = 1; - else - *state = 0; - - if (ACK) - HOST->HOSTFLAGS &= 0xFC; // Clear Change Bits - - return 0; -} - - - - -VOID ONOFF(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - // PROCESS COMMANDS WITH ON/OFF PARAM - - char Param; - UCHAR * valueptr; - UCHAR oldvalue, newvalue = 0xff; - - char Response[80]; - int len; - - _strupr(Tail); - Param = *Tail; - - valueptr = (UCHAR *)TNC + CMD->CMDFLAG;; - oldvalue = (UCHAR)*valueptr; - - switch(Param) - { - case ' ': - break; - case 'Y': - newvalue = 1; - break; - case 'N': - newvalue = 0; - break; - case 'O': - if (Tail[1] == 'N') - newvalue = 1; - else - newvalue = 0; - break; - } - - if (newvalue == 255) - { - len = sprintf(Response, "%s %s\r", CMD->String, (oldvalue)?"ON":"OFF"); - } - else - { - len = sprintf(Response, "%s was %s\r", CMD->String, (oldvalue)?"ON":"OFF"); - *valueptr = newvalue; - } - SENDREPLY(TNC, Response, len); -} - - - -VOID ONOFF_CONOK(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - ONOFF(TNC, Tail, CMD); - - // UPDATE APPL FLAGS ON NODE PORT - - if (TNC->CONOK) - SetAppl(TNCStream->BPQPort, TNC->APPLFLAGS, TNC->APPLICATION); - else - SetAppl(TNCStream->BPQPort, TNC->APPLFLAGS, 0); -} - -VOID SETMYCALL(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - char Response[80]; - int len; - char Call[10] = " "; - - _strupr(Tail); - - if (*Tail == ' ') - { - // REQUEST FOR CURRENT STATE - - len = sprintf(Response, "MYCALL %s\r", TNC->MYCALL); - } - else - { - strlop(Tail,' ');; - memcpy(Call, Tail, (int)strlen(Tail) + 1); - len = sprintf(Response, "MYCALL was %s\r", TNC->MYCALL); - memcpy(TNC->MYCALL, Call, 10); - } - - SENDREPLY(TNC, Response, len); -} -VOID CTEXTCMD(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - char Response[256]; - int len, n; - - if (*Tail == ' ') - { - // REQUEST FOR CURRENT STATE - - len = sprintf(Response, "CTEXT %s\r", TNC->CTEXT); - } - else - { - Tail[TNC->MSGLEN] = 0; - n = strlen(Tail) - 1; - while(n > 0 && Tail[n] == ' ') - Tail[n--] = 0; - - if (strlen(Tail) > 119) - Tail[119] = 0; - - len = sprintf(Response, "CTEXT was %s\r", TNC->CTEXT); - strcpy(TNC->CTEXT, Tail); - } - - SENDREPLY(TNC, Response, len); -} - -VOID BTEXT(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ -} -VOID VALUE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - // PROCESS COMMANDS WITH decimal value - - char Param = *Tail; - UCHAR * valueptr; - int oldvalue, newvalue; - - char Response[80]; - int len; - - valueptr = (UCHAR *)TNC + CMD->CMDFLAG;; - oldvalue = *valueptr; - - strlop(Tail, ' '); - - if (Tail[0]) - { - newvalue = atoi(Tail); - len = sprintf(Response, "%s was %d\r", CMD->String, oldvalue); - *valueptr = newvalue; - } - else - { - len = sprintf(Response, "%s %d\r", CMD->String, oldvalue); - } - SENDREPLY(TNC, Response, len); -} - -VOID VALHEX(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - // PROCESS COMMANDS WITH decimal value - - char Param = *Tail; - - UCHAR * valueptr; - UINT * intvalueptr; - UINT oldvalue, newvalue; - - char Response[80]; - int len; - - valueptr = (UCHAR *)TNC + CMD->CMDFLAG;; - intvalueptr = (UINT *)valueptr; - - oldvalue = *intvalueptr; - - strlop(Tail, ' '); - - if (Tail[0]) - { - if (Tail[0] == '$') - newvalue = (UINT)strtol(Tail + 1, NULL, 16); - else - newvalue = (UINT)strtol(Tail, NULL, 0); - - len = sprintf(Response, "%s was $%x\r", CMD->String, oldvalue); - *intvalueptr = newvalue; - } - else - { - len = sprintf(Response, "%s $%x\r", CMD->String, oldvalue); - } - SENDREPLY(TNC, Response, len); -} - -VOID APPL_VALHEX(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - int ApplNum = 1; - UINT APPLMASK; - - VALHEX(TNC, Tail, CMD); - - // UPDATE APPL FLAGS ON NODE PORT - - if (TNC->CONOK) - SetAppl(TNC->BPQPort, TNC->APPLFLAGS, TNC->APPLICATION); - else - SetAppl(TNC->BPQPort, TNC->APPLFLAGS, 0); - - // Set MYCALL to APPLCALL - - APPLMASK = TNC->APPLICATION; - ApplNum = 1; - - while (APPLMASK && (APPLMASK & 1) == 0) - { - ApplNum++; - APPLMASK >>= 1; - } - - if (TNC->CONOK && TNC->APPLICATION) - memcpy(TNC->MYCALL, GetApplCall(ApplNum), 10); - -} -VOID CSWITCH(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - char Response[80]; - int len; - - len = sprintf(Response, "%s", CMDMSG); - SENDREPLY(TNC, Response, len); - - CONNECTTONODE(TNC); - -} -VOID CONMODE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - SENDREPLY(TNC, CMDMSG, 4); -} - -VOID TNCCONV(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - TNCStream->MODEFLAG |= CONV; - TNCStream->MODEFLAG &= ~(COMMAND+TRANS); -} - -VOID TNCNODE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - // CONNECT TO NODE - - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - TNCStream->VMSR |= 0x88; // SET CONNECTED - - TNCStream->MODEFLAG |= CONV; // INTO CONVERSE MODE - TNCStream->MODEFLAG &= ~(COMMAND+TRANS); - - CONNECTTONODE(TNC); -} - -VOID CStatus(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - char Response[80]; - int i, len; - char Call[10] = ""; - char Selected[3] = " "; - - for (i = 0; i < TNC->HOSTSTREAMS; i++) - { - char Selected[3] = " "; - TNCStream = TNC->TNC2Stream[i]; - - if (TNC->RXStream == i) - Selected[0] = 'I'; - - if (TNC->TXStream == i) - Selected[1] = 'O'; - - if (TNCStream->VMSR & 0x80) - { - GetCallsign(TNCStream->BPQPort, Call); - strlop(Call, ' '); - - len = sprintf(Response, "%c stream - %s CONNECTED to %s\r", i + 'A', Selected, Call); - } - else - { - len = sprintf(Response, "%c stream - %s DISCONNECTED\r", i + 'A', Selected); - } - - SENDREPLY(TNC, Response, len); - } -} - - -VOID TNCCONNECT(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - char Response[80]; - int len; - char Call[10] = ""; - - _strupr(Tail); - - if (*Tail == ' ') - { - // REQUEST FOR CURRENT STATE - - len = sprintf(Response, "%s", LNKSTATEMSG); - - if (TNCStream->VMSR & 0x80) - { - GetCallsign(TNCStream->BPQPort, Call); - strlop(Call, ' '); - - len = sprintf(Response, "%c Link state is: CONNECTED to %s\r", TNC->TXStream + 'A', Call); - } - else - { - len = sprintf(Response, "%c Link state is: DISCONNECTED\r", TNC->TXStream + 'A'); - } - - SENDREPLY(TNC, Response, len); - return; - } - - // CONNECT, BUT NOT TO SWITCH - CONNECT TO NODE, THEN PASS TO IT FOR PROCESSING - - TNCNODE(TNC, Tail, CMD); - READCHANGE(TNCStream->BPQPort); //CLEAR STATUS CHANGE (TO AVOID SUPURIOUS "CONNECTED TO") - - strcat(TNC->TONODEBUFFER, "\r"); - TNC->MSGLEN = (int)strlen(TNC->TONODEBUFFER); - - SENDPACKET(TNC); // Will now go to node - -} -VOID TNCDISC(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - Disconnect(TNCStream->BPQPort); - - SENDREPLY(TNC, CMDMSG, 4); -} - -VOID READCHANGE(int Stream) -{ - int dummy; - LocalSessionState(Stream, &dummy, &dummy, TRUE); -} - -VOID TNCRELEASE(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - ReturntoNode(TNC->BPQPort); - - TNC->VMSR &= 0x7F; // DROP DCD - TNC->VMSR |= 8; //DELTA DCD - - SENDREPLY(TNC, CMDMSG, 4); -} -VOID TNCTRANS(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - // MAKE PRETTY SURE THIS ISNT A BIT OF STRAY DATA - - if (TNC->MSGLEN > 6) - return; - - TNCStream->MODEFLAG |= TRANS; - TNCStream->MODEFLAG &= ~(COMMAND+CONV); -} -static VOID RESTART(struct TNCDATA * TNC) -{ - // REINITIALISE CHANNEL - - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - TNC->PUTPTR = TNC->GETPTR = &TNC->TOUSERBUFFER[0]; - TNC->RXCOUNT = 0; - - TNC->VLSR = 0x20; - TNC->VMSR = 0x30; - - TNCStream->MODEFLAG = COMMAND; - TNC->SENDPAC = 13; - TNC->CRFLAG = 1; - TNC->MALL = 1; - TNC->MMASK = -1; // MONITOR MASK FOR PORTS - TNC->TPACLEN = PACLEN; // TNC PACLEN - - TNC->COMCHAR = 3; - TNC->CMDTIME = 10; // SYSTEM TIMER = 100MS - TNC->CURSOR = &TNC->TONODEBUFFER[0]; // RESET MESSAGE START - TNC->MSGLEN = 0; - - SENDREPLY(TNC, SIGNON, 23); -} - - -static VOID UNPROTOCMD(struct TNCDATA * TNC, char * Tail, CMDX * CMD) -{ -} - - -CMDX COMMANDLIST[] = -{ - "AUTOLF ",2, ONOFF, offsetof(struct TNCDATA, AUTOLF), - "BBSMON ",6, ONOFF, offsetof(struct TNCDATA, BBSMON), - "BTEXT ",2,BTEXT,0, - "CONOK ",4,ONOFF_CONOK,offsetof(struct TNCDATA, CONOK), - "C SWITCH",8,CSWITCH,0, - "CBELL ",2,ONOFF,offsetof(struct TNCDATA, CBELL), - "CMDTIME ",2,VALUE, offsetof(struct TNCDATA, CMDTIME), - "CMSG ",4,ONOFF,offsetof(struct TNCDATA, CMSG), - "COMMAND ",3,VALHEX, offsetof(struct TNCDATA, COMCHAR), - "CONMODE ",4,CONMODE,0, - "CPACTIME",2,ONOFF,offsetof(struct TNCDATA, CPACTIME), - "CR ",2,ONOFF,offsetof(struct TNCDATA, CRFLAG), - "CSTATUS ",2,CStatus,0, - "CTEXT ",2,CTEXTCMD,0, - "APPLFLAG",5,APPL_VALHEX, offsetof(struct TNCDATA, APPLFLAGS), - "APPL ",4,APPL_VALHEX, offsetof(struct TNCDATA, APPLICATION), - "CONVERS ",4,TNCCONV,0, - "CONNECT ",1,TNCCONNECT,0, - "DISCONNE",1,TNCDISC,0, - "ECHO ",1,ONOFF,offsetof(struct TNCDATA, ECHOFLAG), - "FLOW ",4,ONOFF,offsetof(struct TNCDATA, FLOWFLAG), - "HEADERLN",2,ONOFF,offsetof(struct TNCDATA, HEADERLN), - "K ",1,TNCNODE,0, - "MTXFORCE",4,ONOFF,offsetof(struct TNCDATA, MTXFORCE), - "LCSTREAM",8,ONOFF, offsetof(struct TNCDATA, LCStream), - "LFIGNORE",3,ONOFF,offsetof(struct TNCDATA, LFIGNORE), - "MTX ",3,ONOFF,offsetof(struct TNCDATA, MTX), - "MALL ",2,ONOFF,offsetof(struct TNCDATA, MALL), - "MCOM ",4,ONOFF,offsetof(struct TNCDATA, MCOM), - "MCON ",2,ONOFF,offsetof(struct TNCDATA, MCON), - "MMASK ",2,VALHEX, offsetof(struct TNCDATA, MMASK), - "MONITOR ",3,ONOFF,offsetof(struct TNCDATA, TRACEFLAG), - "MYCALL ",2,SETMYCALL,0, - "NEWMODE ",2,ONOFF,offsetof(struct TNCDATA, NEWMODE), - "NODE ",3,TNCNODE,0, - "NOMODE ",2,ONOFF,offsetof(struct TNCDATA, NOMODE), - "SENDPAC ",2,VALHEX, offsetof(struct TNCDATA, SENDPAC), - "STREAMCA",8,ONOFF, offsetof(struct TNCDATA, StreamCall), - "STREAMDBL",7,ONOFF, offsetof(struct TNCDATA, StreamDbl), - "STREAMSW",3,VALHEX, offsetof(struct TNCDATA, StreamSW), - "PACLEN ",1,VALUE, offsetof(struct TNCDATA, TPACLEN), - "PASS ",3,VALHEX, offsetof(struct TNCDATA, PASSCHAR), - "RELEASE ",3,TNCRELEASE,0, - "RESTART ",7,RESTART,0, - "TRANS ",1,TNCTRANS,0, - "UNPROTO ",1,UNPROTOCMD,0, - "USERS ",2,VALUE, offsetof(struct TNCDATA, Users), -}; - -static CMDX * CMD = NULL; - -int NUMBEROFTNCCOMMANDS = sizeof(COMMANDLIST)/sizeof(CMDX); - -/*NEWVALUE DW 0 -HEXFLAG DB 0 - - -NUMBER DB 4 DUP (0),CR -NUMBERH "$0000",CR - -BADMSG "?bad parameter",CR,0 - -BTHDDR ,0 ; CHAIN - DB 0 ; PORT - DW 7 ; LENGTH - DB 0F0H ; PID -BTEXTFLD DB 0DH,256 DUP (0) - -CMDENDADDR,0 ; POINTER TO END OF COMMAND - -MBOPTIONBYTE DB 0 - -NORMCALL DB 10 DUP (0) -AX25CALL DB 7 DUP (0) - -CONNECTCALL DB 10 DUP (0) ; CALLSIGN IN CONNECT MESSAGE -DIGICALL DB 10 DUP (0) ; DIGI IN CONNECT COMMAND -AX25STRING DB 64 DUP (0) ; DIGI STRING IN AX25 FORMAT -DIGIPTR ,0 ; POINTER TO CURRENT DIGI IN STRING - -NORMLEN ,0 - - EVEN -*/ - -int TRANSDELAY = 10; // 1 SEC - -//UNPROTOCALL DB "UNPROTO",80 DUP (0) - -char MONBUFFER[1000]; - -VOID TNC2GetChar(struct TNCDATA * TNC, int * returnedchar, int * moretocome) -{ - // Poll Node - - if (TNC->Mode == 0) - GETDATA(TNC); - - *returnedchar = -1; - *moretocome = 0; - - if (TNC->RXCOUNT == 0) - return; - - *returnedchar = *(TNC->GETPTR++); - - if (TNC->GETPTR == &TNC->TOUSERBUFFER[TNCBUFFLEN]) - TNC->GETPTR = &TNC->TOUSERBUFFER[0]; - - *moretocome = --TNC->RXCOUNT; //ANY MORE? - - if (TNC->RXCOUNT < 128) // GETTING LOW? - { - if (TNC->RTSFLAG & 1) // RTS UP? - { - // RTS HAD BEEN DROPPED TO STOP OTHER END SENDING - RAISE IT AGAIN - - TNC->RTSFLAG &= 0xFE; - } - } -} - -int TNCGetVMSR(struct TNCDATA * TNC, struct TNC2StreamInfo * TNCStream, BOOL ClearDeltas) -{ - // On TNC2 Connected bit should come from current stream - // flow control bits from TNC record - - int val = TNC->VMSR; - - if (TNC->Mode == TNC2) - val |= TNCStream->VMSR; - - if (ClearDeltas) - { - TNC->VMSR &= 0xF0; // CLEAR DELTA BITS - - if (TNC->Mode == TNC2) - TNCStream->VMSR &= 0xF0; - } - return val; -} - -BOOL TNCRUNNING;; - -VOID TNCBGThread(void * unused) -{ - TNCRUNNING = TRUE; - - Sleep(5000); - - while (TNCRUNNING) - { - TNCPoll(); - Sleep(50); - } -} - -VOID AllocateDEDChannel(struct TNCDATA * TNC, int Num) -{ - struct StreamInfo * Channel = zalloc(sizeof(struct StreamInfo)); - char * PNptr; - - // Only show last element of name on Streams display - - PNptr = &TNC->PORTNAME[0]; - - while (strchr(PNptr, '/')) - PNptr = strchr(PNptr, '/') + 1; - - sprintf(pgm, "DED %s", PNptr); - - TNC->Channels[Num] = Channel; - Channel->BPQStream = FindFreeStream(); - READCHANGE(Channel->BPQStream); // Prevent Initial *** disconnected - Debugprintf("BPQ32 DED Stream %d BPQ Stream %d", Num, Channel->BPQStream ); - - if (TNC->MODE) // if host mode, set appl - SetAppl(Channel->BPQStream, TNC->APPLFLAGS, TNC->APPLICATION); - - strcpy(pgm, "bpq32.exe"); -} - - -BOOL InitializeTNCEmulator() -{ - int resp, i; - ULONG OpenCount = 0; - DWORD Errorval; - int ApplNum = 1; - UINT APPLMASK; - struct TNC2StreamInfo * TNCStream; - - struct TNCDATA * TNC = TNCCONFIGTABLE; - - TNC2TABLE = TNCCONFIGTABLE; - - while (TNC) - { - // Com Port may be a hardware device (ie /dev/ttyUSB0) COMn or VCOMn (BPQ Virtual COM) - - char * Baud = strlop(TNC->PORTNAME, ','); - char * PNptr; - - PNptr = &TNC->PORTNAME[0]; - - // Only show last element of name on Streams display - - while (strchr(PNptr, '/')) - { - PNptr = strchr(PNptr, '/') + 1; - } - switch (TNC->Mode) - { - case TNC2: - - sprintf(pgm, "TNC2 %s", PNptr); - - // Start with number of streams, can add or remove with USRES command - - if (TNC->Users == 0) - TNC->Users = TNC->HOSTSTREAMS; - - if (TNC->Users == 0) - TNC->Users = TNC->HOSTSTREAMS = 1; - else - TNC->HOSTSTREAMS = TNC->Users; - - Debugprintf("TNC2 USers = %d, HOSTSTREAMS = %d\n", TNC->Users, TNC->HOSTSTREAMS); - - - for (i = 0; i < TNC->HOSTSTREAMS; i++) - { - TNCStream = TNC->TNC2Stream[i] = zalloc(sizeof(struct TNC2StreamInfo)); - - TNCStream->BPQPort = FindFreeStream(); - - if - (TNCStream->BPQPort == 0) - { - Debugprintf("Insufficient free Streams for TNC2 Emulator"); - return FALSE; - } - - READCHANGE(TNCStream->BPQPort); // Prevent Initial *** disconnected - - TNCStream->MODEFLAG = COMMAND; - - if (TNC->CONOK) - SetAppl(TNCStream->BPQPort, TNC->APPLFLAGS, TNC->APPLICATION); - else - SetAppl(TNCStream->BPQPort, TNC->APPLFLAGS, 0); - - } - - strcpy(pgm, "bpq32.exe"); - - if (TNC->TPACLEN == 0) - TNC->TPACLEN = PACLEN; // TNC PACLEN - - break; - - case DED: - - if (TNC->HOSTSTREAMS == 0) - TNC->HOSTSTREAMS = 4; // Default - - TNC->MALL = 1; - TNC->MTX = 1; - TNC->MCOM = 1; - TNC->MMASK = -1; // MONITOR MASK FOR PORTS - TNC->TPACLEN = PACLEN; // TNC PACLEN - - for (i = 1; i <= TNC->HOSTSTREAMS; i++) - { - AllocateDEDChannel(TNC, i); // Also used by Y command handler - } - - TNC->Channels[0] = zalloc(sizeof(struct StreamInfo)); - memcpy(TNC->Channels[0], TNC->Channels[1], sizeof(struct StreamInfo)); // For monitoring - - break; - - case KANTRONICS: - - sprintf(pgm, "KANT %s", PNptr); - - if (TNC->HOSTSTREAMS == 0) - TNC->HOSTSTREAMS = 1; // Default - - for (i = 0; i <= TNC->HOSTSTREAMS; i++) - { - struct StreamInfo * Channel; - - // Use Stream zero for defaults - - TNC->Channels[i] = malloc(sizeof (struct StreamInfo)); - memset(TNC->Channels[i], 0, sizeof (struct StreamInfo)); - - Channel = TNC->Channels[i]; - - Channel->BPQStream = FindFreeStream(); - READCHANGE(Channel->BPQStream); // Prevent Initial *** disconnected - - Debugprintf("BPQ32 KANT Init Stream %d BPQ Stream %d", i, Channel->BPQStream ); - - // channel->Chan_TXQ = 0; - // channel->BPQStream = 0; - // channel->Connected = FALSE; - // channel->MYCall[0] = 0; - - } - break; - - case SCS: - - TNC->ECHOFLAG = 1; - - if (TNC->HOSTSTREAMS == 0) - TNC->HOSTSTREAMS = 1; // Default - - TNC->MALL = 1; - TNC->MCOM = 1; - TNC->MMASK = -1; // MONITOR MASK FOR PORTS - TNC->TPACLEN = PACLEN; // TNC PACLEN - - sprintf(pgm, "SCS %s", PNptr); - - for (i = 1; i <= TNC->HOSTSTREAMS; i++) - { - struct StreamInfo * Channel = zalloc(sizeof(struct StreamInfo)); - - TNC->Channels[i] = Channel; - - Channel->BPQStream = FindFreeStream(); - READCHANGE(Channel->BPQStream); // Prevent Initial *** disconnected - - Debugprintf("BPQ32 SCS Init Stream %d BPQ Stream %d", i, Channel->BPQStream ); - } - - TNC->Channels[0] = zalloc(sizeof(struct StreamInfo)); - memcpy(TNC->Channels[0], TNC->Channels[1], sizeof(struct StreamInfo)); // For monitoring - - strcpy(pgm, "bpq32.exe"); - - break; - - } - - if (Baud) - TNC->Speed = atoi(Baud); - else - TNC->VCOM = TRUE; - - if (_memicmp(TNC->PORTNAME, "COM", 3) == 0) - { - TNC->VCOM = FALSE; - } - else - { - if (_memicmp(TNC->PORTNAME, "VCOM", 4) == 0) - TNC->ComPort = atoi(&TNC->PORTNAME[4]); - } - if (TNC->VCOM == 0) - { - // Real port - - TNC->hDevice = OpenCOMPort(TNC->PORTNAME, TNC->Speed, TRUE, TRUE, FALSE, 0); - - TNC->PortEnabled = 1; - - TNC->RTS = 1; -// TNC->DTR = 1; - } - else - { - // VCOM Port -#ifdef WIN32 - TNC->hDevice = BPQOpenSerialPort(TNC, &Errorval); -#else - TNC->hDevice = LinuxOpenPTY(TNC->PORTNAME); -#endif - if (TNC->hDevice != (HANDLE) -1) - { - if (TNC->NewVCOM == 0) - { - resp = BPQSerialIsCOMOpen(TNC->hDevice, &OpenCount); - TNC->PortEnabled = OpenCount; - } - - resp = BPQSerialSetCTS(TNC->hDevice); - resp = BPQSerialSetDSR(TNC->hDevice); - - TNC->CTS = 1; - TNC->DSR = 1; - } - else - { - Consoleprintf("TNC - Open Failed for Port %s", TNC->PORTNAME); - TNC->hDevice = 0; - } - } - - if (TNC->hDevice) - { - // Set up buffer pointers - - TNC->PUTPTR = TNC->GETPTR = &TNC->TOUSERBUFFER[0]; - TNC->RXCOUNT = 0; - TNC->CURSOR = &TNC->TONODEBUFFER[0]; // RESET MESSAGE START - TNC->MSGLEN = 0; - - TNC->VLSR = 0x20; - TNC->VMSR = 0x30; - -/* PUSH ECX - - MOV ESI,OFFSET UNPROTOCALL - CALL DECODECALLSTRING - - LEA EDI,UNPROTO[EBX] - MOV ECX,56 - REP MOVSB ; UNPROTO ADDR - - POP ECX -*/ - - APPLMASK = TNC->APPLICATION; - ApplNum = 1; - - while (APPLMASK && (APPLMASK & 1) == 0) - { - ApplNum++; - APPLMASK >>= 1; - } - - memcpy(TNC->MYCALL, &APPLCALLTABLE[ApplNum-1].APPLCALL_TEXT, 10); - - if (TNC->MYCALL[0] < '0') - memcpy(TNC->MYCALL, MYNODECALL, 10); - - strlop(TNC->MYCALL, ' '); - } - - TNC = TNC->Next; - } - -#ifdef LINBPQ - strcpy(pgm, "LinBPQ"); -#else - strcpy(pgm, "bpq32.exe"); -#endif - Consoleprintf("TNC Emulator Init Complete"); - - _beginthread(TNCBGThread,0,0); - - return TRUE; -} - -VOID CloseTNCEmulator() -{ - struct TNCDATA * TNC = TNC2TABLE; // malloc'ed - int i, Stream; - - TNCRUNNING = FALSE; - - while (TNC) - { - if (TNC->Mode == TNC2) - { - Stream = TNC->BPQPort; - - SetAppl(Stream, 0, 0); - Disconnect(Stream); - READCHANGE(Stream); // Prevent Initial *** disconnected - DeallocateStream(Stream); - } - else - { - for (i = 1; i <= TNC->HOSTSTREAMS; i++) - { - Stream = TNC->Channels[i]->BPQStream; - - SetAppl(Stream, TNC->APPLFLAGS, 0); - Disconnect(Stream); - READCHANGE(Stream); // Prevent Initial *** disconnected - DeallocateStream(Stream); - } - } - CloseCOMPort(TNC->hDevice); - - TNC = TNC->Next; - } -} - -VOID TNCTimer() -{ - // 100 Ms Timer - - struct TNCDATA * TNC = TNC2TABLE; - struct StreamInfo * channel; - int n; - - int NeedTrace = 0; - - while (TNC) - { - if (TNC->Mode != TNC2) - goto NotTNC2; - - NeedTrace |= TNC->TRACEFLAG; //SEE IF ANY PORTS ARE MONITORING - - // CHECK FOR PACTIMER EXPIRY AND CMDTIME - - if (TNC->CMDTMR) - { - TNC->CMDTMR--; - - if (TNC->CMDTMR == 0) - { - // CMDTMR HAS EXPIRED - IF 3 COMM CHARS RECEIVED, ENTER COMMAND MODE - - if (TNC->COMCOUNT == 3) - { - // 3 ESCAPE CHARS RECEIVED WITH GUARDS - LEAVE TRAN MODE - - SETCOMM00(TNC); - - goto TIM100; //DONT RISK TRANSTIMER AND CMDTIME FIRING AT ONCE - } - - TNC->CMDTMR = 0; // RESET COUNT - goto TIM100; - - } - } - - if (TNC->TRANSTIMER) - { - TNC->TRANSTIMER--; - if (TNC->TRANSTIMER == 0) - { - if (TNC->MSGLEN) // ?MESSAGE ALREADY SENT - SENDPACKET(TNC); - } - } -TIM100: - // CHECK FLOW CONTROL - - if ((TNC->VMSR & 0x20)) // ALREADY OFF? - { - CHECKCTS(TNC); // No, so check - } - - goto NextTNC; - -NotTNC2: - - for (n = 1; n <= TNC->HOSTSTREAMS; n++) - { - channel = TNC->Channels[n]; - - if (channel->CloseTimer) - { - channel->CloseTimer--; - if (channel->CloseTimer == 0) - Disconnect(channel->BPQStream); - } - } -NextTNC: - TNC = TNC->Next; - } - DOMONITORING(NeedTrace); -} - -/* -#ifndef WIN32 - -int TNCReadCOMBlock(HANDLE fd, char * Block, int MaxLength, int * err) -{ - int Length; - - *err = 0; - - Length = read(fd, Block, MaxLength); - - if (Length < 0) - { - if (errno != 11 && errno != 35) // Would Block - *err = errno; - - return 0; - } - - return Length; -} - -#endif -*/ - -void CheckForConnectStatusChange(struct TNCDATA * TNC); -void CheckForHostStatusChange(struct TNCDATA * TNC); -void CheckForDataFromHost(struct TNCDATA * TNC); -void CheckForDataFromTerminal(struct TNCDATA * TNC); - -int isTNCBusy(struct TNCDATA * TNC) -{ - // if using old VCOM check Q - -#ifdef WIN32 - - if (TNC->VCOM) - { - if (TNC->NewVCOM == 0) - { - int TXCount, RXCount; - - BPQSerialGetQCounts(TNC->hDevice, &RXCount, &TXCount); - - if (TXCount > 4096) - return TRUE; // Busy - - return FALSE; - } - - // Windows New VCOM cant check (I think!) - } - -#endif - - // - - return FALSE; - -} - -VOID TNCPoll() -{ - struct TNCDATA * TNC = TNC2TABLE; // malloc'ed - - // This logic had got very convoluted. This Tries - // to rationalize it - - while (TNC) - { - if (TNC->hDevice) - { - CheckForConnectStatusChange(TNC); - CheckForHostStatusChange(TNC); - CheckForDataFromHost(TNC); - CheckForDataFromTerminal(TNC); - } - - TNC = TNC->Next; - } -} - -void CheckForConnectStatusChange(struct TNCDATA * TNC) -{ -#ifdef WIN32 - if (TNC->VCOM && TNC->NewVCOM == 0) - { - // Can check if other end is connected - - int ConCount = 0; - - BPQSerialIsCOMOpen(TNC->hDevice, &ConCount); - - if (TNC->PortEnabled == 1 && ConCount == 0) - - // Connection has just closed - if connected, disconnect stream - - // This should close all streams on multistream port - - SessionControl(TNC->BPQPort, 2, 0); - - if (TNC->PortEnabled != ConCount) - { - TNC->PortEnabled = ConCount; - } - } -#endif -} - -void CheckForHostStatusChange(struct TNCDATA * TNC) -{ - if (TNC->Mode == KANTRONICS) - { - // Have to poll for Data and State changes - - int n, state, change; - struct StreamInfo * Channel; - - for (n = 1; n <= TNC->HOSTSTREAMS; n++) - { - Channel = TNC->Channels[n]; - - SessionState(Channel->BPQStream, &state, &change); - - if (change == 1) - { - if (state == 1) - - // Connected - - KANTConnected(TNC, Channel, n); - else - KANTDisconnected(TNC, Channel, n); - } - } - return; - } - - // ?? Should other modes check here ?? -} - -void CheckForDataFromHost(struct TNCDATA * TNC) -{ - unsigned int n; - int retval, more; - char TXMsg[1000]; - ULONG Read = 0; - - // I think we should check for space in TNC to Terminal Buffer - - if (TNC->RXCOUNT + 500 > TNCBUFFLEN) - return; - - // Only KANTRONICS and TNC2 check for data here - // DED and SCS check when polled by Host Program - - if (TNC->Mode == KANTRONICS) - { - // Have to poll for Data and State changes - - int n, len, count; - struct StreamInfo * Channel; - UCHAR Buffer[400]; - - for (n = 1; n <= TNC->HOSTSTREAMS; n++) - { - Channel = TNC->Channels[n]; - - do - { - if (TNC->RXCOUNT + 500 > TNCBUFFLEN) - return; - - GetMsg(Channel->BPQStream, &Buffer[3], &len, &count); - - if (len > 0) - { - // If a failure, set a close timer (for Airmail, etc) - - if (strstr(&Buffer[3], "} Downlink connect needs port number") || - strstr(&Buffer[3], "} Failure with ") || - strstr(&Buffer[3], "} Sorry, ")) - Channel->CloseTimer = CloseDelay * 10; - - else - Channel->CloseTimer = 0; // Cancel Timer - - if (TNC->MODE) - { - Buffer[0] = 'D'; - Buffer[1] = '1'; - Buffer[2] = n + '@'; - SendKISSData(TNC, Buffer, len+3); - } - else - SendDataToTNC(TNC, &Buffer[3], len); - } - } - while (0); //(count > 0); - } - return; - } - - if (TNC->Mode == SCS) - return; - - n = 0; - -getloop: - - TNC2GetChar(TNC, &retval, &more); - - if (retval != -1) - TXMsg[n++] = retval; - - if (more > 0 && n < 1000) goto getloop; - - if (n > 0) - WriteCOMBlock(TNC->hDevice, TXMsg, n); - - return; - -} -/* Where does this go ?? - -// We look for change on current RX Stream - - retval = TNCGetVMSR(TNC, TNC->TNC2Stream[TNC->RXStream], TRUE); - - if ((retval & 8) == 8) //' DCD (Connected) Changed - { - TNC->DCD = (retval & 128) / 128; - - if (TNC->DCD == 1) - BPQSerialSetDCD(TNC->hDevice); - else - BPQSerialClrDCD(TNC->hDevice); - } - - if ((retval & 1) == 1) //' CTS (Flow Control) Changed - { - TNC->CTS = (retval & 16) / 16; - - if (TNC->CTS == 1) - BPQSerialSetCTS(TNC->hDevice); - else - BPQSerialClrCTS(TNC->hDevice); - - } - - BPQSerialGetDTRRTS(TNC->hDevice,&ModemStat); - - - if ((ModemStat & 1) != TNC->DTR) - { - TNC->DTR=!TNC->DTR; - } - - if ((ModemStat & 2) >> 1 != TNC->RTS) - { - TNC->RTS=!TNC->RTS; - } - - TNC = TNC->Next; - continue; - } -#endif - { - // Real Port or Linux Virtual - - int Read, n; - int retval, more; - char TXMsg[500]; -#ifndef WIN32 - int err; - - // We can tell if partner has gone on PTY Pair - read returns 5 - - if (TNC->Mode == KANTRONICS || TNC->Mode == SCS) - Read = TNCReadCOMBlock(TNC->hDevice, &TNC->TOUSERBUFFER[TNC->RXBPtr], 1000 - TNC->RXBPtr, &err); - else - Read = TNCReadCOMBlock(TNC->hDevice, rxbuffer, 1000, &err); - - if (err) - { - if (TNC->PortEnabled) - { - TNC->PortEnabled = FALSE; - DisableAppl(TNC); - Debugprintf("Device %s closed", TNC->PORTNAME); - } - } - else - TNC->PortEnabled = TRUE; - -#else - if (TNC->Mode == KANTRONICS || TNC->Mode == SCS) - Read = ReadCOMBlock(TNC->hDevice, &TNC->TOUSERBUFFER[TNC->RXBPtr], 1000 - TNC->RXBPtr); - else - Read = ReadCOMBlock(TNC->hDevice, rxbuffer, 1000); -#endif - - if (Read) - { - if (TNC->Mode == TNC2) - { - for (n = 0; n < Read; n++) - TNC2PutChar(TNC, rxbuffer[n]); - } - else if (TNC->Mode == DED) - { - for (n = 0; n < Read; n++) - TfPut(TNC, rxbuffer[n]); - } - else if (TNC->Mode == KANTRONICS) - { - TNC->RXBPtr += Read; - ProcessPacket(TNC, TNC->TOUSERBUFFER, TNC->RXBPtr); - } - else if (TNC->Mode == SCS) - { - TNC->RXBPtr += Read; - ProcessSCSPacket(TNC, TNC->TOUSERBUFFER, TNC->RXBPtr); - } - } - - n=0; - - getloopR: - - TNC2GetChar(TNC, &retval, &more); - - if (retval != -1) - TXMsg[n++] = retval; - - if (more > 0 && n < 500) goto getloopR; - - if (n > 0) - - { - resp = WriteCOMBlock(TNC->hDevice, TXMsg, n); - } - } - TNC = TNC->Next; - } -} -*/ - - -void CheckForDataFromTerminal(struct TNCDATA * TNC) -{ - unsigned int n; - char rxbuffer[1000]; - ULONG Read = 0, resp; - - if (TNC->Mode == KANTRONICS) - resp = GetDataFromTNC(TNC, &TNC->TOUSERBUFFER[TNC->RXBPtr], 1000 - TNC->RXBPtr, &Read); - - else if (TNC->Mode == SCS) - resp = GetDataFromTNC(TNC, &TNC->FROMUSERBUFFER[TNC->FROMUSERLEN], TNCBUFFLEN - TNC->FROMUSERLEN, &Read); - - else - resp = GetDataFromTNC(TNC, rxbuffer, 1000, &Read); - - if (Read) - { - if (TNC->Mode == TNC2) - { - for (n = 0; n < Read; n++) - TNC2PutChar(TNC, rxbuffer[n]); - } - else if (TNC->Mode == DED) - { - for (n = 0; n < Read; n++) - TfPut(TNC, rxbuffer[n]); - } - else if (TNC->Mode == KANTRONICS) - { - TNC->RXBPtr += Read; - ProcessPacket(TNC, TNC->TOUSERBUFFER, TNC->RXBPtr); - } - else if (TNC->Mode == SCS) - { - TNC->FROMUSERLEN += Read; - ProcessSCSPacket(TNC, TNC->FROMUSERBUFFER, TNC->FROMUSERLEN); - } - } -} - - -int APIENTRY SetTraceOptionsEx(int mask, int mtxparam, int mcomparam, int monUIOnly); - - -VOID DOMONITORING(int NeedTrace) -{ - // IF ANY PORTS HAVE MONITOR ENABLED, SET MONITOR BIT ON FIRST PORT - - struct TNCDATA * TNC = TNC2TABLE; // malloc'ed - int Tracebit = 0, len, count, n; - time_t Stamp; - ULONG SaveMMASK = MMASK; - BOOL SaveMTX = MTX; - BOOL SaveMCOM = MCOM; - BOOL SaveMUI = MUIONLY; - - if (NeedTrace) - Tracebit = 0x80; - - if (TNC->CONOK) - SetAppl(TNC->BPQPort, TNC->APPLFLAGS | Tracebit, TNC->APPLICATION); - else - SetAppl(TNC->BPQPort, TNC->APPLFLAGS | Tracebit, 0); - - Stamp = GetRaw(TNC->BPQPort, (char *)&MONITORDATA, &len, &count); - - if (len == 0) - return; - - len = DecodeFrame(&MONITORDATA, MONBUFFER, Stamp); - - while (TNC) - { - if (TNC->Mode == TNC2 && TNC->TRACEFLAG) - { - SetTraceOptionsEx(TNC->MMASK, TNC->MTX, TNC->MCOM, 0); - len = IntDecodeFrame(&MONITORDATA, MONBUFFER, Stamp, TNC->MMASK, FALSE, FALSE); -// printf("%d %d %d %d %d\n", len, MMASK, MTX, MCOM, MUIONLY); - SetTraceOptionsEx(SaveMMASK, SaveMTX, SaveMCOM, SaveMUI); - - if (len) - { - for (n = 0; n < len; n++) - { - PUTCHARINBUFFER(TNC, MONBUFFER[n]); - } - } - } - TNC=TNC->Next; - } -} - - -VOID TNC2PutChar(struct TNCDATA * TNC, int Char) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - if (TNCStream->MODEFLAG & COMMAND) - goto KEYB06C; // COMMAND MODE - SKIP TRANS TEST - - if (TNCStream->MODEFLAG & TRANS) - goto KEYB06T; // TRANS MODE - - // CONV MODE - SEE IF CPACTIME ON - - if (TNC->CPACTIME) - TNC->TRANSTIMER = TRANSDELAY; - - goto KEYB06; // PROCESS CHAR - -KEYB06T: - -// Transparent Mode - See if Escape Sequence Received (3 esc chars, with guard timer) - -// CHECK FOR COMMAND CHAR IF CMDTIME EXPIRED OR COMAND CHAR ALREADY RECEIVED - - if (TNC->COMCOUNT) - goto KBTRN3; // ALREADY GOT AT LEAST 1 - - if (TNC->CMDTMR) - goto KBTRN5; // LESS THAN CMDTIME SINCE LAST CHAR - -KBTRN3: - - if (Char != TNC->COMCHAR) - { - TNC->COMCOUNT = 0; - goto KBTRN5; // NOT COMMAND CHAR - } - - TNC->COMCOUNT++; - -KBTRN5: - - TNC->CMDTMR = TNC->CMDTIME; // REPRIME ESCAPE TIMER - - TNC->TRANSTIMER = TRANSDELAY; - - KBNORM(TNC, Char); - return; // TRANSPARENT MODE - -KEYB06: - -// STILL JUST CONV MODE - - if (Char != TNC->SENDPAC) - goto NOTSENDPAC; - -// SEND PACKET CHAR - SHOUD WE SEND IT? - - TNC->TRANSTIMER = 0; - - if (TNC->CRFLAG) - KBNORM(TNC, Char); // PUT CR IN BUFFER - - SENDPACKET(TNC); - return; - - -NOTSENDPAC: -KEYB06C: - - // COMMAND OR CONV MODE - - // Check for Escaped - - if (TNC->InEscape) - { - TNC->InEscape = 0; - KBNORM(TNC, Char); // Process as normal chars - return; - } - - if (TNC->InStreamSW) - { - TNC->InStreamSW = 0; - - if (Char != TNC->StreamSW) - { - // Switch TX Stream if valid - - int n; - - if (TNC->ECHOFLAG) - KBECHO(TNC, Char); - - if (TNC->LCStream) - Char = toupper(Char); - - n = Char - 'A'; - - if (n >= 0 && TNC->TNC2Stream[n]) - TNC->TXStream = n; - - return; - } - } - - if (Char == TNC->PASSCHAR) - { - TNC->InEscape = 1; - return; - } - - - - if (TNC->StreamSW && Char == TNC->StreamSW) - { - TNC->InStreamSW = 1; - - if (TNC->ECHOFLAG) - KBECHO(TNC, Char); - - return; - } - - if (Char < 32) // control - { - if (Char == 10 && TNC->LFIGNORE) - return; - - if (Char == 8) - { - if (TNC->MSGLEN == 0) - return; - - TNC->MSGLEN--; - TNC->CURSOR--; - - if (TNC->ECHOFLAG) - { - KBECHO(TNC, Char); // Delete char from display - KBECHO(TNC, ' '); - KBECHO(TNC, Char); - } - return; - } - - if (Char == 26) // Ctrl/Z - { - KBNORM(TNC, Char); // FOR MBX TERMINATOR - return; - } - - if (Char == TNC->COMCHAR) - { - SETCOMMANDMODE(TNC); - return; - } - - if (TNCStream->MODEFLAG & COMMAND) - { - if (Char == 0x14) // CTRL/T - { - TNC->TRACEFLAG ^= 1; - return; - } - - if (Char == 13) - { - KBNORM(TNC, 13); // PUT CR IN BUFFER - SENDPACKET(TNC); - return; - } - } - KBNORM(TNC, Char); // Process others as normal chars - } KBNORM(TNC, Char); -} - -VOID KBNORM(struct TNCDATA * TNC, int Char) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - if (TNC->MSGLEN > 256) - goto TOOLONG; // PROTECT BUFFER - - *(TNC->CURSOR++) = Char; - TNC->MSGLEN++; - -TOOLONG: - - if (TNC->ECHOFLAG) - KBECHO(TNC, Char); - - if (TNC->MSGLEN < TNCStream->TPACLEN) - return; - -// DONT APPLY PACLEN IN COMMAND MODE - - if (TNCStream->MODEFLAG & COMMAND) - return; - - SENDPACKET(TNC); // Send what we have -} - - -VOID SETCOMMANDMODE(struct TNCDATA * TNC) -{ - if (TNC->MSGLEN) - SENDPACKET(TNC); - - SETCOMM00(TNC); -} - -VOID SETCOMM00(struct TNCDATA * TNC) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - TNCStream->MODEFLAG |= COMMAND; // BACK TO COMMAND MODE - TNCStream->MODEFLAG &= ~(CONV+TRANS); - TNC->TRANSTIMER = 0; // CANCEL TRANS MODE SEND TIMER - TNC->AUTOSENDFLAG = 0; // IN CASE ALREADY SET - - CheckForStreamChange(TNC, TNC->TXStream); // Send Stream Switched Message if changed - - SENDREPLY(TNC, CMDMSG, 4); - - TNC->CURSOR = &TNC->TONODEBUFFER[0]; // RESET MESSAGE START - TNC->MSGLEN = 0; -} - - - -VOID SENDPACKET(struct TNCDATA * TNC) -{ - // SEE IF COMMAND STATE - - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - int Stream = 0; // Unprooto - - if (TNCStream->MODEFLAG & COMMAND) - { - TNCCOMMAND(TNC); // COMMAND TO TNC - TNC->CURSOR = &TNC->TONODEBUFFER[0]; // RESET MESSAGE START - TNC->MSGLEN = 0; - return; - } - - // IF CONNECTED, SEND TO L4 (COMMAND HANDLER OR DATA), - // OTHERWISE SEND AS AN UNPROTO FRAME (TO ALL PORTS) - - - if (TNCStream->VMSR & 0x80) // CONNECTED? - Stream = TNCStream->BPQPort; - - SendMsg(Stream, TNC->TONODEBUFFER, TNC->MSGLEN); - - TNC->CURSOR = &TNC->TONODEBUFFER[0]; // RESET MESSAGE START - TNC->MSGLEN = 0; - - CHECKCTS(TNC); // SEE IF NOW BUSY - - return; -} - -VOID KBECHO(struct TNCDATA * TNC, int Char) -{ - PUTCHARINBUFFER(TNC, Char); -} - -VOID TNCCOMMAND(struct TNCDATA * TNC) -{ - // PROCESS COMMAND TO TNC CODE - - char * ptr, * ptr1, * ptr2; - int n; - CMDX * CMD; - - *(--TNC->CURSOR) = 0; - - - strcat(TNC->TONODEBUFFER, " "); - - ptr = strchr(TNC->TONODEBUFFER, ' '); - - if (ptr) - { - // convert command to upper case, leave tail - - *ptr = 0; - _strupr(TNC->TONODEBUFFER); - *ptr = ' '; - } - - if (_memicmp(ptr, " switch", 7) == 0) - _strupr(ptr); // Special Case - - ptr1 = &TNC->TONODEBUFFER[0]; // - - n = 10; - - while ((*ptr1 == ' ' || *ptr1 == 0) && n--) - ptr1++; // STRIP LEADING SPACES and nulls (from keepalive) - - if (n == -1) - { - // Null command - - SENDREPLY(TNC, CMDMSG, 4); - return; - } - - ptr2 = ptr1; // Save - - CMD = &COMMANDLIST[0]; - n = 0; - - for (n = 0; n < NUMBEROFTNCCOMMANDS; n++) - { - int CL = CMD->CMDLEN; - - ptr1 = ptr2; - - // ptr1 is input command - - if (memcmp(CMD->String, ptr1, CL) == 0) - { - // Found match so far - check rest - - char * ptr2 = &CMD->String[CL]; - - ptr1 += CL; - - if (*(ptr1) != ' ') - { - while(*(ptr1) == *ptr2 && *(ptr1) != ' ') - { - ptr1++; - ptr2++; - } - } - - if (*(ptr1) == ' ') - { - ptr1++; // Skip space - - CMD->CMDPROC(TNC, ptr1, CMD); - SENDREPLY(TNC, CMDMSG, 4); - - return; - } - } - - CMD++; - - } - - SENDREPLY(TNC, WHATMSG, 8); - -} - -/* -; -UNPROTOCMD: -; -; EXTRACT CALLSIGN STRING -; - CMP BYTE PTR [ESI],20H - JE UNPROTODIS - - CMP BYTE PTR [ESI],"*" - JE CLEARUNPROTO - - CALL DECODECALLSTRING ; CONVERT TO AX25 FORMAT - - JZ UNPROTOOK - - JMP TNCDUFF - -CLEARUNPROTO: - - LEA EDI,UNPROTO[EBX] - MOV AL,0 - MOV ECX,63 - REP STOSB ; COPY IN - -UNPROTODIS: - - MOV AL,1 - CALL DISPLAYUNPROTO ; DISPLAY CURRENT SETTING - JMP SENDOK - -UNPROTOOK: - - PUSH ESI - MOV AL,0 - CALL DISPLAYUNPROTO ; DISPLAY OLD STRRING - POP ESI - - LEA EDI,UNPROTO[EBX] - MOV ECX,63 - REP MOVSB ; COPY IN -CONMODE: - JMP SENDOK -;CONMODE: - JMP KBRET - -DISPLAYUNPROTO: -; - PUSH EAX - - MOV ESI,OFFSET UNPROT - MOV ECX,8 - CALL PUTSTRINGINBUFFER - - MOV ESI,OFFSET WAS ; DISPLAY "was" - MOV ECX,5 - - POP EAX - OR AL,AL - JZ DISPU00 ; NO - - MOV ECX,1 ; LEAVE OUT "WAS" - -DISPU00: - - CALL PUTSTRINGINBUFFER - - LEA ESI,UNPROTO[EBX] - CMP BYTE PTR [ESI],40H - JBE DISPUPRET - - CALL CONVFROMAX25 - - PUSH ESI - - MOV ESI,OFFSET NORMCALL - - CALL PUTSTRINGINBUFFER - - POP ESI - - CMP BYTE PTR [ESI],0 - JE DISPUPRET - - PUSH ESI - - MOV ESI,OFFSET VIA - MOV ECX,5 - CALL PUTSTRINGINBUFFER - - POP ESI - -DISPUPLOOP: - - CALL CONVFROMAX25 - - PUSH ESI - MOV ESI,OFFSET NORMCALL - INC ECX - CALL PUTSTRINGINBUFFER - POP ESI - - CMP BYTE PTR [ESI],0 - JNE DISPUPLOOP - - -DISPUPRET: - MOV AL,0DH - CALL PUTCHARINBUFFER - RET - - -BTEXT: -; - CMP BYTE PTR [ESI],20H - JE BTDIS -; - PUSH ESI - MOV AL,0 - CALL DISPLAYBT ; DISPLAY OLD STRING - POP ESI - - MOV EDI,OFFSET BTEXTFLD - MOV ECX,255 -BTLOOP: - LODSB - STOSB - CMP ESI,CMDENDADDR ; END? - JE BTEND - - LOOP BTLOOP -BTEND: - XOR AL,AL - STOSB ; NULL ON END -; -; SET UP TO SEND IT AS A UI -; - MOV ECX,EDI - MOV ESI,OFFSET BTHDDR - SUB ECX,ESI - MOV MSGLENGTH[ESI],CX -; -; PASS TO SWITCH -; - MOV ESI,OFFSET BTEXTFLD - SUB ECX,6 ; DONT NEED HEADER - - MOV AH,12 ; UPDATE FUNCTIONS - MOV DX,1 ; UPDATE BT - - CALL NODE ; PASS TO NODE - - JMP SENDOK - -BTDIS: - MOV AL,1 - CALL DISPLAYBT ; DISPLAY CURRENT SETTING - JMP SENDOK - - -DISPLAYBT: -; - PUSH EAX - - MOV ESI,OFFSET BTCMD - MOV ECX,8 - CALL PUTSTRINGINBUFFER - - MOV ESI,OFFSET WAS ; DISPLAY "was" - MOV ECX,5 - - POP EAX - OR AL,AL - JZ DISPBT00 ; NO - - MOV ECX,1 ; LEAVE OUT "WAS" - -DISPBT00: - CALL PUTSTRINGINBUFFER - - MOV ESI,OFFSET BTEXTFLD -DISPBT10: - LODSB - OR AL,AL - JZ DISPBT20 - - CALL PUTCHARINBUFFER - - JMP DISPBT10 - -DISPBT20: - MOV AL,0DH - CALL PUTCHARINBUFFER - RET - - -*/ - -VOID DOCONMODECHANGE(struct TNCDATA * TNC, int Stream) -{ - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[Stream]; - - TNCStream->VMSR |= 0x88; // SET CONNECTED - - // IF NOMODE IS ON LEAVE IN TNC COMMAND MODE, ELSE PUT INTO CONV MODE - // (MAY NEED TO IMPLEMENT CONMODE SOMETIME) - - if (TNC->NOMODE) - return; - - TNCStream->MODEFLAG |= CONV; // INTO CONVERSE MODE - TNCStream->MODEFLAG &= ~(COMMAND+TRANS); -} - -VOID SENDREPLY(struct TNCDATA * TNC, char * Msg, int Len) -{ - int n = 0; - - CheckForStreamChange(TNC, TNC->TXStream); // Send Stream Switched Message if changed - - for (n= 0; n < Len; n++) - { - PUTCHARINBUFFER(TNC, Msg[n]); - } -} - - -VOID SEND_CONNECTED(struct TNCDATA * TNC, int ToStream) -{ - // SEND TAPR-STYLE *** CONNECTED TO CURRENT PORT - - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[ToStream]; - - int len; - char Response[128]; - char Call[11] = ""; - int paclen, dummy; - BPQVECSTRUC * SESS; - TRANSPORTENTRY * L4 = NULL; - int stream; - - GetConnectionInfo(TNCStream->BPQPort, Call, &dummy, &dummy, &paclen, &dummy, &dummy); - - if (paclen) - TNCStream->TPACLEN = paclen; - - if (TNCStream->MODEFLAG & TRANS) - return; //NOT IF TRANSPARENT - - strlop(Call, ' '); - - strcpy(TNCStream->RemoteCall, Call); - - CheckForStreamChange(TNC, ToStream); // Send Stream Switched Message if changed - - if (TNC->CBELL) - len = sprintf(Response, "%s%s%c\r", CONMSG, Call, 7); // Add BELL char - else - len = sprintf(Response, "%s%s\r", CONMSG, Call); - - SENDREPLY(TNC, Response, len); - - // If incoming session Send CTEXT if set - - stream = TNCStream->BPQPort; - stream--; // API uses 1 - 64 - - if (stream < 0 || stream > 63) - return; - - SESS = &BPQHOSTVECTOR[stream]; - - if (SESS && SESS->HOSTSESSION) - L4 = SESS->HOSTSESSION; - - if (L4 && (L4->L4CIRCUITTYPE & DOWNLINK)) - { - if (TNC->CMSG && TNC->CTEXT[0]) - { - // Add CTEXT - int n; - char Msg[256]; - - n = sprintf(Msg, "%s\r", TNC->CTEXT); - SendMsg(TNCStream->BPQPort, Msg, n); - } - - // if CHECK_FOR_ESC set in applflags send "^d to disconnect msg - - if ((TNC->APPLFLAGS & CHECK_FOR_ESC)) // If incoming session - { - char Msg[] = "Send ^D to disconnect\r"; - - SendMsg(TNCStream->BPQPort, Msg, (int)strlen(Msg)); - } - } -} - -VOID PUTCHARINBUFFER(struct TNCDATA * TNC, int Char) -{ - // CALLED BY L4 CODE TO PASS DATA TO VIRTUAL TNC - ; - if (TNC->RXCOUNT >= TNCBUFFLEN) - { - // OVERRUN - LOSE IT - - TNC->VLSR |= 2; // SET OVERRUN ERROR - return; - } - - TNC->VLSR &= ~2; // CLEAR OVERRRUN - - *(TNC->PUTPTR++) = Char; - TNC->RXCOUNT++; - - if (TNC->PUTPTR == &TNC->TOUSERBUFFER[TNCBUFFLEN]) - TNC->PUTPTR = &TNC->TOUSERBUFFER[0]; - - if(TNC->RXCOUNT > TNCBUFFLEN-300) // ALLOW FOR FULL PACKET - { - // BUFFER GETTING FULL - DROP RTS/DTR - - TNC->RTSFLAG |= 1; // SET BUSY - } - - if (Char == 13 && TNC->AUTOLF) - PUTCHARINBUFFER(TNC, 10); // Add LF -} - - -VOID CHECKCTS(struct TNCDATA * TNC) -{ - // SEE IF CROSS-SESSION STILL BUSY - - if (RXCount(TNC->BPQPort) > 4) - { - // Busy - - if ((TNC->VMSR & 0x10) == 0) // ALREADY OFF? - return; // No Change - - TNC->VMSR &= 0xef; // Drop CTS - TNC->VMSR |= 1; // Delta bit - return; - } - - // Not busy - - if (TNC->VMSR & 0x10) // ALREADY ON? - return; // No Change - - TNC->VMSR |= 0x11; // CTS AND DELTA CTS -} - - - -VOID CONNECTTONODE(struct TNCDATA * TNC) -{ - char AXCALL[7]; - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - int SaveAuthProg = AuthorisedProgram; - - AuthorisedProgram = 1; - SessionControl(TNCStream->BPQPort, 1, TNC->APPLICATION); - AuthorisedProgram = SaveAuthProg; - - ConvToAX25(TNC->MYCALL, AXCALL); - ChangeSessionCallsign(TNCStream->BPQPort, AXCALL); - - // Set default Paclen - - TNCStream->TPACLEN = TNC->TPACLEN; -} - - -VOID GETDATA(struct TNCDATA * TNC) -{ - // I'm sure this should only be called for TNC2 devices - - struct TNC2StreamInfo * TNCStream = TNC->TNC2Stream[TNC->TXStream]; - - int state, change, InputLen, count, n, i; - char InputBuffer[512]; - - // LOOK FOR STATUS CHANGE - - for (i = 0; i < TNC->HOSTSTREAMS; i++) - { - TNCStream = TNC->TNC2Stream[i]; - - LocalSessionState(TNCStream->BPQPort, &state, &change, TRUE); - - if (change == 1) - { - if (state == 1) // Connected - { - SEND_CONNECTED(TNC, i); - DOCONMODECHANGE(TNC, i); // SET CONNECTED AND CHANGE MODE IF NEEDED - } - else - { - TNCStream->MODEFLAG |= COMMAND; - TNCStream->MODEFLAG &= ~(CONV+TRANS); - - TNCStream->VMSR &= 0x7F; // DROP DCD - TNCStream->VMSR |= 8; // DELTA DCD - - CheckForStreamChange(TNC, i); // Send Stream Switched Message if changed - SENDREPLY(TNC, DISCONNMSG, 18); - } - } - else - { - // No Change - - // VERIFY CURRENT STATE - - if (state == 1) // Connected - { - // SWITCH THINKS WE ARE CONNECTED - - if ((TNCStream->VMSR & 0x80) == 0) - { - // TNC Doesn't - - SEND_CONNECTED(TNC, i); - DOCONMODECHANGE(TNC, i); // SET CONNECTED AND CHANGE MODE IF NEEDED - } - } - else - { - // SWITCH THINKS WE ARE DISCONNECTED - - if (TNCStream->VMSR & 0x80) - { - // We Disagree, so force off - - TNCStream->MODEFLAG |= COMMAND; - TNCStream->MODEFLAG &= ~(CONV+TRANS); - - TNCStream->VMSR &= 0x7F; // DROP DCD - TNCStream->VMSR |= 8; // DELTA DCD - - CheckForStreamChange(TNC, i); // Send Stream Switched Message if changed - SENDREPLY(TNC, DISCONNMSG, 18); - } - } - } - - // SEE IF ANYTHING QUEUED - - if (TNC->RTSFLAG & 1) - continue; - - GetMsg(TNCStream->BPQPort, InputBuffer, &InputLen, &count); - - if (InputLen == 0) - continue; - - CheckForStreamChange(TNC, i); // Send Stream Switched Message if changed - - // if CHECK_FOR_ESC set in APPLFLAGS looks for Disconnect Escape - - if (TNC->APPLFLAGS & CHECK_FOR_ESC) - { - // look for ^D (or ^d) - - if (InputLen == 3) - { - if (_memicmp(InputBuffer, "^D\r", 3) == 0) - { - Disconnect(TNCStream->BPQPort); - continue; - } - } - } - - for (n = 0; n < InputLen; n++) - { - char c = InputBuffer[n]; - - if (TNC->StreamDbl && c == TNC->StreamSW) - PUTCHARINBUFFER(TNC, TNC->StreamSW); - - PUTCHARINBUFFER(TNC, c); - } - } -} - -// DED Mode Support - -unsigned char PARAMREPLY[]="* 0 0 64 10 4 4 10 100 18000 30 2 0 2\r\n"; - -#define PARAMPORT PARAMREPLY[2] - -#define LPARAMREPLY 39 - -unsigned char BADCMDREPLY[]="\x2" "INVALID COMMAND\x0"; - -#define LBADCMDREPLY 17 //sizeof BADCMDREPLY - -unsigned char DATABUSYMSG[]="\x2" "TNC BUSY - LINE IGNORED\x0"; -#define LDATABUSY 25 - -unsigned char BADCONNECT[]="\x2" "INVALID CALLSIGN\x0"; -#define LBADCONNECT 18 - -unsigned char BUSYMSG[]="BUSY fm SWITCH\x0"; - -//unsigned char CONSWITCH[]="\x3" "(1) CONNECTED to \x0"; - -unsigned char DEDSWITCH[]="\x1" "0:SWITCH \x0"; -#define LSWITCH 14 - -unsigned char NOTCONMSG[]="\x1" "CHANNEL NOT CONNECTED\x0"; -#define LNOTCON 23 - -unsigned char ALREADYCONMSG[]="You are already connected on another port\r"; -#define ALREADYLEN 45 - - -byte * EncodeCall(byte * Call); -VOID SENDENFORCINGPACLEN(struct StreamInfo * Channel, char * Msg, int Len); -VOID SENDCMDREPLY(struct TNCDATA * TNC, char * Msg, int Len); -int APIENTRY SetTraceOptionsEx(int mask, int mtxparam, int mcomparam, int monUIOnly); -int DOCOMMAND(struct TNCDATA * conn); -int PROCESSPOLL(struct TNCDATA * TNC, struct StreamInfo * Channel); - - - - -VOID PUTSTRING(struct TNCDATA * conn, UCHAR * Msg) -{ - int len = (int)strlen(Msg); - - while (len) - { - *(conn->PUTPTR++) = *(Msg++); - - if (conn->PUTPTR == &conn->TOUSERBUFFER[TNCBUFFLEN]) - conn->PUTPTR = (UCHAR *)&conn->TOUSERBUFFER; - - conn->RXCOUNT++; - - len--; - } -} - - -int PUTCHARx(struct TNCDATA * conn, UCHAR c) -{ - *(conn->PUTPTR++) = c; - - if (conn->PUTPTR == &conn->TOUSERBUFFER[TNCBUFFLEN]) - conn->PUTPTR = (UCHAR *)&conn->TOUSERBUFFER; - - conn->RXCOUNT++; - - return 0; -} - - - -VOID DisableAppl(struct TNCDATA * TNC) -{ - int i, Stream; - - for (i = 1; i <= TNC->HOSTSTREAMS; i++) - { - Stream = TNC->Channels[i]->BPQStream; - - SetAppl(Stream, TNC->APPLFLAGS, 0); - Disconnect(Stream); - READCHANGE(Stream); // Prevent Initial *** disconnected - } -} - -VOID EnableAppl(struct TNCDATA * TNC) -{ - int i; - - for (i = 1; i <= TNC->HOSTSTREAMS; i++) - { - SetAppl(TNC->Channels[i]->BPQStream, TNC->APPLFLAGS, TNC->APPLICATION); - } -} - -BOOL TfPut(struct TNCDATA * TNC, UCHAR character) -{ - struct StreamInfo * Channel; - TRANSPORTENTRY * L4 = NULL; - - if (!TNC->MODE) - goto CHARMODE; - -// HOST MODE - - if (TNC->HOSTSTATE == 0) - { - TNC->MSGCHANNEL = character; - TNC->HOSTSTATE++; - return TRUE; - } - - if (TNC->HOSTSTATE == 1) - { - TNC->MSGTYPE = character; - TNC->HOSTSTATE++; - return TRUE; - } - - if (TNC->HOSTSTATE == 2) - { - TNC->MSGCOUNT = character; - TNC->MSGLENGTH = character; - TNC->MSGCOUNT++; - TNC->MSGLENGTH++; - TNC->HOSTSTATE++; - - TNC->DEDCURSOR = &TNC->DEDTXBUFFER[0]; - return TRUE; - } - -// RECEIVING COMMAND/DATA - - *(TNC->DEDCURSOR++) = character; - - TNC->MSGCOUNT--; - - if (TNC->MSGCOUNT) - return TRUE; // MORE TO COME - - TNC->HOSTSTATE=0; - - if (TNC->MSGCHANNEL <= TNC->HOSTSTREAMS) - Channel = TNC->Channels[TNC->MSGCHANNEL]; - else - Channel = TNC->Channels[1]; - - DEDPROCESSHOSTPACKET(Channel, TNC); - - TNC->HOSTSTATE = 0; - - return TRUE; - - -CHARMODE: - - if (character == 0x11) return TRUE; - - if (character == 0x18) - { - // CANCEL INPUT - - TNC->CURSOR = (UCHAR *)&TNC->TONODEBUFFER; - - return(TRUE); - } - - *(TNC->CURSOR++) = character; - - if (character == 1 && (TNC->CURSOR > &TNC->TONODEBUFFER[4]) && *(TNC->CURSOR - 2) == 1 && *(TNC->CURSOR - 3) == 1) - { - // Looks like a resync request - Appl thinks we are in host mode - - TNC->MODE = 1; - TNC->CURSOR = (UCHAR *)&TNC->TONODEBUFFER; - EnableAppl(TNC); - - return(TRUE); - } - - - if (TNC->CURSOR == &TNC->TONODEBUFFER[300]) - TNC->CURSOR--; - - if (character == 0x0d) - { - // PROCESS COMMAND (UNLESS HOST MODE) - - *(TNC->CURSOR++) = 0; - - DOCOMMAND(TNC); - } - return TRUE; -} - - -int DEDPROCESSHOSTPACKET(struct StreamInfo * Channel, struct TNCDATA * TNC) -{ - UCHAR * TXBUFFERPTR; - int i; - int Work; - char WorkString[256]; - int State, Change, Count; - TRANSPORTENTRY * L4 = NULL; - unsigned char * MONCURSOR=0; - int SaveAuthProg = 0; - - TXBUFFERPTR = &TNC->DEDTXBUFFER[0]; - - if (Channel->Chan_TXQ == (UCHAR *)(ptrdiff_t) -1) - { - Channel->Chan_TXQ = 0; - } - - if (TNC->MSGTYPE != 0) - goto NOTDATA; - - goto HOSTDATAPACKET; - -//HOSTCMDS: -// DD 'G','I', 'J', 'C', 'D', 'L', '@', 'Y', 'M' -// DD POLL,ICMD,JCMD,CCMD,DCMD,LCMD,ATCOMMAND,YCMD,HOSTMON - -NOTDATA: - - if (TNC->DEDTXBUFFER[0] == 1) - { - // recovering - -// if (!TNC->Recovering) -// { -// sprintf(msg, "Port %d DED Recovery started\n", TNC->ComPort); -// OutputDebugString(msg); -// TNC->Recovering = TRUE; -// } - } - else - { - // Not recovery - -// if (TNC->Recovering) -// { -// sprintf(msg, "Port %d DED Recovery completed\n", TNC->ComPort); -// OutputDebugString(msg); -// TNC->Recovering = FALSE; -// } - - } - - if (TNC->DEDTXBUFFER[0] == 1) - goto DUFFHOSTCMD; - -// sprintf(msg,"DED CMD: Port %d CMD %c MSGCHANNEL %d\n", TNC->ComPort, TNC->TONODEBUFFER[0], MSGCHANNEL); -// OutputDebugString(msg); - - if (_memicmp(TNC->DEDTXBUFFER, "QRES", 4 == 0)) - goto SENDHOSTOK; - - switch (toupper(TNC->DEDTXBUFFER[0])) - { - case 1: - - goto DUFFHOSTCMD; - - case 'G': - - goto POLL; - - case 'I': - goto ICMD; - - case 'J': - - TNC->MODE = TNC->DEDTXBUFFER[5] & 1; - - if (TNC->MODE) - EnableAppl(TNC); - else - DisableAppl(TNC); - - goto SENDHOSTOK; - - case 'C': - goto CCMD; - - case 'D': - goto DCMD; - - case 'L': - goto LCMD; - - case '@': - goto ATCOMMAND; - - case 'Y': - goto YCMD; - - case 'E': - goto ECMD; - - case 'M': - - if (TNC->DEDTXBUFFER[1] == 'N') - goto DISABLEMONITOR; - - goto ENABLEMONITOR; - - case 'K': - case 'O': - goto SENDHOSTOK; - - case 'V': // Vesrion - - PUTCHARx(TNC, TNC->MSGCHANNEL); - PUTCHARx(TNC, 1); - PUTSTRING(TNC, "DSPTNC Firmware V.1.3a, (C) 2005-2010 SCS GmbH & Co."); - PUTCHARx(TNC, 0); - - return TRUE; - - default: - goto SENDHOSTOK; - -ATCOMMAND: - - if (TNC->DEDTXBUFFER[1] == 'B') - goto BUFFSTAT; - - if (TNC->DEDTXBUFFER[1] == 'M') - goto BUFFMIN; - -// Not recognised - - PUTCHARx(TNC, TNC->MSGCHANNEL); - - for (i=0; i < LBADCMDREPLY; i++) - { - PUTCHARx(TNC, BADCMDREPLY[i]); - } - - return TRUE; - - -BUFFMIN: - - Work = MINBUFFCOUNT; - goto BUFFCOMM; - -BUFFSTAT: - - Work = QCOUNT; - -BUFFCOMM: - - PUTCHARx(TNC, TNC->MSGCHANNEL); // REPLY ON SAME CHANNEL - PUTCHARx(TNC, 1); - - sprintf(WorkString, "%d", Work); // Buffer count - - PUTSTRING(TNC, WorkString); - - PUTCHARx(TNC, 0); - return TRUE; - -ICMD: - - { - char * Call = &TNC->DEDTXBUFFER[1]; - int len; - char Reply[80]; - char ReplyCall[10]; - - - if (TNC->MSGLENGTH > 2) - { - // Save callsign - - TNC->DEDTXBUFFER[TNC->MSGLENGTH] = 0; - - if (*Call == ' ') - *Call++; // May have leading space - - _strupr(Call); - - memset(Channel->MYCall, ' ', 10); - memcpy(Channel->MYCall, Call, (int)strlen(Call)); - - Debugprintf("DED Host I chan %d call %s", TNC->MSGCHANNEL, Call); - - strcpy(ReplyCall, Call); - -/* - if (TNC->MSGCHANNEL == 0) // if setting zero, copy to all others - { - int i; - - for (i = 1; i <= TNC->HOSTSTREAMS; i++) - { - memcpy(TNC->Channels[i]->MYCall, TNC->Channels[0]->MYCall, 10); - Debugprintf("DED Capy to chan %d call %s", i, Channel->MYCall); - } - } -*/ - - - - - - - } - else - { - memcpy(ReplyCall, Channel->MYCall, 10); - strlop(ReplyCall, ' '); - } - - len = sprintf(Reply, "\x2%s", ReplyCall); - - SENDCMDREPLY(TNC, Reply, len + 1); // include the null - - return TRUE; - } -ECMD: - - goto SENDHOSTOK; - -DUFFHOSTCMD: - - PUTCHARx(TNC, TNC->MSGCHANNEL); - - for (i=0; i < LBADCMDREPLY; i++) - { - PUTCHARx(TNC, BADCMDREPLY[i]); - } - - return TRUE; - -ENABLEMONITOR: - - TNC->TRACEFLAG = 0x80; - goto MONCOM; - -DISABLEMONITOR: - - TNC->TRACEFLAG = 0; - -MONCOM: - - SetAppl(TNC->Channels[0]->BPQStream, 2 | TNC->TRACEFLAG, TNC->APPLICATION); - - goto SENDHOSTOK; - -CCMD: - -// CONNECT REQUEST - - if (TNC->MSGCHANNEL == 0) - goto SENDHOSTOK; // SETTING UNPROTO ADDR - JUST ACK IT - - *TNC->DEDCURSOR = 0; - - if (TNC->MSGLENGTH > 1) - goto REALCALL; - -// STATUS REQUEST - IF CONNECTED, GET CALL - - DEDSWITCH[3] = 0; - - GetCallsign(Channel->BPQStream, &DEDSWITCH[3]); - - Debugprintf("CCMD %d %d %s", TNC->MSGCHANNEL, TNC->Channels[TNC->MSGCHANNEL]->BPQStream, &DEDSWITCH[3]); - - if (DEDSWITCH[3] == 0) - SENDCMDREPLY(TNC, NOTCONMSG, LNOTCON); - else - SENDCMDREPLY(TNC, DEDSWITCH, LSWITCH); - - return TRUE; - -REALCALL: - -// If to Switch, just connect, else pass c command to Node - - Debugprintf("CCMD %d %s", TNC->MSGCHANNEL, TXBUFFERPTR); - - SaveAuthProg = AuthorisedProgram; - AuthorisedProgram =1; - Connect(Channel->BPQStream); - AuthorisedProgram = SaveAuthProg; - -// CONNECT WILL BE REPORTED VIA NORMAL STATUS CHANGE - - if (Channel->MYCall[0] > ' ') - ChangeSessionCallsign(Channel->BPQStream, EncodeCall(Channel->MYCall)); - else - ChangeSessionCallsign(Channel->BPQStream, EncodeCall(TNC->Channels[0]->MYCall)); - - _strupr(TXBUFFERPTR); - - if (strstr(TXBUFFERPTR, "SWITCH") == 0) // Not switch - { - char * Call, * Arg1; - char * Context; - char seps[] = " ,\r"; - - Call = strtok_s(TXBUFFERPTR + 1, seps, &Context); - Arg1 = strtok_s(NULL, seps, &Context); - - if (Arg1) - { - // Have a digi string - - // First digi is used as a port number. Any others are rwal digis or WINMOR/PACTOR - - if (Context[0]) - TNC->MSGLEN = sprintf(TXBUFFERPTR + 100, "C %s %s v %s\r", Arg1, Call, Context); - else - TNC->MSGLEN = sprintf(TXBUFFERPTR + 100, "C %s %s\r", Call, Arg1); - } - else - TNC->MSGLEN = sprintf(TXBUFFERPTR + 100, "C %s\r", Call); - - strcpy(TXBUFFERPTR, TXBUFFERPTR + 100); - - SendMsg(Channel->BPQStream, TXBUFFERPTR, TNC->MSGLEN); - -// READCHANGE(Channel->BPQStream); // Suppress Connected to Switch - - goto SENDHOSTOK; - } - } - - goto SENDHOSTOK; - -DCMD: - -// DISCONNECT REQUEST - - Disconnect(Channel->BPQStream); - - goto SENDHOSTOK; - -LCMD: - - PUTCHARx(TNC, TNC->MSGCHANNEL); // REPLY ON SAME CHANNEL - PUTCHARx(TNC, 1); - -// GET STATE AND QUEUED BUFFERS - - if (TNC->MSGCHANNEL) - goto NORM_L; - -// TO MONITOR CHANNEL - -// SEE IF MONITORED FRAMES AVAILABLE - - if (MONCount(TNC->Channels[0]->BPQStream)) - Work = 0x31; - else - Work = 0x30; - - goto MON_L; - -NORM_L: - - LocalSessionState(Channel->BPQStream, &State, &Change, FALSE); - - if (State == 0) - Work = '0'; - else - Work = '4'; // AX.25 STATE - - PUTCHARx(TNC, Change + '0'); // Status Messages - - PUTCHARx(TNC, ' '); - -// GET OTHER QUEUE COUNTS - - Count = RXCount(Channel->BPQStream); - - sprintf(WorkString, "%d", Count); // message count - - PUTSTRING(TNC, WorkString); - PUTCHARx(TNC, ' '); - -// NOT SENT IS NUMBER ON OUR QUEUE, NOT ACKED NUMBER FROM SWITCH - - -// SEE HOW MANY BUFFERS ATTACHED TO Q HEADER IN BX - - Count = 0;// C_Q_COUNT(Channel->Chan_TXQ); - - sprintf(WorkString, "%d", Count); // message count - PUTSTRING(TNC, WorkString); - PUTCHARx(TNC, ' '); - - if (Count > 8) - Work = '8'; // Busy - - Count = CountFramesQueuedOnSession(L4); - - sprintf(WorkString, "%d", Count); // message count - PUTSTRING(TNC, WorkString); - PUTCHARx(TNC, ' '); - -MON_L: - - PUTCHARx(TNC, '0'); - PUTCHARx(TNC, ' '); - PUTCHARx(TNC, Work); - PUTCHARx(TNC, 0); - - return TRUE; - -HOSTDATAPACKET: - -// } -// { -// UCHAR msg[100]; - -// sprintf(msg,"Host Data Packet: Port %d\n", TNC->ComPort); -// OutputDebugString(msg); -// } -// - - -// IF WE ALREADY HAVE DATA QUEUED, ADD THIS IT QUEUE - -// if (Channel->Chan_TXQ) -// { - -// // COPY MESSAGE TO A CHAIN OF BUFFERS - -// if (QCOUNT < 10) -// goto CANTSEND; // NO SPACE - RETURN ERROR (?) - -//QUEUEFRAME: - -// C_Q_ADD(Channel->Chan_TXQ, COPYMSGTOBUFFERS()); // RETURNS EDI = FIRST (OR ONLY) FRAGMENT - -// goto SENDHOSTOK; - - // MAKE SURE NODE ISNT BUSY - - if (TNC->MSGCHANNEL == 0) // UNPROTO Channel - goto SendUnproto; - - Count = CountFramesQueuedOnSession(L4); - -// if (Count > 4 || QCOUNT < 40) -// goto QUEUEFRAME; - - // OK TO PASS TO NODE - - SENDENFORCINGPACLEN(Channel, TNC->DEDTXBUFFER, TNC->MSGLENGTH); - goto SENDHOSTOK; - -SendUnproto: - - SendMsg(0, TXBUFFERPTR, TNC->MSGLENGTH); - goto SENDHOSTOK; - -POLL: - - PROCESSPOLL(TNC, Channel); - return TRUE; - -YCMD: - - *TNC->DEDCURSOR = 0; - - Work = atoi(&TXBUFFERPTR[1]); - - if (Work == 0) - Work = 1; // Mustn't release last stream - - if (Work >= 0 && Work <= MAXSTREAMS) - { - int Stream; - - if (Work < TNC->HOSTSTREAMS) - { - // Need to get rid of some streams - - for (i = Work + 1; i <= TNC->HOSTSTREAMS; i++) - { - Stream = TNC->Channels[i]->BPQStream; - - if (Stream) - { - Disconnect(Stream); - READCHANGE(Stream); // Prevent Initial *** disconnected - - DeallocateStream(Stream); - - Debugprintf("DED YCMD Release Stream %d", Stream); - } - - free(TNC->Channels[i]); - TNC->Channels[i] = 0; - } - } - else - { - for (i = TNC->HOSTSTREAMS+1; i <= Work; i++) - { - AllocateDEDChannel(TNC, i); // Also used by Y command handler - } - } - TNC->HOSTSTREAMS = Work; - } - - /* - - Why is this here? - { - int Len=0; - UCHAR Message[1000]; - - while (TNC->RXCOUNT > 0) - { - Message[Len++]= *(TNC->PUTPTR++); - - TNC->RXCOUNT--; - - if (TNC->PUTPTR == &TNC->TOUSERBUFFER[TNCBUFFLEN]) - TNC->PUTPTR = (UCHAR *)&TNC->TOUSERBUFFER; - - if (Len > 900) - { - BPQSerialSendData(TNC, Message, Len); - Len = 0; - } - } - - if (Len > 0) - { - BPQSerialSendData(TNC, Message, Len); - } - } - _asm { - - popad - - - RET -*/ - -SENDHOSTOK: - - PUTCHARx(TNC, TNC->MSGCHANNEL); // REPLY ON SAME CHANNEL - PUTCHARx(TNC, 0); // NOTHING DOING - - return TRUE; - -} -int PROCESSPOLL(struct TNCDATA * TNC, struct StreamInfo * Channel) -{ - int PollType; - - // ASK SWITCH FOR STATUS CHANGE OR ANY RECEIVED DATA - - if (TNC->MSGLENGTH == 1) - goto GENERALPOLL; - - PollType = 0; - -// HE'S BEING AWKWARD, AND USING SPECIFIC DATA/STATUS POLL - - if (TNC->TONODEBUFFER[1] == '0') - goto DATAONLY; - - STATUSPOLL(TNC, Channel); - -GENERALPOLL: - - if (STATUSPOLL(TNC, Channel)) - return TRUE; // Status was reported - -DATAONLY: - - if (DATAPOLL(TNC, Channel)) - return TRUE; // Data Sent - - goto SENDHOSTOK; // NOTHING DOING - - -SENDHOSTOK: - - PUTCHARx(TNC, TNC->MSGCHANNEL); // REPLY ON SAME CHANNEL - PUTCHARx(TNC, 0); // NOTHING DOING - - return TRUE; -} - -int ConvertToDEDMonFormat(struct TNCDATA * TNC, char * Decoded, int Len, MESSAGE * Rawdata) -{ - // convert tnc2 format monitor to ded format - - unsigned char * MONCURSOR=0; - unsigned char MONHEADER[256]; - char * From, * To, * via, * ctl, *Context, *ptr, *iptr; - int pid, NR, NS, MonLen; - char rest[20]; - -/* - - From DEDHOST Documentation - - -Codes of 4 and 5 both signify a monitor header. This is a null-terminated -format message containing the - - fm {call} to {call} via {digipeaters} ctl {name} pid {hex} - -string that forms a monitor header. The monitor header is also identical to -the monitor header displayed in user mode. If the code was 4, the monitored -frame contained no information field, so the monitor header is all you get. If -you monitor KB6C responding to a connect request from me and then poll channel -0, you'll get: - - 0004666D204B42364320746F204B42354D552063746C2055612070494420463000 - ! ! f m K B 6 C t o K B 5 M U c t l U A p i d F 0 ! - ! ! ! - ! +---- Code = 4 (Monitor, no info) Null termination ----+ - +------- Channel = 0 (Monitor info is always on channel 0) - - If the code was 5, the monitored frame did contain an information field. In -this case, another G command to channel 0 will return the monitored information -with a code of 6. Since data transmissions must be transparent, the monitored -information is passed as a byte-count format transmission. That is, it is -preceded by a count byte (one less than the number of bytes in the field). No -null terminator is used in this case. Since codes 4, 5, and 6 pertain to -monitored information, they will be seen only on channel 0. If you hear KB6C -say "Hi" to NK6K, and then poll channel 0, you'll get: - - 0005666D204B42364320746F204E4B364B2063746C204930302070494420463000 - ! ! f m K B 6 C t o N K 6 K c t l I 0 0 p i d F 0 ! - ! ! ! ! ! - ! ! or whatever ----+-+ ! - ! ! ! - ! +---- Code = 5 (Monitor, info follows) Null termination ----+ - +------ Channel = 0 (Monitor info is always on channel 0) - -and then the very next poll to channel 0 will get: - - 00 06 02 48 69 0D - ! ! ! H i CR - ! ! ! ! - ! ! ! +---- (this is a data byte) - ! ! +---- Count = 2 (three bytes of data) - ! +------- Code = 6 (monitored information) - +---------- Channel = 0 (Monitor info is always on channel 0) - - -*/ - - iptr = strchr(&Decoded[10], ':'); // Info if present - - MONHEADER[0] = 4; // NO DATA FOLLOWS - MONCURSOR = &MONHEADER[1]; - - if (strstr(Decoded, "NET/ROM") || strstr(Decoded, "NODES br") || strstr(Decoded, "INP3 RIF")) - pid = 0xcf; - else - pid = 0xf0; - - From = strtok_s(&Decoded[10], ">", &Context); - To = strtok_s(NULL, " ", &Context); - - via = strlop(To, ','); - - Context = strchr(Context, '<'); - if (Context == 0) - return 0; - - ctl = strtok_s(NULL, ">", &Context); - - if (via) - MONCURSOR += sprintf(MONCURSOR, "fm %s to %s via %s ctl ", From, To, via); - else - MONCURSOR += sprintf(MONCURSOR, "fm %s to %s ctl ", From, To); - - rest[0] = 0; - - switch (ctl[1]) - { - case 'R': - - NR = ctl[strlen(ctl)-1] - 48; - strlop(ctl, ' '); - sprintf(rest, "%s%d", &ctl[1], NR); - break; - - case 'I': - - ptr = strchr(ctl, 'S'); - if (ptr) NS = ptr[1] - 48; - ptr = strchr(ctl, 'R'); - if (ptr) NR = ptr[1] - 48; - sprintf(rest, "I%d%d pid %X", NS, NR, pid); - - if (pid == 0xcf) - { - // NETROM - pass the raw data - - MonLen = Rawdata->LENGTH - (MSGHDDRLEN + 16); // Data portion of frame - memcpy(&TNC->MONBUFFER[2], &Rawdata->L2DATA[0], MonLen); - - MONHEADER[0] = 5; // Data to follow - TNC->MONFLAG = 1; // Data to follow - TNC->MONBUFFER[0] = 6; - TNC->MONLENGTH = MonLen + 2; - TNC->MONBUFFER[1] = (MonLen - 1); - } - else - { - if (iptr) - { - iptr += 2; // Skip colon and cr - MonLen = Len - (int)(iptr - Decoded); - if (MonLen > 256) - MonLen = 256; - - memcpy(&TNC->MONBUFFER[2], iptr, MonLen); - - - if (MonLen == 0) // No data - { - MONHEADER[0] = 4; // No Data to follow - TNC->MONFLAG = 0; // No Data to follow - } - else - { - MONHEADER[0] = 5; // Data to follow - TNC->MONFLAG = 1; // Data to follow - TNC->MONBUFFER[0] = 6; - TNC->MONLENGTH = MonLen + 2; - TNC->MONBUFFER[1] = (MonLen - 1); - } - } - } - break; - - case 'C': - - strcpy(rest, "SABM"); - break; - - case 'D': - - if (ctl[1] == 'M') - strcpy(rest, "DM"); - else - strcpy(rest, "DISC"); - - break; - - case 'U': - - if (ctl[2] == 'A') - strcpy(rest, "UA"); - else - { - // UI - - size_t MonLen;; - - MONHEADER[0] = 5; // Data to follow - sprintf(rest, "UI pid %X", pid); - TNC->MONFLAG = 1; // Data to follow - TNC->MONBUFFER[0] = 6; - - if (pid ==0xcf) - { - // NETROM - pass th raw data - - MonLen = Rawdata->LENGTH - (MSGHDDRLEN + 16); // Data portion of frame - memcpy(&TNC->MONBUFFER[2], &Rawdata->L2DATA[0], MonLen); - } - else - { - ptr = strchr(Context, ':'); - - if (ptr == 0) - { - TNC->MONFLAG = 0; - return 0; - } - - ptr += 2; // Skip colon and cr - MonLen = Len - (ptr - Decoded); - memcpy(&TNC->MONBUFFER[2], ptr, MonLen); - } - - if (MonLen == 0) // No data - { - MONHEADER[0] = 4; // No Data to follow - TNC->MONFLAG = 0; // No Data to follow - } - else - { - TNC->MONLENGTH = (int)MonLen + 2; - TNC->MONBUFFER[1] = (int)(MonLen - 1); - } - break; - } - - default: - rest[0] = 0; - } - - MONCURSOR += sprintf(MONCURSOR, "%s", rest); - - if (MONCURSOR == &MONHEADER[1]) - return 0; // NOTHING DOING - - *MONCURSOR++ = 0; // NULL TERMINATOR - - SENDCMDREPLY(TNC, MONHEADER, (int)(MONCURSOR - &MONHEADER[0])); - return 1; -} - -// GET THE CONTROL BYTE, TO SEE IF THIS FRAME IS TO BE DISPLAYED -/* - -static char CTL_MSG[]=" ctl "; -static char VIA_MSG[]=" via "; -static char PID_MSG[]=" pid "; -static char SABM_MSG[]="SABM"; -static char DISC_MSG[]="DISC"; -static char UA_MSG[]="UA"; - -static char DM_MSG []="DM"; -static char RR_MSG []="RR"; -static char RNR_MSG[]="RNR"; -static char I_MSG[]="I pid "; -static char UI_MSG[]="UI pid "; -static char FRMR_MSG[]="FRMR"; -static char REJ_MSG[]="REJ"; - - PUSH EDI - MOV ECX,8 ; MAX DIGIS -CTRLLOOP: - TEST BYTE PTR (MSGCONTROL-1)[EDI],1 - JNZ CTRLFOUND - - ADD EDI,7 - LOOP CTRLLOOP -; -; INVALID FRAME -; - POP EDI - RET - -CTRLFOUND: - MOV AL,MSGCONTROL[EDI] - - and AL,NOT PFBIT ; Remove P/F bit - mov FRAME_TYPE,AL - - - POP EDI -; - TEST AL,1 ; I FRAME - JZ IFRAME - - CMP AL,3 ; UI - JE OKTOTRACE ; ALWAYS DO UI - - CMP AL,FRMR - JE OKTOTRACE ; ALWAYS DO FRMR -; -; USEQ/CONTROL - TRACE IF MCOM ON -; - CMP MCOM,0 - JNE OKTOTRACE - - RET - -;-----------------------------------------------------------------------------; -; Check for MALL ; -;-----------------------------------------------------------------------------; - -IFRAME: - cmp MALL,0 - jne OKTOTRACE - - ret - -OKTOTRACE: -; -;-----------------------------------------------------------------------------; -; Get the port number of the received frame ; -;-----------------------------------------------------------------------------; -; -; CHECK FOR PORT SELECTIVE MONITORING -; - MOV CL,MSGPORT[EDI] - mov PORT_NO,CL - - DEC CL - MOV EAX,1 - SHL EAX,CL ; SHIFT BIT UP - - TEST MMASK,EAX - JNZ TRACEOK1 - - RET - -TRACEOK1: - - MOV FRMRFLAG,0 - push EDI - mov AH,MSGDEST+6[EDI] - mov AL,MSGORIGIN+6[EDI] - -; -; Display Origin Callsign ; -; - -; 0004666D204B42364320746F204B42354D552063746C2055612070494420463000 -; ! ! f m K B 6 C t o K B 5 M U c t l U A p i d F 0 ! -; ! ! ! -; ! +---- Code = 4 (Monitor, no info) Null termination ----+ - ; +------- Channel = 0 (Monitor info is always on channel 0) - - mov ESI,OFFSET FM_MSG - call NORMSTR - - lea ESI,MSGORIGIN[EDI] - call CONVFROMAX25 - mov ESI,OFFSET NORMCALL - call DISPADDR - - pop EDI - push EDI - - mov ESI,OFFSET TO_MSG - call NORMSTR -; -; Display Destination Callsign ; -; - lea ESI,MSGDEST[EDI] - call CONVFROMAX25 - mov ESI,OFFSET NORMCALL - call DISPADDR - - pop EDI - push EDI - - mov AX,MMSGLENGTH[EDI] - mov FRAME_LENGTH,AX - mov ECX,8 ; Max number of digi-peaters -; -; Display any Digi-Peaters ; -; - test MSGORIGIN+6[EDI],1 - jnz NO_MORE_DIGIS - - mov ESI,OFFSET VIA_MSG - call NORMSTR - jmp short skipspace - -NEXT_DIGI: - test MSGORIGIN+6[EDI],1 - jnz NO_MORE_DIGIS - - mov AL,' ' - call MONPUTCHAR -skipspace: - add EDI,7 - sub FRAME_LENGTH,7 ; Reduce length - - push EDI - push ECX - lea ESI,MSGORIGIN[EDI] - call CONVFROMAX25 ; Convert to call - - push EAX ; Last byte is in AH - - mov ESI,OFFSET NORMCALL - call DISPADDR - - pop EAX - - test AH,80H - jz NOT_REPEATED - - mov AL,'*' - call MONPUTCHAR - -NOT_REPEATED: - pop ECX - pop EDI - loop NEXT_DIGI - -NO_MORE_DIGIS: - -;----------------------------------------------------------------------------; -; Display ctl ; -;----------------------------------------------------------------------------; - - mov ESI,OFFSET CTL_MSG - call NORMSTR - -;-----------------------------------------------------------------------------; -; Start displaying the frame information ; -;-----------------------------------------------------------------------------; - - - mov INFO_FLAG,0 - - mov AL,FRAME_TYPE - - test AL,1 - jne NOT_I_FRAME - -;-----------------------------------------------------------------------------; -; Information frame ; -;-----------------------------------------------------------------------------; - - mov AL,'I' - call MONPUTCHAR - mov INFO_FLAG,1 - - mov ESI,OFFSET I_MSG - call NORMSTR - - lea ESI,MSGPID[EDI] - lodsb - - call BYTE_TO_HEX - - - jmp END_OF_TYPE - -NOT_I_FRAME: - -;-----------------------------------------------------------------------------; -; Un-numbered Information Frame ; -;-----------------------------------------------------------------------------; - - cmp AL,UI - jne NOT_UI_FRAME - - mov ESI,OFFSET UI_MSG - call NORMSTR - - lea ESI,MSGPID[EDI] - lodsb - - call BYTE_TO_HEX - - mov INFO_FLAG,1 - jmp END_OF_TYPE - -NOT_UI_FRAME: - test AL,10B - jne NOT_R_FRAME - -;-----------------------------------------------------------------------------; -; Process supervisory frames ; -;-----------------------------------------------------------------------------; - - - and AL,0FH ; Mask the interesting bits - cmp AL,RR - jne NOT_RR_FRAME - - mov ESI,OFFSET RR_MSG - call NORMSTR - jmp END_OF_TYPE - -NOT_RR_FRAME: - cmp AL,RNR - jne NOT_RNR_FRAME - - mov ESI,OFFSET RNR_MSG - call NORMSTR - jmp END_OF_TYPE - -NOT_RNR_FRAME: - cmp AL,REJ - jne NOT_REJ_FRAME - - mov ESI,OFFSET REJ_MSG - call NORMSTR - jmp SHORT END_OF_TYPE - -NOT_REJ_FRAME: - mov AL,'?' ; Print "?" - call MONPUTCHAR - jmp SHORT END_OF_TYPE - -; -; Process all other frame types ; -; - -NOT_R_FRAME: - cmp AL,UA - jne NOT_UA_FRAME - - mov ESI,OFFSET UA_MSG - call NORMSTR - jmp SHORT END_OF_TYPE - -NOT_UA_FRAME: - cmp AL,DM - jne NOT_DM_FRAME - - mov ESI,OFFSET DM_MSG - call NORMSTR - jmp SHORT END_OF_TYPE - -NOT_DM_FRAME: - cmp AL,SABM - jne NOT_SABM_FRAME - - mov ESI,OFFSET SABM_MSG - call NORMSTR - jmp SHORT END_OF_TYPE - -NOT_SABM_FRAME: - cmp AL,DISC - jne NOT_DISC_FRAME - - mov ESI,OFFSET DISC_MSG - call NORMSTR - jmp SHORT END_OF_TYPE - -NOT_DISC_FRAME: - cmp AL,FRMR - jne NOT_FRMR_FRAME - - mov ESI,OFFSET FRMR_MSG - call NORMSTR - MOV FRMRFLAG,1 - jmp SHORT END_OF_TYPE - -NOT_FRMR_FRAME: - mov AL,'?' - call MONPUTCHAR - -END_OF_TYPE: - - CMP FRMRFLAG,0 - JE NOTFRMR -; -; DISPLAY FRMR BYTES -; - lea ESI,MSGPID[EDI] - MOV CX,3 ; TESTING -FRMRLOOP: - lodsb - CALL BYTE_TO_HEX - - LOOP FRMRLOOP - - JMP NO_INFO - -NOTFRMR: - - MOVZX ECX,FRAME_LENGTH - - - cmp INFO_FLAG,1 ; Is it an information packet ? - jne NO_INFO - - - XOR AL,AL ; IN CASE EMPTY - - sub ECX,23 - CMP ecx,0 - je NO_INFO ; EMPTY I FRAME - -; -; PUT DATA IN MONBUFFER, LENGTH IN MONLENGTH -; - - pushad -} - TNC->MONFLAG = 1; - - _asm{ - - popad - - MOV MONHEADER,5 ; DATA FOLLOWS - - cmp ECX,257 - jb LENGTH_OK -; - mov ECX,256 -; -LENGTH_OK: -; - mov MonDataLen, ECX - - pushad - - } - - TNC->MONBUFFER[1] = MonDataLen & 0xff; - TNC->MONBUFFER[1]--; - - - TNC->MONLENGTH = MonDataLen+2; - - ptr1=&TNC->MONBUFFER[2]; - - _asm{ - - popad - - MOV EDI,ptr1 - -MONCOPY: - LODSB - CMP AL,7 ; REMOVE BELL - JNE MONC00 - - MOV AL,20H -MONC00: - STOSB - - LOOP MONCOPY - - POP EDI - RET - -NO_INFO: -; -; ADD CR UNLESS DATA ALREADY HAS ONE -; - CMP AL,CR - JE NOTANOTHER - - mov AL,CR - call MONPUTCHAR - -NOTANOTHER: -; - pop EDI - ret - -;----------------------------------------------------------------------------; -; Display ASCIIZ strings ; -;----------------------------------------------------------------------------; - -NORMSTR: - lodsb - cmp AL,0 ; End of String ? - je NORMSTR_RET ; Yes - call MONPUTCHAR - jmp SHORT NORMSTR - -NORMSTR_RET: - ret - -;-----------------------------------------------------------------------------; -; Display Callsign pointed to by SI ; -;-----------------------------------------------------------------------------; - -DISPADDR: - jcxz DISPADDR_RET - - lodsb - call MONPUTCHAR - - loop DISPADDR - -DISPADDR_RET: - ret - - -;-----------------------------------------------------------------------------; -; Convert byte in AL to nn format ; -;-----------------------------------------------------------------------------; - -DISPLAY_BYTE_2: - cmp AL,100 - jb TENS_2 - - sub AL,100 - jmp SHORT DISPLAY_BYTE_2 - -TENS_2: - mov AH,0 - -TENS_LOOP_2: - cmp AL,10 - jb TENS_LOOP_END_2 - - sub AL,10 - inc AH - jmp SHORT TENS_LOOP_2 - -TENS_LOOP_END_2: - push EAX - mov AL,AH - add AL,30H - call MONPUTCHAR - pop EAX - - add AL,30H - call MONPUTCHAR - - ret - -;-----------------------------------------------------------------------------; -; Convert byte in AL to Hex display ; -;-----------------------------------------------------------------------------; - -BYTE_TO_HEX: - push EAX - shr AL,1 - shr AL,1 - shr AL,1 - shr AL,1 - call NIBBLE_TO_HEX - pop EAX - call NIBBLE_TO_HEX - ret - -NIBBLE_TO_HEX: - and AL,0FH - cmp AL,10 - - jb LESS_THAN_10 - add AL,7 - -LESS_THAN_10: - add AL,30H - call MONPUTCHAR - ret - - - -CONVFROMAX25: -; -; CONVERT AX25 FORMAT CALL IN [SI] TO NORMAL FORMAT IN NORMCALL -; RETURNS LENGTH IN CX AND NZ IF LAST ADDRESS BIT IS SET -; - PUSH ESI ; SAVE - MOV EDI,OFFSET NORMCALL - MOV ECX,10 ; MAX ALPHANUMERICS - MOV AL,20H - REP STOSB ; CLEAR IN CASE SHORT CALL - MOV EDI,OFFSET NORMCALL - MOV CL,6 -CONVAX50: - LODSB - CMP AL,40H - JE CONVAX60 ; END IF CALL - DO SSID - - SHR AL,1 - STOSB - LOOP CONVAX50 -CONVAX60: - POP ESI - ADD ESI,6 ; TO SSID - LODSB - MOV AH,AL ; SAVE FOR LAST BIT TEST - SHR AL,1 - AND AL,0FH - JZ CONVAX90 ; NO SSID - FINISHED -; - MOV BYTE PTR [EDI],'-' - INC EDI - CMP AL,10 - JB CONVAX70 - SUB AL,10 - MOV BYTE PTR [EDI],'1' - INC EDI -CONVAX70: - ADD AL,30H ; CONVERT TO DIGIT - STOSB -CONVAX90: - MOV ECX,EDI - SUB ECX,OFFSET NORMCALL - MOV NORMLEN,ECX ; SIGNIFICANT LENGTH - - TEST AH,1 ; LAST BIT SET? - RET - - -PUTCHAR: - - pushad - push eax - push TNC - call PUTCHARx - pop eax - pop eax - popad - ret -} -} -*/ - - - -VOID SENDENFORCINGPACLEN(struct StreamInfo * Channel, char * Msg, int Len) -{ - int Paclen = 0; - - if (Len == 0) - return; - - if (BPQHOSTVECTOR[Channel->BPQStream-1].HOSTSESSION) - Paclen = BPQHOSTVECTOR[Channel->BPQStream-1].HOSTSESSION->SESSPACLEN; - - if (Paclen == 0) - goto nochange; // paclen not set - -fragloop: - - if (Len <= Paclen) - goto nochange; // msglen <= paclen - -// need to fragment - - SendMsg(Channel->BPQStream, Msg, Paclen); - - Msg += Paclen; - - Len -= Paclen; - - if (Len) - goto fragloop; - - return; - -nochange: - - SendMsg(Channel->BPQStream, Msg, Len); - return; -} - -int DOCOMMAND(struct TNCDATA * conn) -{ - char Errbuff[500]; - int i; - -// PROCESS NORMAL MODE COMMAND - - sprintf(Errbuff, "BPQHOST Port %d Normal Mode CMD %s\n",conn->ComPort, conn->TONODEBUFFER); - OutputDebugString(Errbuff); - -// IF ECHO ENABLED, ECHO IT - - if (conn->ECHOFLAG) - { - UCHAR * ptr = conn->TONODEBUFFER; - UCHAR c; - - do - { - c = *(ptr++); - - if (c == 0x1b) c = ':'; - - PUTCHARx(conn, c); - - } while (c != 13); - } - - if (conn->TONODEBUFFER[0] != 0x1b) - goto NOTCOMMAND; // DATA IN NORMAL MODE - IGNORE - - switch (toupper(conn->TONODEBUFFER[1])) - { - case 'J': - - if (conn->TONODEBUFFER[6] == 0x0d) - conn->MODE = 0; - else - conn->MODE = conn->TONODEBUFFER[6] & 1; - - if (conn->MODE) - EnableAppl(conn); - else - DisableAppl(conn); - - if (conn->MODE) - { - // send host mode ack - -// PUTCHARx(conn, 0); -// PUTCHARx(conn, 0); - - conn->CURSOR = (UCHAR *)&conn->TONODEBUFFER; - return 0; - } - - break; - - case 'E': - - conn->ECHOFLAG = conn->TONODEBUFFER[2] & 1; - break; - - case 'I': - { - // Save call - - char * Call = &conn->TONODEBUFFER[2]; - - *(conn->CURSOR - 2) = 0; - - for (i = 0; i <= conn->HOSTSTREAMS; i++) - { - strcpy(conn->Channels[i]->MYCall, Call); - } - - break;; - } - case 'P': - -// PARAMS COMMAND - RETURN FIXED STRING - - PARAMPORT = conn->TONODEBUFFER[2]; - - for (i=0; i < LPARAMREPLY; i++) - { - PUTCHARx(conn, PARAMREPLY[i]); - } - - break; - - case 'S': - case 'D': - - // Return Channel Not Connected - - PUTSTRING(conn, "* CHANNEL NOT CONNECTED *\r"); - - default: - - break; - - } - -// PUTCHARx(conn, 'c'); -// PUTCHARx(conn, 'm'); -// PUTCHARx(conn, 'd'); -// PUTCHARx(conn, ':'); -// PUTCHARx(conn, 13); - -NOTCOMMAND: - - conn->CURSOR = (UCHAR *)&conn->TONODEBUFFER; - - return 0; - -} - -VOID SENDCMDREPLY(struct TNCDATA * TNC, char * Msg, int Len) -{ - int n; - - if (Len == 0) - return; - - PUTCHARx(TNC, TNC->MSGCHANNEL); - - for (n = 0; n < Len; n++) - { - PUTCHARx(TNC, Msg[n]); - } -} - -int STATUSPOLL(struct TNCDATA * TNC, struct StreamInfo * Channel) -{ - // Status Poll - - int State, Change, i; - char WorkString[256]; - - if (TNC->MSGCHANNEL == 0) // Monitor Chan - return 0; - - LocalSessionState(Channel->BPQStream, &State, &Change, TRUE); - - if (Change == 0) - return 0; - - // PORT HAS CONNECTED OR DISCONNECTED - SEND STATUS CHANGE TO PC - - if (State == 0) - { - // DISCONNECTED - - i = sprintf(CONMSG, "\x3(%d) DISCONNECTED fm 0:SWITCH\r", TNC->MSGCHANNEL); - i++; - } - else - { - // GET CALLSIGN - - GetCallsign(Channel->BPQStream, WorkString); - strlop(WorkString, ' '); - i = sprintf(CONMSG, "\x3(%d) CONNECTED to %s\r", TNC->MSGCHANNEL, WorkString); - i++; - } - - SENDCMDREPLY(TNC, CONMSG, i); - return 1; -} - -int DATAPOLL(struct TNCDATA * TNC, struct StreamInfo * Channel) -{ - unsigned char NODEBUFFER[300]; // MESSAGE FROM NODE - int Len, Count, i; - time_t stamp; - char * ptr1; - - if (TNC->MSGCHANNEL == 0) - { - // POLL FOR MONITOR DATA - - if (TNC->MONFLAG == 0) - goto NOMONITOR; - - // HAVE ALREADY GOT DATA PART OF MON FRAME OT SEND - - TNC->MONFLAG = 0; - - ptr1 = (UCHAR *)&TNC->MONBUFFER; - - if (TNC->MONLENGTH) - { - SENDCMDREPLY(TNC, ptr1, TNC->MONLENGTH); - return TRUE; - } - - OutputDebugString("BPQHOST Mondata Flag Set with no data"); - -NOMONITOR: - - // SEE IF ANYTHING TO MONITOR - - stamp = GetRaw(TNC->Channels[0]->BPQStream, (char *)&MONITORDATA, &Len, &Count); - - if (Len) - { - // Use Normal Decode, then reformat to DED standard - - ULONG SaveMMASK = MMASK; - BOOL SaveMTX = MTX; - BOOL SaveMCOM = MCOM; - BOOL SaveMUI = MUIONLY; - unsigned char Decoded[1000]; - - SetTraceOptionsEx(TNC->MMASK, TNC->MTX, TNC->MCOM, 0); - Len = IntDecodeFrame(&MONITORDATA, Decoded, stamp, TNC->MMASK, FALSE, FALSE); - SetTraceOptionsEx(SaveMMASK, SaveMTX, SaveMCOM, SaveMUI); - - if (Len) - { - return ConvertToDEDMonFormat(TNC, Decoded, Len, &MONITORDATA); - } - } - return 0; - } - - // Look for session data - - GetMsg(Channel->BPQStream, NODEBUFFER, &Len, &Count); - - if (Len == 0) - return 0; - - if (Len > 256) - { - Debugprintf("BPQHOST Corrupt Length = %d", Len); - return 0; - } - - // SEND DATA - - // If a failure, set a close timer (for Airmail, etc) - - NODEBUFFER[Len] = 0; // For strstr - - if (strstr(NODEBUFFER, "} Downlink connect needs port number") || - strstr(NODEBUFFER, "} Error - TNC Not Ready") || - strstr(NODEBUFFER, "} Failure with ") || - strstr(NODEBUFFER, "} Sorry, ")) - Channel->CloseTimer = CloseDelay * 10; - else - Channel->CloseTimer = 0; // Cancel Timer - - PUTCHARx(TNC, TNC->MSGCHANNEL); // REPLY ON SAME CHANNEL - PUTCHARx(TNC, 7); - PUTCHARx(TNC, Len - 1); - - for (i = 0; i < Len; i++) - { - PUTCHARx(TNC, NODEBUFFER[i]); - } - - return 1; // HAVE SEND SOMETHING -} - - - - - - - - - -// Kantronics Host Mode Stuff - -// Kantronics Host Mode Stuff - -#define FEND 0xC0 // KISS CONTROL CODES -#define FESC 0xDB -#define TFEND 0xDC -#define TFESC 0xDD - - -static VOID ProcessKHOSTPacket(struct TNCDATA * conn, UCHAR * rxbuffer, int Len); -VOID ProcessKNormCommand(struct TNCDATA * conn, UCHAR * rxbuffer); -VOID SendKISSData(struct TNCDATA * conn, UCHAR * txbuffer, int Len); -static int KissDecode(UCHAR * inbuff, UCHAR * outbuff, int len); -static int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); -static int DoReceivedData(struct TNCDATA * conn, struct StreamInfo * channel); - - - -VOID ProcessPacket(struct TNCDATA * conn, UCHAR * rxbuffer, int Len) -{ - UCHAR * FendPtr; - size_t NewLen; - - if (!conn->MODE) - { - // In Terminal Mode - Pass to Term Mode Handler - - ProcessKPacket(conn, rxbuffer, Len); - return; - } - - // Split into KISS Packets. By far the most likely is a single KISS frame - // so treat as special case - - if (!(rxbuffer[0] == FEND)) - { - // Getting Non Host Data in Host Mode - Appl will have to sort the mess - // Discard any data - - conn->RXBPtr = 0; - return; - } - - conn->RXBPtr = 0; // Assume we will use all data in buffer - will reset if part packet received - - FendPtr = memchr(&rxbuffer[1], FEND, Len-1); - - if (FendPtr == &rxbuffer[Len-1]) - { - ProcessKHOSTPacket(conn, &rxbuffer[1], Len - 2); - return; - } - - if (FendPtr == NULL) - { - // We have a partial Packet - Save it - - conn->RXBPtr = Len; - memcpy(&conn->TOUSERBUFFER[0], rxbuffer, Len); - return; - } - - // Process the first Packet in the buffer - - NewLen = FendPtr - rxbuffer -1; - ProcessKHOSTPacket(conn, &rxbuffer[1], (int)NewLen ); - - // Loop Back - - ProcessPacket(conn, FendPtr+1, Len - (int)NewLen -2); - return; - -} - -VOID ProcessKPacket(struct TNCDATA * conn, UCHAR * rxbuffer, int Len) -{ - UCHAR Char; - UCHAR * cmdStart; - int cmdlen = 0; - - // we will often get a whole connamd at once, but may not, so be prepared to receive char by char - // Could also get more than one command per packet - - cmdStart = rxbuffer; - - if (rxbuffer[0] == FEND && rxbuffer[Len-1] == FEND) - { - // Term thinks it is hosr mode - - // Unless it is FEND FF FEND (exit KISS) or FEND Q FEND (exit host) - - if (rxbuffer[2] == FEND) - { - if (rxbuffer[1] == 255 || rxbuffer[1] == 'q') - { - // If any more , process it. - - if (Len == 3) - return; - - Len -= 3; - rxbuffer+= 3; - ProcessKPacket(conn, rxbuffer, Len); - return; - } - } - conn->MODE = 1; - return; - } - - while (Len > 0) - { - Char = *(rxbuffer++); - Len--; - cmdlen++; - -// if (conn->TermPtr > 120) conn->TermPtr = 120; // Prevent overflow - - if (conn->ECHOFLAG) BPQSerialSendData(conn, &Char, 1); - - if (Char == 0x0d) - { - // We have a command line - - *(rxbuffer-1) = 0; - ProcessKNormCommand(conn, cmdStart); - conn->RXBPtr -= cmdlen; - cmdlen = 0; - cmdStart = rxbuffer; - } - } -} - -VOID ProcessKNormCommand(struct TNCDATA * conn, UCHAR * rxbuffer) -{ -// UCHAR CmdReply[]="C00"; - UCHAR ResetReply[] = "\xC0\xC0S00\xC0"; - int Len; - - char seps[] = " \t\r"; - char * Command, * Arg1, * Arg2; - char * Context; - - if (conn->Channels[1]->Connected) - { - Len = (int)strlen(rxbuffer); - rxbuffer[Len] = 0x0d; - SendMsg(conn->Channels[1]->BPQStream, rxbuffer, Len+1); - return; - } - - Command = strtok_s(rxbuffer, seps, &Context); - Arg1 = strtok_s(NULL, seps, &Context); - Arg2 = strtok_s(NULL, seps, &Context); - - if (Command == NULL) - { - BPQSerialSendData(conn, "cmd:", 4); - return; - } - - if (_stricmp(Command, "RESET") == 0) - { - if (conn->nextMode) - BPQSerialSendData(conn, ResetReply, 6); - else - BPQSerialSendData(conn, "cmd:", 4); - - - conn->MODE = conn->nextMode; - - if (conn->MODE) - EnableAppl(conn); - else - DisableAppl(conn); - - return; - } - - if (_stricmp(Command, "K") == 0) - { - int SaveAuthProg = AuthorisedProgram; - - AuthorisedProgram = 1; - SessionControl(conn->Channels[1]->BPQStream, 1, 0); - AuthorisedProgram = SaveAuthProg; - - return; - } - - if (_memicmp(Command, "IN", 2) == 0) - { - if (Arg1) - { - if (_stricmp(Arg1, "HOST") == 0) - conn->nextMode = TRUE; - else - conn->nextMode = FALSE; - } - - BPQSerialSendData(conn, "INTFACE was TERMINAL\r", 21); - BPQSerialSendData(conn, "cmd:", 4); - return; - } - -//cmd: - -//INTFACE HOST -//INTFACE was TERMINAL -//cmd:RESET -//ÀÀS00À -//ÀC20XFLOW OFFÀ - - - //SendKISSData(conn, CmdReply, 3); - - BPQSerialSendData(conn, "cmd:", 4); - - - // Process Non-Hostmode Packet - - return; -} -int FreeBytes = 999; - -static VOID ProcessKHOSTPacket(struct TNCDATA * conn, UCHAR * rxbuffer, int Len) -{ - struct StreamInfo * channel; - UCHAR Command[80]; - UCHAR Reply[400]; - UCHAR TXBuff[400]; - UCHAR CmdReply[]="C00"; - - UCHAR Chan, Stream; - int i, j, TXLen, StreamNo; - - char * Cmd, * Arg1, * Arg2, * Arg3; - char * Context; - char seps[] = " \t\r\xC0"; - int CmdLen; - - if ((Len == 1) && ((rxbuffer[0] == 'q') || (rxbuffer[0] == 'Q'))) - { - // Force Back to Command Mode - - Sleep(3000); - conn->MODE = FALSE; - BPQSerialSendData(conn, "\r\r\rcmd:", 7); - return; - } - - if (rxbuffer[0] == '?') - { - // what is this ??? - - memcpy(Reply,CmdReply,3); - SendKISSData(conn, Reply, 3); - return; - } - - Chan = rxbuffer[1]; - Stream = rxbuffer[2]; - - StreamNo = Stream == '0' ? 0 : Stream - '@'; - - if (StreamNo > conn->HOSTSTREAMS) - { - SendKISSData(conn, "C00Invalid Stream", 17); - return; - } - - switch (rxbuffer[0]) - { - case 'C': - - // Command Packet. Extract Command - - if (Len > 80) Len = 80; - - memcpy(Command, &rxbuffer[3], Len-3); - Command[Len-3] = 0; - - Cmd = strtok_s(Command, seps, &Context); - Arg1 = strtok_s(NULL, seps, &Context); - Arg2 = strtok_s(NULL, seps, &Context); - Arg3 = strtok_s(NULL, seps, &Context); - CmdLen = (int)strlen(Cmd); - - if (_stricmp(Cmd, "S") == 0) - { - // Status - - FreeBytes = 2000; - - // Ideally I should do flow control by channel, but Paclink (at least) doesn't have a mechanism - - for (i = 1; i < conn->HOSTSTREAMS; i++) - { - if (conn->Channels[i]->Connected) - if (TXCount(conn->Channels[1]->BPQStream) > 10) - FreeBytes = 0; - } - - // This format works with Paclink and RMS Packet, but it doesn't seem to conform to the spec - - // I think maybe the Channel status should be in the same Frame. - - TXLen = sprintf(Reply, "C00FREE BYTES %d\r", FreeBytes); - SendKISSData(conn, Reply, TXLen); - - for (j=1; j <= conn->HOSTSTREAMS; j++) - { - channel = conn->Channels[j]; - - if (channel->Connected) - { - TXLen = sprintf(Reply, "C00%c/V stream - CONNECTED to %s", j + '@', "SWITCH"); - SendKISSData(conn, Reply, TXLen); - } -// else -// TXLen = sprintf(Reply, "C00%c/V stream - DISCONNECTED", j + '@'); - - } - return; - } - - if (_memicmp(Cmd, "C", CmdLen) == 0) - { - int Port; - struct StreamInfo * channel; - int BPQStream; - UCHAR * MYCall; - - // Connect. If command has a via string and first call is numeric use it as a port number - - if (StreamNo == 0) - { - Stream = 'A'; - StreamNo = 1; - } - - if (Arg2 && Arg3) - { - if (_memicmp(Arg2, "via", (int)strlen(Arg2)) == 0) - { - // Have a via string as 2nd param - - Port = atoi(Arg3); - { - if (Port > 0) // First Call is numeric - { - if (strlen(Context) > 0) // More Digis - TXLen = sprintf(TXBuff, "c %s %s v %s\r", Arg3, Arg1, Context); - else - TXLen = sprintf(TXBuff, "c %s %s\r", Arg3, Arg1); - } - else - { - // First Call Isn't Numeric. This won't work, as Digis without a port is invalid - - SendKISSData(conn, "C00Invalid via String (First must be Port)", 42); - return; - - } - } - } - else - TXLen = sprintf(TXBuff, "%s %s %s %s %s\r", Cmd, Arg1, Arg2, Arg3, Context); - - } - else - { - TXLen = sprintf(TXBuff, "C %s\r", Arg1); - } - - Reply[0] = 'C'; - Reply[1] = Chan; - Reply[2] = Stream; - SendKISSData(conn, Reply, 3); - - channel = conn->Channels[StreamNo]; - BPQStream = channel->BPQStream; - MYCall = (UCHAR *)&channel->MYCall; - - Connect(BPQStream); - - if (MYCall[0] > 0) - { - ChangeSessionCallsign(BPQStream, EncodeCall(MYCall)); - } - - SendMsg(conn->Channels[StreamNo]->BPQStream, TXBuff, TXLen); - - return; - - } - - if (_stricmp(Cmd, "D") == 0) - { - // Disconnect - - if (StreamNo == 0) - { - Stream = 'A'; - StreamNo = 1; - } - - SessionControl(conn->Channels[StreamNo]->BPQStream, 2, 0); - return; - } - - if (_memicmp(Cmd, "INT", 3) == 0) - { - SendKISSData(conn, "C00INTFACE HOST", 15); - return; - } - - if (_stricmp(Cmd, "PACLEN") == 0) - { - SendKISSData(conn, "C00PACLEN 128/128", 17); - return; - } - - if (_memicmp(Cmd, "MYCALL", CmdLen > 1 ? CmdLen : 2) == 0) - { - if (strlen(Arg1) < 30) - strcpy(conn->Channels[StreamNo]->MYCall, Arg1); - } - - memcpy(Reply,CmdReply,3); - SendKISSData(conn, Reply, 3); - return; - - case 'D': - - // Data to send - - - if (StreamNo > conn->HOSTSTREAMS) return; // Protect - - TXLen = KissDecode(&rxbuffer[3], TXBuff, Len-3); - SendMsg(conn->Channels[StreamNo]->BPQStream, TXBuff, TXLen); - - conn->Channels[StreamNo]->CloseTimer = 0; // Cancel Timer - - return; - - default: - - memcpy(Reply,CmdReply,3); - SendKISSData(conn, Reply, 3); - return; - } -} - -static int KissDecode(UCHAR * inbuff, UCHAR * outbuff, int len) -{ - int i,txptr=0; - UCHAR c; - - for (i=0;iBPQStream, ConnectingCall); - strlop(ConnectingCall, ' '); - - if (conn->MODE) - { - Len = sprintf (Msg, "S1%c*** CONNECTED to %s ", Stream + '@', ConnectingCall); - SendKISSData(conn, Msg, Len); - } - else - { - Len = sprintf (Msg, "*** CONNECTED to %s\r", ConnectingCall); - BPQSerialSendData(conn, Msg, Len); - BPQSerialSetDCD(conn->hDevice); - } - - channel->Connected = TRUE; - - return 0; - -} - -int KANTDisconnected (struct TNCDATA * conn, struct StreamInfo * channel, int Stream) -{ - UCHAR Msg[50]; - int Len; - - if (conn->MODE) - { - Len = sprintf (Msg, "S1%c*** DISCONNECTED", Stream + '@'); - SendKISSData(conn, Msg, Len); - } - else - { - BPQSerialSendData(conn, "*** DISCONNECTED\r", 17); - BPQSerialClrDCD(conn->hDevice); - } - - channel->Connected = FALSE; - channel->CloseTimer = 0; - - return 0; -} - -// SCS Mode Stuff - -unsigned short int compute_crc(unsigned char *buf,int len); -VOID EmCRCStuffAndSend(struct TNCDATA * conn, UCHAR * Msg, int Len); -int APIENTRY ChangeSessionPaclen(int Stream, int Paclen); - -int EmUnstuff(UCHAR * MsgIn, UCHAR * MsgOut, int len) -{ - int i, j=0; - - for (i=0; iOutgoingCall[0]) - strcpy(ConnectedCall, Channel->OutgoingCall); - else - GetCallsign(BPQStream, ConnectedCall); - - SCSReply[2] = HostStream; - SCSReply[3] = 3; - ReplyLen = sprintf(&SCSReply[4], "(%d) CONNECTED to %s", Channel->BPQStream, ConnectedCall); - ReplyLen += 5; - EmCRCStuffAndSend(conn, SCSReply, ReplyLen); - - Channel->Connected = TRUE; - return TRUE; - } - // Disconnected - - SCSReply[2] = HostStream; - SCSReply[3] = 3; - ReplyLen = sprintf(&SCSReply[4], "(%d) DISCONNECTED fm G8BPQ", Channel->BPQStream); - ReplyLen += 5; // Include Null - EmCRCStuffAndSend(conn, SCSReply, ReplyLen); - - Channel->Connected = FALSE; - return TRUE; - } - return FALSE; -} - -BOOL SCSCheckForData(struct TNCDATA * conn, struct StreamInfo * Channel, int HostStream, int BPQStream) -{ - int Length, Count; - - GetMsg(BPQStream, &SCSReply[5], &Length, &Count); - - if (Length == 0) - return FALSE; - - if (strstr(&SCSReply[5], "} Downlink connect needs port number") || - strstr(&SCSReply[5], "} Failure with ") || - strstr(&SCSReply[5], "} Sorry, ")) - Channel->CloseTimer = CloseDelay * 10; - else - Channel->CloseTimer = 0; // Cancel Timer - - SCSReply[2] = HostStream; - SCSReply[3] = 7; - SCSReply[4] = Length - 1; - - ReplyLen = Length + 5; - EmCRCStuffAndSend(conn, SCSReply, ReplyLen); - - return TRUE; -} - -VOID ProcessSCSHostFrame(struct TNCDATA * conn, UCHAR * Buffer, int Length) -{ - int Channel = Buffer[0]; - int Command = Buffer[1] & 0x3f; - int Len = Buffer[2]; - struct StreamInfo * channel; - UCHAR TXBuff[400]; - int BPQStream; - char * MYCall; - UCHAR Stream; - int TXLen, i; - BPQVECSTRUC * HOST; - - // SCS Channel 31 is the Pactor channel, mapped to the first stream - - if (Channel == 0) - Stream = -1; - else - if (Channel == 31) - Stream = 0; - else - Stream = Channel; - - channel = conn->Channels[Stream]; - - if (conn->Toggle == (Buffer[1] & 0x80) && (Buffer[1] & 0x40) == 0) - { - // Repeat Condition - - //EmCRCStuffAndSend(conn, SCSReply, ReplyLen); - //return; - } - - conn->Toggle = (Buffer[1] & 0x80); - conn->Toggle ^= 0x80; - -// if (Channel == 255 && Len == 0) - if (Channel == 255) - { - UCHAR * NextChan = &SCSReply[4]; - - // General Poll - - // See if any channels have anything avaiilable - - for (i = 1; i <= conn->HOSTSTREAMS; i++) - { - channel = conn->Channels[i]; - HOST = &BPQHOSTVECTOR[channel->BPQStream - 1]; // API counts from 1 - - if ((HOST->HOSTFLAGS & 3)) - { - *(NextChan++) = i + 1; // Something for this channel - continue; - } - - if (RXCount(channel->BPQStream)) - *(NextChan++) = i + 1; // Something for this channel - } - - *(NextChan++) = 0; - - SCSReply[2] = 255; - SCSReply[3] = 1; - - ReplyLen = (int)(NextChan - &SCSReply[0]); - - EmCRCStuffAndSend(conn, SCSReply, ReplyLen); - return; - } - - if (Channel == 254) // Status - { - // Extended Status Poll - - //TNC->Streams[0].PTCStatus0 = Status; - // TNC->Streams[0].PTCStatus1 = PactorLevel; // Pactor Level 1-4 - // TNC->Streams[0].PTCStatus2 = Msg[7]; // Speed Level - // Offset = Msg[8]; - - SCSReply[2] = 254; - SCSReply[3] = 7; // Status - SCSReply[4] = 3; // Len -1 - - if (conn->Channels[0]->Connected) - { - SCSReply[5] = 0x0AA; - SCSReply[6] = 3; - SCSReply[7] = 5; - SCSReply[8] = 128; - } - else - { - SCSReply[5] = 0; - SCSReply[6] = 0; - SCSReply[7] = 0; - SCSReply[8] = 0; - } - ReplyLen = 9; - EmCRCStuffAndSend(conn, SCSReply, 9); - return; - } - - - if (Command == 0) - { - // Data Frame - - SendMsg(channel->BPQStream, &Buffer[3], Buffer[2]+ 1); - - goto AckIt; - } - - switch (Buffer[3]) - { - case 'J': // JHOST - - conn->MODE = FALSE; - DisableAppl(conn); - - return; - - case 'G': // Specific Poll - - if (CheckStatusChange(conn, channel, Channel, channel->BPQStream)) - return; // It has sent reply - - if (SCSCheckForData(conn, channel, Channel, channel->BPQStream)) - return; // It has sent reply - - SCSReply[2] = Channel; - SCSReply[3] = 0; - ReplyLen = 4; - EmCRCStuffAndSend(conn, SCSReply, 4); - return; - - case 'C': // Connect - - // Could be real, or just C to request status - - if (Channel == 0) - goto AckIt; - - if (Length == 0) - { - // STATUS REQUEST - IF CONNECTED, GET CALL - - return; - } - Buffer[Length - 2] = 0; - - // Save call for connected report - - if (Buffer[5] = '%' ) // Pactor long path? - { - TXLen = sprintf(TXBuff, "C %s\r", &Buffer[6]); - strcpy(channel->OutgoingCall, &Buffer[6]); - } - else - { - TXLen = sprintf(TXBuff, "C %s\r", &Buffer[5]); - strcpy(channel->OutgoingCall, &Buffer[5]); - } - - BPQStream = channel->BPQStream; - MYCall = &channel->MYCall[0]; - - if (MYCall[0] == 0) - MYCall = (char *)&conn->MYCALL; - - Connect(BPQStream); - if (MYCall[0] > 0) - { - ChangeSessionCallsign(BPQStream, EncodeCall(MYCall)); - } - - ChangeSessionPaclen(BPQStream, 100); - - SendMsg(BPQStream, TXBuff, TXLen); - - AckIt: - - SCSReply[2] = Channel; - SCSReply[3] = 0; - ReplyLen = 4; - EmCRCStuffAndSend(conn, SCSReply, 4); - return; - - case 'D': - - // Disconnect - - Disconnect(channel->BPQStream); - goto AckIt; - - case '%': - - // %X commands - - switch (Buffer[4]) - { - case 'V': // Version - - SCSReply[2] = Channel; - SCSReply[3] = 1; - strcpy(&SCSReply[4], "4.8 1.32"); - ReplyLen = 13; - EmCRCStuffAndSend(conn, SCSReply, 13); - - return; - case 'M': - - default: - - SCSReply[2] = Channel; - SCSReply[3] = 1; - SCSReply[4] = 0; - - ReplyLen = 5; - EmCRCStuffAndSend(conn, SCSReply, 5); - - return; - } - case '@': - default: - - SCSReply[2] = Channel; - SCSReply[3] = 1; - SCSReply[4] = 0; - - ReplyLen = 5; - EmCRCStuffAndSend(conn, SCSReply, 5); - } -} - - -VOID ProcessSCSTextCommand(struct TNCDATA * conn, char * Command, int Len) -{ - // Command to SCS in non-Host mode. - - // We can probably just dump anything but JHOST 4 and MYCALL - - if (Len == 1) - goto SendPrompt; // Just a CR - - Debugprintf("%s", Command); - - if (_memicmp(Command, "JHOST4", 6) == 0) - { - conn->MODE = TRUE; - conn->Toggle = 0; - EnableAppl(conn); - - return; - } - - if (_memicmp(Command, "TERM 4", 6) == 0) - conn->Term4Mode = TRUE; - - else if (_memicmp(Command, "T 0", 3) == 0) - conn->Term4Mode = FALSE; - - else if (_memicmp(Command, "PAC 4", 5) == 0) - conn->PACMode = TRUE; - - if (_memicmp(Command, "MYC", 3) == 0) - { - char * ptr = strchr(Command, ' '); - char MYResp[80]; - - Command[Len-1] = 0; // Remove CR - - if (ptr && (strlen(ptr) > 2)) - { - strcpy(conn->MYCALL, ++ptr); - } - - sprintf(MYResp, "\rMycall: >%s<", conn->MYCALL); - PUTSTRING(conn, MYResp); - } - - else if (_memicmp(Command, "SYS SERN", 8) == 0) - { - char SerialNo[] = "\r\nSerial number: 0100000000000000"; - PUTSTRING(conn, SerialNo); - } - else - { - char SerialNo[] = "\rXXXX"; - PUTSTRING(conn, SerialNo); - } - -SendPrompt: - - if (conn->PACMode) - { - PUTCHARx(conn, 13); - PUTCHARx(conn, 'p'); - PUTCHARx(conn, 'a'); - PUTCHARx(conn, 'c'); - PUTCHARx(conn, ':'); - PUTCHARx(conn, ' '); - - return; - } - - if (conn->Term4Mode) - { - PUTCHARx(conn, 13); - PUTCHARx(conn, 4); - PUTCHARx(conn, 13); - PUTCHARx(conn, 'c'); - PUTCHARx(conn, 'm'); - PUTCHARx(conn, 'd'); - PUTCHARx(conn, ':'); - PUTCHARx(conn, ' '); - PUTCHARx(conn, 1); - } - else - { - PUTCHARx(conn, 13); - PUTCHARx(conn, 'c'); - PUTCHARx(conn, 'm'); - PUTCHARx(conn, 'd'); - PUTCHARx(conn, ':'); - PUTCHARx(conn, ' '); - } - - -/* - - if (conn->Term4Mode) - PUTCHARx(conn, 4); - - PUTCHARx(conn, 13); - PUTCHARx(conn, 'c'); - PUTCHARx(conn, 'm'); - PUTCHARx(conn, 'd'); - PUTCHARx(conn, ':'); - PUTCHARx(conn, ' '); - -*/ - return; -} - - -VOID ProcessSCSPacket(struct TNCDATA * conn, UCHAR * rxbuffer, int Length) -{ - unsigned short crc; - char UnstuffBuffer[500]; - - // DED mode doesn't have an end of frame delimiter. We need to know if we have a full frame - - // Fortunately this is a polled protocol, so we only get one frame at a time - - // If first char != 170, then probably a Terminal Mode Frame. Wait for CR on end - - // If first char is 170, we could check rhe length field, but that could be corrupt, as - // we haen't checked CRC. All I can think of is to check the CRC and if it is ok, assume frame is - // complete. If CRC is duff, we will eventually time out and get a retry. The retry code - // can clear the RC buffer - -Loop: - - if (rxbuffer[0] != 170) - { - UCHAR *ptr; - int cmdlen; - - // Char Mode Frame I think we need to see CR on end (and we could have more than one in buffer - - // If we think we are in host mode, then to could be noise - just discard. - - if (conn->MODE) - { - conn->FROMUSERLEN = 0; - return; - } - - rxbuffer[Length] = 0; - - if (rxbuffer[0] == 0) - { - // Just ignore - - conn->FROMUSERLEN--; - if (conn->FROMUSERLEN) - { - memmove(rxbuffer, rxbuffer+1, conn->FROMUSERLEN + 1); - Length--; - goto Loop; - } - return; - } - if (rxbuffer[0] == 0x1b) - { - // Just ignore (I think!) - - conn->FROMUSERLEN--; - if (conn->FROMUSERLEN) - { - memmove(rxbuffer, rxbuffer+1, conn->FROMUSERLEN + 1); - Length--; - goto Loop; - } - return; - } - - if (rxbuffer[0] == 0x1e) - { - // Status POLL - - conn->FROMUSERLEN--; - if (conn->FROMUSERLEN) - { - memmove(rxbuffer, rxbuffer+1, conn->FROMUSERLEN + 1); - Length--; - goto Loop; - } - PUTCHARx(conn, 30); - PUTCHARx(conn, 0x87); - if (conn->Term4Mode) - { - PUTCHARx(conn, 13); - PUTCHARx(conn, 4); - PUTCHARx(conn, 13); - PUTCHARx(conn, 'c'); - PUTCHARx(conn, 'm'); - PUTCHARx(conn, 'd'); - PUTCHARx(conn, ':'); - PUTCHARx(conn, ' '); - PUTCHARx(conn, 1); - } - else - { - PUTCHARx(conn, 13); - PUTCHARx(conn, 'c'); - PUTCHARx(conn, 'm'); - PUTCHARx(conn, 'd'); - PUTCHARx(conn, ':'); - PUTCHARx(conn, ' '); - } - - - return; - } - ptr = strchr(rxbuffer, 13); - - if (ptr == 0) - return; // Wait for rest of frame - - ptr++; - - cmdlen = (int)(ptr - rxbuffer); - - // Complete Char Mode Frame - - conn->FROMUSERLEN -= cmdlen; // Ready for next frame - - ProcessSCSTextCommand(conn, rxbuffer, cmdlen); - - if (conn->FROMUSERLEN) - { - memmove(rxbuffer, ptr, conn->FROMUSERLEN + 1); - - if (conn->Mode) - { - // now in host mode, so pass rest up a level - - ProcessSCSPacket(conn, conn->FROMUSERBUFFER, conn->FROMUSERLEN); - return; - } - goto Loop; - } - return; - } - - // Receiving a Host Mode frame - - if (Length < 6) // Minimum Frame Sise - return; - - if (rxbuffer[2] == 170) - { - // Retransmit Request - - conn->RXBPtr = 0; - return; // Ignore for now - } - - // Can't unstuff into same buffer - fails if partial msg received, and we unstuff twice - - - Length = EmUnstuff(&rxbuffer[2], &UnstuffBuffer[2], Length - 2); - - if (Length == -1) - { - // Unstuff returned an errors (170 not followed by 0) - - conn->FROMUSERLEN = 0; - return; // Ignore for now - } - crc = compute_crc(&UnstuffBuffer[2], Length); - - if (crc == 0xf0b8) // Good CRC - { - conn->FROMUSERLEN = 0; // Ready for next frame - ProcessSCSHostFrame(conn, &UnstuffBuffer[2], Length); - return; - } - - // Bad CRC - assume incomplete frame, and wait for rest. If it was a full bad frame, timeout and retry will recover link. - - return; -} - - -VOID EmCRCStuffAndSend(struct TNCDATA * conn, UCHAR * Msg, int Len) -{ - unsigned short int crc; - UCHAR StuffedMsg[500]; - int i, j; - - crc = compute_crc(&Msg[2], Len-2); - crc ^= 0xffff; - - Msg[Len++] = (crc&0xff); - Msg[Len++] = (crc>>8); - - for (i = j = 2; i < Len; i++) - { - StuffedMsg[j++] = Msg[i]; - if (Msg[i] == 170) - { - StuffedMsg[j++] = 0; - } - } - - if (j != i) - { - Len = j; - memcpy(Msg, StuffedMsg, j); - } - - Msg[0] = 170; - Msg[1] = 170; - - BPQSerialSendData(conn, Msg, Len); -} - - - \ No newline at end of file diff --git a/V4-HPLaptop.c b/V4-HPLaptop.c deleted file mode 100644 index 7673a10..0000000 --- a/V4-HPLaptop.c +++ /dev/null @@ -1,1821 +0,0 @@ -/* -Copyright 2001-2018 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// DLL to provide interface to allow G8BPQ switch to use the V4 TNC as a Port Driver -// -// Uses BPQ EXTERNAL interface -// -// Uses a number of routines in WINMOR.c - - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include - - -#define SD_RECEIVE 0x00 -#define SD_SEND 0x01 -#define SD_BOTH 0x02 - - -#include "CHeaders.h" -#include "tncinfo.h" -#include "bpq32.h" - -int (WINAPI FAR *GetModuleFileNameExPtr)(); - -#define WSA_ACCEPT WM_USER + 1 -#define WSA_DATA WM_USER + 2 -#define WSA_CONNECT WM_USER + 3 - -static int Socket_Data(int sock, int error, int eventcode); -INT_PTR CALLBACK ConfigDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); - -KillTNC(struct TNCINFO * TNC); -RestartTNC(struct TNCINFO * TNC); -KillPopups(struct TNCINFO * TNC); -VOID MoveWindows(struct TNCINFO * TNC); -char * CheckAppl(struct TNCINFO * TNC, char * Appl); -static VOID ChangeMYC(struct TNCINFO * TNC, char * Call); -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); - -static char ClassName[]="V4STATUS"; -static char WindowTitle[] = "V4TNC"; -static int RigControlRow = 147; - -#define V4 -#define NARROWMODE 0 -#define WIDEMODE 0 - -#include - - -extern int SemHeldByAPI; - -static RECT Rect; - -struct TNCINFO * TNCInfo[34]; // Records are Malloc'd - -static int ProcessLine(char * buf, int Port); - -// RIGCONTROL COM60 19200 ICOM IC706 5e 4 14.103/U1w 14.112/u1 18.1/U1n 10.12/l1 - - - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC; - char errbuf[256]; - - strcpy(errbuf, buf); - - ptr = strtok(buf, " \t\n\r"); - - if (ptr == NULL) return (TRUE); - - if (*ptr == '#') return (TRUE); // comment - - if (*ptr == ';') return (TRUE); // comment - - if (_stricmp(buf, "ADDR")) - return FALSE; // Must start with ADDR - - ptr = strtok(NULL, " \t\n\r"); - - BPQport = Port; - p_ipad = ptr; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - - if (p_ipad == NULL) - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - WINMORport = atoi(p_port); - - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(WINMORport); - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(WINMORport+1); - - TNC->HostName = malloc(strlen(p_ipad)+1); - - if (TNC->HostName == NULL) return TRUE; - - strcpy(TNC->HostName,p_ipad); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - if (_stricmp(ptr, "CI-V") == 0) - TNC->PTTMode = PTTCI_V; - else if (_stricmp(ptr, "CAT") == 0) - TNC->PTTMode = PTTCI_V; - else if (_stricmp(ptr, "RTS") == 0) - TNC->PTTMode = PTTRTS; - else if (_stricmp(ptr, "DTR") == 0) - TNC->PTTMode = PTTDTR; - else if (_stricmp(ptr, "DTRRTS") == 0) - TNC->PTTMode = PTTDTR | PTTRTS; - else if (_stricmp(ptr, "CM108") == 0) - TNC->PTTMode = PTTCM108; - else if (_stricmp(ptr, "HAMLIB") == 0) - TNC->PTTMode = PTTHAMLIB; - - ptr = strtok(NULL, " \t\n\r"); - } - } - } - - if (ptr) - { - if (_memicmp(ptr, "PATH", 4) == 0) - { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - } - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if ((_memicmp(buf, "CAPTURE", 7) == 0) || (_memicmp(buf, "PLAYBACK", 8) == 0)) - {} // Ignore - else - if (_memicmp(buf, "WL2KREPORT", 10) == 0) - {} // Ignore - else - - strcat (TNC->InitScript, buf); - } - - return (TRUE); -} - - - -void ConnecttoWINMORThread(int port); -VOID V4ProcessDataSocketData(int port); -int ConnecttoWINMOR(); -int ProcessReceivedData(struct TNCINFO * TNC); -VOID ReleaseTNC(struct TNCINFO * TNC); -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - -#define MAXBPQPORTS 32 - -static time_t ltime; - -#pragma pack() - -static SOCKADDR_IN sinx; -static SOCKADDR_IN rxaddr; - -static int addrlen=sizeof(sinx); - -static fd_set readfs; -static fd_set writefs; -static fd_set errorfs; -static struct timeval timeout; - -static VOID ChangeMYC(struct TNCINFO * TNC, char * Call) -{ - UCHAR TXMsg[100]; - int datalen; - - if (strcmp(Call, TNC->CurrentMYC) == 0) - return; // No Change - - strcpy(TNC->CurrentMYC, Call); - -// send(TNC->TCPSock, "CODEC FALSE\r\n", 13, 0); - - datalen = sprintf(TXMsg, "MYCALL %s\r\n", Call); - send(TNC->TCPSock,TXMsg, datalen, 0); - -// send(TNC->TCPSock, "CODEC TRUE\r\n", 12, 0); -// TNC->StartSent = TRUE; - -// send(TNC->TCPSock, "MYCALL\r\n", 8, 0); -} - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int datalen; - PMSGWITHLEN buffptr; - int i,winerr; - char txbuff[500]; - char Status[80]; - unsigned int bytes,txlen=0; - char ErrMsg[255]; - int Param; - HKEY hKey=0; - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - if (TNC == NULL) - return 0; // Port not defined - - switch (fn) - { - case 1: // poll - - while (TNC->PortRecord->UI_Q) // Release anything accidentally put on UI_Q - { - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - ReleaseBuffer(buffptr); - } - - if (TNC->BusyDelay) - { - // Still Busy? - - if ((TNC->Busy & CDBusy) == 0) - { - // No, so send - - send(TNC->TCPSock, TNC->ConnectCmd, (int)strlen(TNC->ConnectCmd), 0); - TNC->Streams[0].Connecting = TRUE; - - memset(TNC->Streams[0].RemoteCall, 0, 10); - memcpy(TNC->Streams[0].RemoteCall, &TNC->ConnectCmd[11], strlen(TNC->ConnectCmd)-13); - - sprintf(Status, "%s Connecting to %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, Status); - strcpy(TNC->WEB_TNCSTATE, Status); - - free(TNC->ConnectCmd); - TNC->BusyDelay = 0; - } - else - { - // Wait Longer - - TNC->BusyDelay--; - - if (TNC->BusyDelay == 0) - { - // Timed out - Send Error Response - - PMSGWITHLEN buffptr = GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "Sorry, Can't Connect - Channel is busy\r"); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - free(TNC->ConnectCmd); - - } - } - } - - if (TNC->HeartBeat++ > 600 || (TNC->Streams[0].Connected && TNC->HeartBeat > 50)) // Every Minute unless connected - { - TNC->HeartBeat = 0; - - if (TNC->CONNECTED) - - // Probe link - - send(TNC->TCPSock, "BUFFER\r\n", 8, 0); - } - - if (TNC->FECMode) - { - if (TNC->FECIDTimer++ > 6000) // ID every 10 Mins - { - if (!TNC->Busy) - { - TNC->FECIDTimer = 0; - send(TNC->TCPSock, "SENDID 0\r\n", 10, 0); - } - } - if (TNC->FECPending) // Check if FEC Send needed - { - if (!TNC->Busy) - { - TNC->FECPending = 0; - - if (TNC->FEC1600) - send(TNC->TCPSock,"FECSEND 1600\r\n", 14, 0); - else - send(TNC->TCPSock,"FECSEND 500\r\n", 13, 0); - } - } - } - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - { - // Send the DISCONNECT - - send(TNC->TCPSock,"ARQEND\r\n", 8, 0); - TNC->Streams[0].ARQENDSent = TRUE; - } - } - - if (TNC->DiscPending) - { - TNC->DiscPending--; - - if (TNC->DiscPending == 0) - { - // Too long in Disc Pending - Kill and Restart TNC - - if (TNC->PID) - { - KillTNC(TNC); - RestartTNC(TNC); - } - } - } -/* - if (TNC->UpdateWL2K) - { - TNC->UpdateWL2KTimer--; - - if (TNC->UpdateWL2KTimer == 0) - { - TNC->UpdateWL2KTimer = 32910/2; // Every Hour - if (CheckAppl(TNC, "RMS ")) // Is RMS Available? - SendReporttoWL2K(TNC); - } - } -*/ - if (TNC->RIG) - { - if (TNC->RIG->RigFreq != TNC->LastFreq) - { - char FREQMsg[80]; - int Len; - - TNC->LastFreq = TNC->RIG->RigFreq; - Len = sprintf(FREQMsg, "DISPLAY CF:%1.4f\r\n", TNC->LastFreq + .0015); - send(TNC->TCPSock,FREQMsg, Len, 0); - } - } - - if (TNC->TimeSinceLast++ > 700) // Allow 10 secs for Keepalive - { - // Restart TNC - - if (TNC->ProgramPath) - { - if (strstr(TNC->ProgramPath, "V4 TNC")) - { - struct tm * tm; - char Time[80]; - - TNC->Restarts++; - TNC->LastRestart = time(NULL); - - tm = gmtime(&TNC->LastRestart); - - sprintf_s(Time, sizeof(Time),"%04d/%02d/%02d %02d:%02dZ", - tm->tm_year +1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); - - MySetWindowText(TNC->xIDC_RESTARTTIME, Time); - strcpy(TNC->WEB_RESTARTTIME, Time); - - sprintf_s(Time, sizeof(Time),"%d", TNC->Restarts); - MySetWindowText(TNC->xIDC_RESTARTS, Time); - strcpy(TNC->WEB_RESTARTS, Time); - - KillTNC(TNC); - RestartTNC(TNC); - - TNC->TimeSinceLast = 0; - } - } - } - - if (TNC->PortRecord->ATTACHEDSESSIONS[0] && TNC->Streams[0].Attached == 0) - { - // New Attach - - int calllen; - char Msg[80]; - - TNC->Streams[0].Attached = TRUE; - TNC->Streams[0].ARQENDSent = FALSE; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4USER, TNC->Streams[0].MyCall); - TNC->Streams[0].MyCall[calllen] = 0; - - // Stop Listening, and set MYCALL to user's call - -// send(TNC->TCPSock, "LISTEN FALSE\r\n", 14, 0); - ChangeMYC(TNC, TNC->Streams[0].MyCall); - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - sprintf(Status, "In Use by %s", TNC->Streams[0].MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, Status); - strcpy(TNC->WEB_TNCSTATE, Status); - - // Stop Scanning - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command(-1, Msg); - - } - - if (TNC->Streams[0].Attached) - CheckForDetach(TNC, 0, &TNC->Streams[0], TidyClose, ForcedClose, CloseComplete); - - if (TNC->Streams[0].ReportDISC) - { - TNC->Streams[0].ReportDISC = FALSE; - buff->PORT = 0; - return -1; - } - - if (TNC->CONNECTED == FALSE && TNC->CONNECTING == FALSE) - { - // See if time to reconnect - - time(<ime); - if (ltime - TNC->lasttime >9 ) - { - TNC->LastFreq = 0; // so display will be updated - ConnecttoWINMOR(port); - TNC->lasttime = ltime; - } - } - - FD_ZERO(&readfs); - - if (TNC->CONNECTED) FD_SET(TNC->TCPDataSock,&readfs); - - FD_ZERO(&writefs); - - if (TNC->BPQtoWINMOR_Q) FD_SET(TNC->TCPDataSock,&writefs); // Need notification of busy clearing - - FD_ZERO(&errorfs); - - if (TNC->CONNECTING || TNC->CONNECTED) FD_SET(TNC->TCPDataSock,&errorfs); - - if (select((int)TNC->TCPSock + 1, &readfs, &writefs, &errorfs, &timeout) > 0) - { - // See what happened - - if (readfs.fd_count == 1) - V4ProcessDataSocketData(port); - - if (writefs.fd_count == 1) - { - // Write block has cleared. Send rest of packet - - buffptr=Q_REM(&TNC->BPQtoWINMOR_Q); - txlen = (unsigned int)buffptr->Len; - - memcpy(txbuff,buffptr->Data, txlen); - bytes=send(TNC->TCPSock,(const char FAR *)&txbuff,txlen,0); - ReleaseBuffer(buffptr); - } - - if (errorfs.fd_count == 1) - { - i=sprintf(ErrMsg, "V4 Data Connection lost for BPQ Port %d\n", port); - WritetoConsole(ErrMsg); - TNC->CONNECTING = FALSE; - TNC->CONNECTED = FALSE; - TNC->Streams[0].ReportDISC = TRUE; - } - } - - // See if any frames for this port - - if (TNC->WINMORtoBPQ_Q != 0) - { - buffptr = Q_REM(&TNC->WINMORtoBPQ_Q); - - datalen = (int)buffptr->Len; - - buff->PORT = 0; // Compatibility with Kam Driver - buff->PID = 0xf0; - memcpy(&buff->L2DATA[0], buffptr->Data, datalen); - - datalen += sizeof(void *) + 4; - PutLengthinBuffer(buff, (int)datalen); - - ReleaseBuffer(buffptr); - - return (1); - } - - return (0); - - case 2: // send - - if (!TNC->CONNECTED) - { - // Send Error Response - - PMSGWITHLEN buffptr = GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "No Connection to V4 TNC\r"); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - return 0; // Don't try if not connected - } - - if (TNC->BPQtoWINMOR_Q) - return 0; // Socket is blocked - just drop packets till it clears - - if (TNC->SwallowSignon) - { - TNC->SwallowSignon = FALSE; // Discard *** connected - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - - if (TNC->Streams[0].Connected) - bytes=send(TNC->TCPDataSock, buff->L2DATA, txlen,0); - else - { - if (_memicmp(buff->L2DATA, "D\r", 2) == 0) - { - TNC->Streams[0].ReportDISC = TRUE; // Tell Node - return 0; - } - - if (TNC->FECMode) - { - char Buffer[300]; - int len; - - // Send FEC Data - - buff->L2DATA[txlen] = 0; - len = sprintf(Buffer, "%-9s: %s", TNC->Streams[0].MyCall, buff->L2DATA); - - send(TNC->TCPDataSock, Buffer, len, 0); - -/* if (TNC->Busy) - { - TNC->FECPending = 1; - } - else - { - if (TNC->FEC1600) - send(TNC->TCPSock,"FECSEND 1600\r\n", 14, 0); - else - send(TNC->TCPSock,"FECSEND 500\r\n", 13, 0); - } -*/ return 0; - } - - - // See if Local command (eg RADIO) - - if (_memicmp(buff->L2DATA, "RADIO ", 6) == 0) - { - sprintf(buff->L2DATA, "%d %s", TNC->Port, &buff->L2DATA[6]); - - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK->CIRCUITINDEX, buff->L2DATA)) - { - } - else - { - PMSGWITHLEN buffptr = GetBuff(); - - if (buffptr == 0) return 1; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, buff->L2DATA); - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - } - return 1; - } - - if (_memicmp(buff->L2DATA, "CODEC TRUE", 9) == 0) - TNC->StartSent = TRUE; - - if (_memicmp(buff->L2DATA, "D\r", 2) == 0) - { - TNC->Streams[0].ReportDISC = TRUE; // Tell Node - return 0; - } - - if (_memicmp(&buff[8], "FEC\r", 4) == 0 || _memicmp(&buff[8], "FEC ", 4) == 0) - { - TNC->FECMode = TRUE; - TNC->FECIDTimer = 0; - send(TNC->TCPSock,"MODE FEC\r\n", 10, 0); - strcpy(TNC->WEB_MODE, "FEC"); - MySetWindowText(TNC->xIDC_MODE, TNC->WEB_MODE); - - return 0; - } - - // See if a Connect Command. If so, start codec and set Connecting - - if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect - { - char Connect[80] = "ARQCONNECT "; - - memcpy(&Connect[11], &buff->L2DATA[2], txlen); - txlen += 9; - Connect[txlen++] = 0x0a; - Connect[txlen] = 0; - - _strupr(Connect); - - // See if Busy - - if (TNC->Busy & CDBusy) - { - // Channel Busy. Unless override set, wait - - if (TNC->OverrideBusy == 0) - { - // Save Command, and wait up to 10 secs - - TNC->ConnectCmd = _strdup(Connect); - TNC->BusyDelay = 100; // 10 secs - return 0; - } - } - - TNC->OverrideBusy = FALSE; - - bytes=send(TNC->TCPSock, Connect, txlen, 0); - TNC->Streams[0].Connecting = TRUE; - - memset(TNC->Streams[0].RemoteCall, 0, 10); - memcpy(TNC->Streams[0].RemoteCall, &Connect[11], txlen-13); - - sprintf(Status, "%s Connecting to %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, Status); - strcpy(TNC->WEB_TNCSTATE, Status); - - } - else - { - buff->L2DATA[txlen++] = 0x0a; - bytes=send(TNC->TCPSock, buff->L2DATA, txlen, 0); - } - } - if (bytes != txlen) - { - - // WINMOR doesn't seem to recover from a blocked write. For now just reset - -// if (bytes == SOCKET_ERROR) -// { - winerr=WSAGetLastError(); - - i=sprintf(ErrMsg, "V4 Write Failed for port %d - error code = %d\n", port, winerr); - WritetoConsole(ErrMsg); - - -// if (winerr != WSAEWOULDBLOCK) -// { - closesocket(TNC->TCPSock); - - TNC->CONNECTED = FALSE; - - return (0); -// } -// else -// { -// bytes=0; // resent whole packet -// } - -// } - - // Partial Send or WSAEWOULDBLOCK. Save data, and send once busy clears - - - // Get a buffer - -// buffptr=GetBuff(); - -// if (buffptr == 0) -// { - // No buffers, so can only break connection and try again - -// closesocket(TCPSock[MasterPort[port]]); - -// CONNECTED[MasterPort[port]]=FALSE; - -// return (0); -// } - -// buffptr->Len=txlen-bytes; // Bytes still to send - -// memcpy(buffptr+2,&txbuff[bytes],txlen-bytes); - -// C_Q_ADD(&BPQtoWINMOR_Q[MasterPort[port]],buffptr); - -// return (0); - } - - - return (0); - - case 3: - - // CHECK IF OK TO SEND (And check TNC Status) - - if (TNC->Streams[0].Attached == 0) - return TNC->CONNECTED << 8 | 1; - - return (TNC->CONNECTED << 8 | TNC->Streams[0].Disconnecting << 15); // OK - - break; - - case 4: // reinit - - return (0); - - case 5: // Close - - send(TNC->TCPSock, "CODEC FALSE\r\n", 13, 0); - Sleep(100); - shutdown(TNC->TCPDataSock, SD_BOTH); - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - - closesocket(TNC->TCPDataSock); - closesocket(TNC->TCPSock); - - if (TNC->PID && TNC->WeStartedTNC) - { - KillTNC(TNC); - } - - return (0); - - case 6: // Scan Stop Interface - - Param = (int)(size_t)buff; - - if (Param == 1) // Request Permission - { - if (!TNC->ConnectPending) - return 0; // OK to Change - -// send(TNC->TCPSock, "LISTEN FALSE\r\n", 14, 0); - - return TRUE; - } - - if (Param == 2) // Check Permission - { - if (TNC->ConnectPending) - return -1; // Skip Interval - - return 1; // OK to change - } - - if (Param == 3) // Release Permission - { -// send(TNC->TCPSock, "LISTEN TRUE\r\n", 13, 0); - return 0; - } - - if (Param == 4) // Set Wide Mode - { - send(TNC->TCPSock, "BW 1600\r\n", 9, 0); - return 0; - } - - if (Param == 5) // Set Narrow Mode - { - send(TNC->TCPSock, "BW 500\r\n", 8, 0); - return 0; - } - - return 0; - } - return 0; -} - -VOID V4ProcessDataSocketData(int port) -{ - // Info on Data Socket - just packetize and send on - - struct TNCINFO * TNC = TNCInfo[port]; - int InputLen, PacLen = 236, i; - PMSGWITHLEN buffptr; - char * msg; - - TNC->TimeSinceLast = 0; - -loop: - buffptr = GetBuff(); - - if (buffptr == NULL) return; // No buffers, so ignore - - InputLen=recv(TNC->TCPDataSock, (char *)&buffptr[2], PacLen, 0); - - if (InputLen == -1) - { - ReleaseBuffer(buffptr); - return; - } - - - //Debugprintf("Winmor: RXD %d bytes", InputLen); - - if (InputLen == 0) - { - // Does this mean closed? - - strcpy(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - - TNC->CONNECTING = FALSE; - TNC->CONNECTED = FALSE; - TNC->Streams[0].ReportDISC = TRUE; - - ReleaseBuffer(buffptr); - return; - } - - - msg = buffptr->Data; - - // Message should always be received in 17 char chunks. 17th is a status byte - // In ARQ, 6 = "Echo as sent" ack - - if (InputLen != 17) - { - Debugprintf("V4 TNC incorrect RX Len = %d", InputLen); - goto loop; - } - - if (msg[16] == 0x06) - goto loop; - - InputLen = 16; - - for (i = 0; i < 16; i++) - { - if (msg[i] == 0) - break; - - if (msg[i] == 10) - continue; - - if (msg[i] < 0x20 || msg[i] > 0x7e) - msg[i] = '?'; - } - - - msg[InputLen] = 0; - - WritetoTrace(TNC, msg, InputLen); - - // V4 Sends null padded blocks - - InputLen = (int)strlen(buffptr->Data); - - if (msg[InputLen - 1] == 10) // LF - { - // Replace with CRLF - - msg[InputLen-1] = 13; // Add CR - msg[InputLen++] = 10; - } - - buffptr->Len = InputLen; - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - goto loop; -} - - - - -static VOID ReleaseTNC(struct TNCINFO * TNC) -{ - // Set mycall back to Node or Port Call - - ChangeMYC(TNC, TNC->NodeCall); - -// send(TNC->TCPSock, "LISTEN TRUE\r\nMAXCONREQ 4\r\n", 26, 0); - - MySetWindowText(TNC->xIDC_TNCSTATE, "Free"); - strcpy(TNC->WEB_TNCSTATE, "Free"); - - // Start Scanner - - ReleaseOtherPorts(TNC); - -} - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, "" - "" - "V4 Status" - "

V4 Status

"); - - Len += sprintf(&Buff[Len], ""); - - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); -// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
Proto State%s
Traffic%s
TNC Restarts
"); - - Len += sprintf(&Buff[Len], "", TNC->WebBuffer); - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - - - - -void * V4ExtInit(EXTPORTDATA * PortEntry) -{ - int i, port; - char Msg[255]; - char * ptr; - struct TNCINFO * TNC; - char * TempScript; - - port = PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); - WritetoConsole(Msg); - - return ExtProc; - } - - TNC->Port = port; - - if (TNC->ProgramPath) - TNC->WeStartedTNC = RestartTNC(TNC); - - TNC->Hardware = H_V4; - - TNC->PortRecord = PortEntry; - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - memcpy(TNC->NodeCall, MYNODECALL, 10); - else - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - TNC->Interlock = PortEntry->PORTCONTROL.PORTINTERLOCK; - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - PortEntry->MAXHOSTMODESESSIONS = 1; -// PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 236; - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - // Set Essential Params and MYCALL - - // Put overridable ones on front, essential ones on end - - TempScript = malloc(1000); - - strcpy(TempScript, "DebugLog True\r\n"); - strcat(TempScript, "AUTOID FALSE\r\n"); - strcat(TempScript, "CODEC FALSE\r\n"); - strcat(TempScript, "TIMEOUT 90\r\n"); - strcat(TempScript, "MODE ARQ\r\n"); - strcat(TempScript, "TUNING 100\r\n"); - - strcat(TempScript, TNC->InitScript); - - free(TNC->InitScript); - TNC->InitScript = TempScript; - - // Set MYCALL - - -// strcat(TNC->InitScript,"FECRCV True\r\n"); - - sprintf(Msg, "MYCALL %s\r\nCODEC TRUE\r\nMYCALL\r\n", TNC->NodeCall); - strcat(TNC->InitScript, Msg); - - strcat(TNC->InitScript,"PROCESSID\r\n"); - - strcpy(TNC->CurrentMYC, TNC->NodeCall); - - if (TNC->destaddr.sin_family == 0) - { - // not defined in config file, so use localhost and port from IOBASE - - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(PortEntry->PORTCONTROL.IOBASE); - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(PortEntry->PORTCONTROL.IOBASE+1); - - TNC->HostName=malloc(10); - - if (TNC->HostName != NULL) - strcpy(TNC->HostName,"127.0.0.1"); - - } - - - PortEntry->PORTCONTROL.TNC = TNC; - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 520; - TNC->WebWinY = 500; - TNC->WebBuffer = zalloc(5000); - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - TNC->WEB_CHANSTATE = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_PROTOSTATE = zalloc(100); - TNC->WEB_RESTARTTIME = zalloc(100); - TNC->WEB_RESTARTS = zalloc(100); - - TNC->WEB_MODE = zalloc(20); - TNC->WEB_TRAFFIC = zalloc(100); - - - -#ifndef LINBPQ - - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 450, 500, ForcedClose); - - CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,6,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,6,386,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,28,106,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,28,520,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,50,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,50,200,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,72,110,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,72,144,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,94,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,116,94,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,116,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,116,40,20 , TNC->hDlg, NULL, hInstance, NULL); - CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,116,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,116,200,20, TNC->hDlg, NULL, hInstance, NULL); - - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, - 0,138,250,300, TNC->hDlg, NULL, hInstance, NULL); - - - TNC->ClientHeight = 450; - TNC->ClientWidth = 500; - - TNC->hMenu = CreatePopupMenu(); - - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill V4 TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart V4 TNC"); -// AppendMenu(TNC->hPopMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after each Connection"); -// CheckMenuItem(TNC->hPopMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); - - - MoveWindows(TNC); -#endif - i=sprintf(Msg,"V4 Host %s %d\n", TNC->HostName, htons(TNC->destaddr.sin_port)); - WritetoConsole(Msg); - - strcpy(TNC->WEB_MODE, "ARQ"); - MySetWindowText(TNC->xIDC_MODE, TNC->WEB_MODE); - ConnecttoWINMOR(port); - - time(&TNC->lasttime); // Get initial time value - - return ExtProc; -} - -#ifndef LINBPQ - -static BOOL CALLBACK EnumTNCWindowsProc(HWND hwnd, LPARAM lParam) -{ - char wtext[100]; - struct TNCINFO * TNC = (struct TNCINFO *)lParam; - UINT ProcessId; - - GetWindowText(hwnd,wtext,99); - - if (memcmp(wtext,"Registration", 12) == 0) - { - SendMessage(hwnd, WM_CLOSE, 0, 0); - return TRUE; - } - if (memcmp(wtext,"V4 Sound Card TNC", 17) == 0) - { - GetWindowThreadProcessId(hwnd, &ProcessId); - - if (TNC->PID == ProcessId) - { - // Our Process - - sprintf (wtext, "V4 Sound Card TNC - BPQ %s", TNC->PortRecord->PORTCONTROL.PORTDESCRIPTION); - MySetWindowText(hwnd, wtext); - // return FALSE; - } - } - - return (TRUE); -} -#endif - -static VOID ProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) -{ - // Response on WINMOR control channel. Could be a reply to a command, or - // an Async Response - - PMSGWITHLEN buffptr; - char Status[80]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - if (_memicmp(Buffer, "FAULT failure to Restart Sound card", 20) == 0) - { - // Force a restart - - send(TNC->TCPSock, "CODEC FALSE\r\n", 13, 0); - send(TNC->TCPSock, "CODEC TRUE\r\n", 12, 0); - } - else - { - TNC->TimeSinceLast = 0; - } - - Buffer[MsgLen - 2] = 0; // Remove CRLF - - if (_memicmp(Buffer, "PTT T", 5) == 0) - { - TNC->Busy |= PTTBusy; - if (TNC->PTTMode) - Rig_PTT(TNC->RIG, TRUE); - return; - } - if (_memicmp(Buffer, "PTT F", 5) == 0) - { - TNC->Busy &= ~PTTBusy; - if (TNC->PTTMode) - Rig_PTT(TNC->RIG, FALSE); - return; - } - - if (_memicmp(Buffer, "BUSY TRUE", 9) == 0) - { - TNC->Busy |= CDBusy; - MySetWindowText(TNC->xIDC_CHANSTATE, "Busy"); - strcpy(TNC->WEB_CHANSTATE, "Busy"); - - return; - } - - if (_memicmp(Buffer, "BUSY FALSE", 10) == 0) - { - TNC->Busy &= ~CDBusy; - MySetWindowText(TNC->xIDC_CHANSTATE, "Clear"); - strcpy(TNC->WEB_CHANSTATE, "Clear"); - return; - } - - if (_memicmp(Buffer, "OFFSET", 6) == 0) - { -// WritetoTrace(TNC, Buffer, MsgLen - 2); -// memcpy(TNC->TargetCall, &Buffer[7], 10); - return; - } - - if (_memicmp(Buffer, "CONNECTED", 9) == 0) - { - char Call[11]; - char * ptr; - char * ApplPtr = APPLS; - APPLCALLS * APPL; - int App; - char Appl[10]; - - WritetoTrace(TNC, Buffer, MsgLen - 2); - - STREAM->ConnectTime = time(NULL); - - memcpy(Call, &Buffer[10], 10); - - ptr = strchr(Call, ' '); - if (ptr) *ptr = 0; - - TNC->HadConnect = TRUE; - - if (TNC->PortRecord->ATTACHEDSESSIONS[0] == 0) - { - // Incomming Connect - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - ProcessIncommingConnect(TNC, Call, 0, TRUE); - TNC->Streams[0].ARQENDSent = FALSE; - - if (TNC->RIG) - sprintf(Status, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, TNC->TargetCall, TNC->RIG->Valchar); - else - sprintf(Status, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, TNC->TargetCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, Status); - strcpy(TNC->WEB_TNCSTATE, Status); - - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(TNC->CurrentMYC, Appl) == 0) - break; - } - - if (App < 32) - { - char AppName[13]; - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // Make sure app is available - - if (CheckAppl(TNC, AppName)) - { - MsgLen = sprintf(Buffer, "%s\r", AppName); - - GetSemaphore(&Semaphore, 50); - - buffptr = GetBuff(); - - if (buffptr == 0) - { - FreeSemaphore(&Semaphore); - return; // No buffers, so ignore - } - - buffptr->Len = MsgLen; - memcpy(buffptr+2, Buffer, MsgLen); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - FreeSemaphore(&Semaphore); - - TNC->SwallowSignon = TRUE; - } - else - { - char Msg[] = "Application not available\r\n"; - - // Send a Message, then a disconenct - - send(TNC->TCPDataSock, Msg, (int)strlen(Msg), 0); - STREAM->NeedDisc = 100; // 10 secs - } - } - - return; - } - else - { - // Connect Complete - - char Reply[80]; - int ReplyLen; - - buffptr = GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - ReplyLen = sprintf(Reply, "*** Connected to %s\r", &Buffer[10]); - - buffptr->Len = ReplyLen; - memcpy(buffptr+2, Reply, ReplyLen); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - TNC->Streams[0].Connecting = FALSE; - TNC->Streams[0].Connected = TRUE; // Subsequent data to data channel - - if (TNC->RIG) - sprintf(Status, "%s Connected to %s Outbound Freq %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall, TNC->RIG->Valchar); - else - sprintf(Status, "%s Connected to %s Outbound", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, Status); - strcpy(TNC->WEB_TNCSTATE, Status); - - UpdateMH(TNC, Call, '+', 'O'); - - return; - } - } - - if (_memicmp(Buffer, "DISCONNECTED", 12) == 0) - { - if (TNC->FECMode) - return; - - if (TNC->StartSent) - { - TNC->StartSent = FALSE; // Disconnect reported following start codec - return; - } - - if (TNC->Streams[0].Connecting) - { - // Report Connect Failed, and drop back to command mode - - TNC->Streams[0].Connecting = FALSE; - buffptr = GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "V4} Failure with %s\r", TNC->Streams[0].RemoteCall); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - sprintf(Status, "In Use by %s", TNC->Streams[0].MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, Status); - strcpy(TNC->WEB_TNCSTATE, Status); - - return; - } - - WritetoTrace(TNC, Buffer, MsgLen - 2); - - // Release Session - - TNC->Streams[0].Connecting = FALSE; - TNC->Streams[0].Connected = FALSE; // Back to Command Mode - TNC->Streams[0].ReportDISC = TRUE; // Tell Node - - if (TNC->Streams[0].Disconnecting) // - ReleaseTNC(TNC); - - TNC->Streams[0].Disconnecting = FALSE; - - return; - } - - if (_memicmp(Buffer, "CMD", 3) == 0) - { - return; - } - - if (_memicmp(Buffer, "PENDING", 6) == 0) - return; - -/* - - if (_memicmp(Buffer, "FAULT Not connected!", 20) == 0) - { - // If in response to ARQEND, assume Disconnected was missed - - if (TNC->Streams[0].Disconnecting) - { - TNC->Streams[0].Connecting = FALSE; - TNC->Streams[0].Connected = FALSE; // Back to Command Mode - TNC->Streams[0].ReportDISC = TRUE; // Tell Node - - ReleaseTNC(TNC); - - TNC->Streams[0].Disconnecting = FALSE; - } - } -*/ - if (_memicmp(Buffer, "FAULT", 5) == 0) - { - WritetoTrace(TNC, Buffer, MsgLen - 2); - return; - } - - if (_memicmp(Buffer, "BUFFER", 6) == 0) - { - sscanf(&Buffer[7], "%d", &TNC->Streams[0].BytesOutstanding); - - if (TNC->Streams[0].BytesOutstanding == 0) - { - // all sent - - if (TNC->Streams[0].Disconnecting) // Disconnect when all sent - { - if (TNC->Streams[0].ARQENDSent == FALSE) - { - send(TNC->TCPSock,"ARQEND\r\n", 8, 0); - TNC->Streams[0].ARQENDSent = TRUE; - } - } - } - else - { - // Make sure Node Keepalive doesn't kill session. - - TRANSPORTENTRY * SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - if (SESS) - { - SESS->L4KILLTIMER = 0; - SESS = SESS->L4CROSSLINK; - if (SESS) - SESS->L4KILLTIMER = 0; - } - } - - MySetWindowText(TNC->xIDC_TRAFFIC, &Buffer[7]); - strcpy(TNC->WEB_TRAFFIC, &Buffer[7]); - - return; - } - - if (_memicmp(Buffer, "PROCESSID", 9) == 0) - { - HANDLE hProc; - char ExeName[256] = ""; - - TNC->PID = atoi(&Buffer[10]); - - // Get the File Name in case we want to restart it. - - if (GetModuleFileNameExPtr) - { - hProc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, TNC->PID); - - if (hProc) - { - GetModuleFileNameExPtr(hProc, 0, ExeName, 255); - CloseHandle(hProc); - - if (TNC->ProgramPath) - free(TNC->ProgramPath); - - TNC->ProgramPath = _strdup(ExeName); - } - } - - // Set Window Title to reflect BPQ Port Description - -#ifndef LINBPQ - EnumWindows(EnumTNCWindowsProc, (LPARAM)TNC); -#endif - } - - if (_memicmp(Buffer, "PLAYBACKDEVICES", 15) == 0) - { - TNC->PlaybackDevices = _strdup(&Buffer[16]); - } - // Others should be responses to commands - - if (_memicmp(Buffer, "BLOCKED", 6) == 0) - { - WritetoTrace(TNC, Buffer, MsgLen - 2); - return; - } - - if (_memicmp(Buffer, "CONREQ", 6) == 0) - { - // if to one of our APPLCALLS, change TNC MYCALL - - APPLCALLS * APPL; - char Appl[11]; - char Target[20]; - char * ptr; - int i; - - memcpy(Target, &Buffer[7], 12); - ptr = memchr(Target, ' ', 12); - if (ptr) - *ptr = 0; - - if (strcmp(Target, TNC->NodeCall) == 0) - ChangeMYC(TNC, Target); - else - { - for (i = 0; i < 32; i++) - { - APPL=&APPLCALLTABLE[i]; - - if (APPL->APPLCALL_TEXT[0] > ' ') - { - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (strcmp(Appl, Target) == 0) - { - ChangeMYC(TNC, Target); - break; - } - } - } - } - WritetoTrace(TNC, Buffer, MsgLen - 2); - - // Update MH - - ptr = strstr(Buffer, " de "); - if (ptr) - UpdateMH(TNC, ptr + 4, '!', 'O'); - } - - buffptr = GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "V4} %s\r", Buffer); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - -} - -int V4ProcessReceivedData(struct TNCINFO * TNC) -{ - char ErrMsg[255]; - - int InputLen, MsgLen; - char * ptr, * ptr2; - char Buffer[2000]; - - // May have several messages per packet, or message split over packets - - if (TNC->InputLen > 1000) // Shouldnt have lines longer than this on command connection - TNC->InputLen=0; - - InputLen=recv(TNC->TCPSock, &TNC->TCPBuffer[TNC->InputLen], 1000 - TNC->InputLen, 0); - - if (InputLen == 0 || InputLen == SOCKET_ERROR) - { - // Does this mean closed? - - if (!TNC->CONNECTING) - { - sprintf(ErrMsg, "V4TNC Connection lost for BPQ Port %d\r\n", TNC->Port); - WritetoConsole(ErrMsg); - } - TNC->CONNECTING = FALSE; - TNC->CONNECTED = FALSE; - TNC->Streams[0].ReportDISC = TRUE; - - return 0; - } - - TNC->InputLen += InputLen; - -loop: - - ptr = memchr(TNC->TCPBuffer, '\n', TNC->InputLen); - - if (ptr) // CR in buffer - { - ptr2 = &TNC->TCPBuffer[TNC->InputLen]; - ptr++; // Assume LF Follows CR - - if (ptr == ptr2) - { - // Usual Case - single meg in buffer - - ProcessResponse(TNC, TNC->TCPBuffer, TNC->InputLen); - TNC->InputLen=0; - } - else - { - // buffer contains more that 1 message - - MsgLen = TNC->InputLen - (int)(ptr2 - ptr); - - memcpy(Buffer, TNC->TCPBuffer, MsgLen); - - ProcessResponse(TNC, Buffer, MsgLen); - - memmove(TNC->TCPBuffer, ptr, TNC->InputLen-MsgLen); - - TNC->InputLen -= MsgLen; - goto loop; - } - } - return 0; -} - -/* -INT_PTR CALLBACK ConfigDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - int Cmd = LOWORD(wParam); - - switch (message) - { - case WM_INITDIALOG: - { - struct TNCINFO * TNC = (struct TNCINFO * )lParam; - char * ptr1, *ptr2; - int ptr3 = 0; - char Line[1000]; - int len; - - ptr1 = TNC->CaptureDevices; - - if (!ptr1) - return 0; // No Devices - - - while (ptr2 = strchr(ptr1, ',')) - { - len = ptr2 - ptr1; - memcpy(&Line[ptr3], ptr1, len); - ptr3 += len; - Line[ptr3++] = '\r'; - Line[ptr3++] = '\n'; - - ptr1 = ++ptr2; - } - Line[ptr3] = 0; - strcat(Line, ptr1); - - SetDlgItemText(hDlg, IDC_CAPTURE, Line); - - ptr3 = 0; - - ptr1 = TNC->PlaybackDevices; - - if (!ptr1) - return 0; // No Devices - - - while (ptr2 = strchr(ptr1, ',')) - { - len = ptr2 - ptr1; - memcpy(&Line[ptr3], ptr1, len); - ptr3 += len; - Line[ptr3++] = '\r'; - Line[ptr3++] = '\n'; - - ptr1 = ++ptr2; - } - Line[ptr3] = 0; - strcat(Line, ptr1); - - SetDlgItemText(hDlg, IDC_PLAYBACK, Line); - - SendDlgItemMessage(hDlg, IDC_PLAYBACK, EM_SETSEL, -1, 0); - -// KillTNC(TNC); - - return TRUE; - } - - case WM_SIZING: - { - return TRUE; - } - - case WM_ACTIVATE: - -// SendDlgItemMessage(hDlg, IDC_MESSAGE, EM_SETSEL, -1, 0); - - break; - - - case WM_COMMAND: - - - if (Cmd == IDCANCEL) - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - - return (INT_PTR)TRUE; - - break; - } - return (INT_PTR)FALSE; -} -*/ -static VOID TidyClose(struct TNCINFO * TNC, int Stream) -{ - // If all acked, send disc - - if (TNC->Streams[0].BytesOutstanding == 0) - { - send(TNC->TCPSock,"ARQEND\r\n", 8, 0); - TNC->Streams[0].ARQENDSent = TRUE; - } -} - -static VOID ForcedClose(struct TNCINFO * TNC, int Stream) -{ - send(TNC->TCPSock,"ABORT\r\n", 7, 0); -} - -VOID CloseComplete(struct TNCINFO * TNC, int Stream) -{ - ReleaseTNC(TNC); - - ChangeMYC(TNC, TNC->NodeCall); // In case changed to an applcall - - if (TNC->FECMode) - { - TNC->FECMode = FALSE; - send(TNC->TCPSock,"MODE ARQ\r\n", 10, 0); - strcpy(TNC->WEB_MODE, "ARQ"); - MySetWindowText(TNC->xIDC_MODE, TNC->WEB_MODE); - } -} diff --git a/VARA-HPLaptop.c b/VARA-HPLaptop.c deleted file mode 100644 index 40a02c2..0000000 --- a/VARA-HPLaptop.c +++ /dev/null @@ -1,2553 +0,0 @@ -/* -Copyright 2001-2015 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// Interface to allow G8BPQ switch to use VARA Virtual TNC in a form -// of ax.25 - - -#define _CRT_SECURE_NO_DEPRECATE - -#include -#include - - -#include "CHeaders.h" - -#ifdef WIN32 -#include -#endif - -int (WINAPI FAR *GetModuleFileNameExPtr)(); -extern int (WINAPI FAR *EnumProcessesPtr)(); - -#define SD_RECEIVE 0x00 -#define SD_SEND 0x01 -#define SD_BOTH 0x02 - -#include "bpq32.h" - -#include "tncinfo.h" - - -#define WSA_ACCEPT WM_USER + 1 -#define WSA_DATA WM_USER + 2 -#define WSA_CONNECT WM_USER + 3 - -static int Socket_Data(int sock, int error, int eventcode); - -int KillTNC(struct TNCINFO * TNC); -int RestartTNC(struct TNCINFO * TNC); -int KillPopups(struct TNCINFO * TNC); -VOID MoveWindows(struct TNCINFO * TNC); -int SendReporttoWL2K(struct TNCINFO * TNC); -char * CheckAppl(struct TNCINFO * TNC, char * Appl); -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); -BOOL KillOldTNC(char * Path); -int VARASendData(struct TNCINFO * TNC, UCHAR * Buff, int Len); -VOID VARASendCommand(struct TNCINFO * TNC, char * Buff, BOOL Queue); -VOID VARAProcessDataPacket(struct TNCINFO * TNC, UCHAR * Data, int Length); -void CountRestarts(struct TNCINFO * TNC); - -#ifndef LINBPQ -BOOL CALLBACK EnumVARAWindowsProc(HWND hwnd, LPARAM lParam); -#endif - -static char ClassName[]="VARASTATUS"; -static char WindowTitle[] = "VARA"; -static int RigControlRow = 165; - -#define WINMOR -#define NARROWMODE 21 -#define WIDEMODE 22 - -#ifndef LINBPQ -#include -#endif - -extern char * PortConfig[33]; -extern int SemHeldByAPI; - -static RECT Rect; - -extern struct TNCINFO * TNCInfo[41]; // Records are Malloc'd - - -BOOL VARAStopPort(struct PORTCONTROL * PORT) -{ - // Disable Port - close TCP Sockets or Serial Port - - struct TNCINFO * TNC = PORT->TNC; - - TNC->CONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - TNC->Streams[0].Disconnecting = FALSE; - - if (TNC->TCPSock) - { - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPSock); - } - - if (TNC->TCPDataSock) - { - shutdown(TNC->TCPDataSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPDataSock); - } - - TNC->TCPSock = 0; - TNC->TCPDataSock = 0; - - KillTNC(TNC); - - sprintf(PORT->TNC->WEB_COMMSSTATE, "%s", "Port Stopped"); - MySetWindowText(PORT->TNC->xIDC_COMMSSTATE, PORT->TNC->WEB_COMMSSTATE); - - return TRUE; -} - -int ConnecttoVARA(int port); - -BOOL VARAStartPort(struct PORTCONTROL * PORT) -{ - // Restart Port - Open Sockets or Serial Port - - struct TNCINFO * TNC = PORT->TNC; - - ConnecttoVARA(TNC->Port); - TNC->lasttime = time(NULL);; - - sprintf(PORT->TNC->WEB_COMMSSTATE, "%s", "Port Restarted"); - MySetWindowText(PORT->TNC->xIDC_COMMSSTATE, PORT->TNC->WEB_COMMSSTATE); - - return TRUE; -} - - - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC; - char errbuf[256]; - - strcpy(errbuf, buf); - - ptr = strtok(buf, " \t\n\r"); - - if(ptr == NULL) return (TRUE); - - if(*ptr =='#') return (TRUE); // comment - - if(*ptr ==';') return (TRUE); // comment - - if (_stricmp(buf, "ADDR")) - return FALSE; // Must start with ADDR - - ptr = strtok(NULL, " \t\n\r"); - - BPQport = Port; - p_ipad = ptr; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - if (p_ipad == NULL) - p_ipad = strtok(NULL, " \t\n\r"); - - if (p_ipad == NULL) return (FALSE); - - p_port = strtok(NULL, " \t\n\r"); - - if (p_port == NULL) return (FALSE); - - WINMORport = atoi(p_port); - - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(WINMORport); - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(WINMORport+1); - - TNC->HostName = malloc(strlen(p_ipad)+1); - - if (TNC->HostName == NULL) return TRUE; - - strcpy(TNC->HostName,p_ipad); - - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); - - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - } - - if (ptr) - { - if (_memicmp(ptr, "PATH", 4) == 0) - { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - } - - TNC->MaxConReq = 10; // Default - - // Read Initialisation lines - - while (TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - else if (_memicmp(buf, "BW2300", 6) == 0) - { - TNC->ARDOPCurrentMode[0] = 'W'; // Save current state for scanning - strcat(TNC->InitScript, buf); - TNC->DefaultMode = TNC->WL2KMode = 50; - } - else if (_memicmp(buf, "BW500", 5) == 0) - { - TNC->ARDOPCurrentMode[0] = 'N'; - strcat(TNC->InitScript, buf); - TNC->DefaultMode = TNC->WL2KMode = 53; - } - else if (_memicmp(buf, "BW2750", 6) == 0) - { - TNC->ARDOPCurrentMode[0] = 'W'; // Save current state for scanning - strcat(TNC->InitScript, buf); - TNC->DefaultMode = TNC->WL2KMode = 54; - } - else if (_memicmp(buf, "FM1200", 6) == 0) - TNC->DefaultMode = TNC->WL2KMode = 51; - else if (_memicmp(buf, "FM9600", 5) == 0) - TNC->DefaultMode = TNC->WL2KMode = 52; - else if (standardParams(TNC, buf) == FALSE) - strcat(TNC->InitScript, buf); - } - - return (TRUE); -} - -void VARAThread(void * portptr); -int ConnecttoVARA(int port); -VOID VARAProcessReceivedData(struct TNCINFO * TNC); -VOID VARAProcessReceivedControl(struct TNCINFO * TNC); -VOID VARAReleaseTNC(struct TNCINFO * TNC); -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); - - -#define MAXBPQPORTS 32 - -static time_t ltime; - - -static SOCKADDR_IN sinx; -static SOCKADDR_IN rxaddr; - -static int addrlen=sizeof(sinx); - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - size_t datalen; - PMSGWITHLEN buffptr; - char txbuff[500]; - unsigned int bytes,txlen=0; - size_t Param; - HKEY hKey=0; - struct TNCINFO * TNC = TNCInfo[port]; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - struct ScanEntry * Scan; - - if (TNC == NULL) - return 0; // Port not defined - - if (TNC->CONNECTED == 0) - { - // clear Q if not connected - - while(TNC->BPQtoWINMOR_Q) - { - buffptr = Q_REM(&TNC->BPQtoWINMOR_Q); - - if (buffptr) - ReleaseBuffer(buffptr); - } - } - - TNC->Streams[0].Disconnecting = FALSE; - - switch (fn) - { - case 8: - - return 0; - - case 7: - - // approx 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances - - // Check session limit timer - - - if ((STREAM->Connecting || STREAM->Connected) && !STREAM->Disconnecting) - { - if (TNC->SessionTimeLimit && STREAM->ConnectTime && time(NULL) > (TNC->SessionTimeLimit + STREAM->ConnectTime)) - { - VARASendCommand(TNC, "CLEANTXBUFFER\r", TRUE); - VARASendCommand(TNC, "DISCONNECT\r", TRUE); - STREAM->Disconnecting = TRUE; - TNC->SessionTimeLimit += 120; // Don't retrigger unless things have gone horribly wrong - } - } - - while (TNC->PortRecord->UI_Q) - { - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - ReleaseBuffer(buffptr); - } - - if (TNC->Busy) // Count down to clear - { - if ((TNC->BusyFlags & CDBusy) == 0) // TNC Has reported not busy - { - TNC->Busy--; - if (TNC->Busy == 0) - SetWindowText(TNC->xIDC_CHANSTATE, "Clear"); - strcpy(TNC->WEB_CHANSTATE, "Clear"); - } - } - - if (TNC->BusyDelay) - { - // Still Busy? - - if (InterlockedCheckBusy(TNC) == FALSE) - { - // No, so send - - VARASendCommand(TNC, TNC->ConnectCmd, TRUE); - TNC->Streams[0].Connecting = TRUE; - TNC->Streams[0].ConnectTime = time(NULL); - - memset(TNC->Streams[0].RemoteCall, 0, 10); - memcpy(TNC->Streams[0].RemoteCall, &TNC->ConnectCmd[8], strlen(TNC->ConnectCmd)-10); - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - free(TNC->ConnectCmd); - TNC->BusyDelay = 0; - } - else - { - // Wait Longer - - TNC->BusyDelay--; - - if (TNC->BusyDelay == 0) - { - // Timed out - Send Error Response - - PMSGWITHLEN buffptr = GetBuff(); - - TNC->Streams[0].Connecting = FALSE; - TNC->Streams[0].ConnectTime = time(NULL); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = 39; - memcpy(buffptr->Data,"Sorry, Can't Connect - Channel is busy\r", 39); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - free(TNC->ConnectCmd); - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", TNC->Streams[0].MyCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - } - } - } - - return 0; - - case 1: // poll - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - { - // Send the DISCONNECT - - VARASendCommand(TNC, "DISCONNECT\r", TRUE); - } - } - - /* - { - struct tm * tm; - char Time[80]; - - TNC->Restarts++; - TNC->LastRestart = time(NULL); - - tm = gmtime(&TNC->LastRestart); - - sprintf_s(Time, sizeof(Time),"%04d/%02d/%02d %02d:%02dZ", - tm->tm_year +1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); - - MySetWindowText(TNC->xIDC_RESTARTTIME, Time); - strcpy(TNC->WEB_RESTARTTIME, Time); - - sprintf_s(Time, sizeof(Time),"%d", TNC->Restarts); - MySetWindowText(TNC->xIDC_RESTARTS, Time); - strcpy(TNC->WEB_RESTARTS, Time); -*/ - - if (TNC->PortRecord->ATTACHEDSESSIONS[0] && TNC->Streams[0].Attached == 0) - { - // New Attach - - int calllen; - char Msg[80]; - - TNC->Streams[0].Attached = TRUE; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4USER, TNC->Streams[0].MyCall); - TNC->Streams[0].MyCall[calllen] = 0; - - // Stop Listening, and set MYCALL to user's call - - VARASendCommand(TNC, "LISTEN OFF\r", TRUE); - - TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", TNC->Streams[0].MyCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Stop Scanning - - sprintf(Msg, "%d SCANSTOP", TNC->Port); - - Rig_Command(-1, Msg); - } - - if (TNC->Streams[0].Attached) - CheckForDetach(TNC, 0, &TNC->Streams[0], TidyClose, ForcedClose, CloseComplete); - - if (TNC->Streams[0].ReportDISC) - { - TNC->Streams[0].ReportDISC = FALSE; - buff->PORT = 0; - return -1; - } - - if (TNC->CONNECTED == FALSE && TNC->CONNECTING == FALSE) - { - // See if time to reconnect - - time(<ime); - if (ltime - TNC->lasttime > 9 ) - { - TNC->lasttime = ltime; - ConnecttoVARA(port); - } - } - - // See if any frames for this port - - if (TNC->Streams[0].BPQtoPACTOR_Q) //Used for CTEXT - { - PMSGWITHLEN buffptr = Q_REM(&TNC->Streams[0].BPQtoPACTOR_Q); - txlen = (int)buffptr->Len; - memcpy(txbuff, buffptr->Data, txlen); - bytes = VARASendData(TNC, &txbuff[0], txlen); - STREAM->BytesTXed += bytes; - ReleaseBuffer(buffptr); - } - - - if (TNC->WINMORtoBPQ_Q != 0) - { - buffptr=Q_REM(&TNC->WINMORtoBPQ_Q); - - datalen = buffptr->Len; - - buff->PORT = 0; // Compatibility with Kam Driver - buff->PID = 0xf0; - memcpy(&buff->L2DATA[0], buffptr->Data, datalen); - - datalen += sizeof(void *) + 4; - PutLengthinBuffer(buff, (int)datalen); - - ReleaseBuffer(buffptr); - - return (1); - } - - return (0); - - case 2: // send - - if (!TNC->CONNECTED) - { - // Send Error Response - - PMSGWITHLEN buffptr = GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len=36; - memcpy(buffptr->Data,"No Connection to VARA TNC\r", 36); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - return 0; // Don't try if not connected - } - - if (TNC->Streams[0].BPQtoPACTOR_Q) //Used for CTEXT - { - PMSGWITHLEN buffptr = Q_REM(&TNC->Streams[0].BPQtoPACTOR_Q); - txlen = (int)buffptr->Len; - memcpy(txbuff, buffptr->Data, txlen); - bytes=send(TNC->TCPDataSock, buff->L2DATA, txlen, 0); - STREAM->BytesTXed += bytes; - WritetoTrace(TNC, txbuff, txlen); - ReleaseBuffer(buffptr); - } - - if (TNC->SwallowSignon) - { - TNC->SwallowSignon = FALSE; // Discard *** connected - return 0; - } - - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - - if (TNC->Streams[0].Connected) - { - STREAM->PacketsSent++; - - bytes=send(TNC->TCPDataSock, buff->L2DATA, txlen, 0); - STREAM->BytesTXed += bytes; - WritetoTrace(TNC, buff->L2DATA, txlen); - } - else - { - if (_memicmp(buff->L2DATA, "D\r", 2) == 0 || _memicmp(buff->L2DATA, "BYE\r", 4) == 0) - { - TNC->Streams[0].ReportDISC = TRUE; // Tell Node - return 0; - } - - // See if Local command (eg RADIO) - - if (_memicmp(buff->L2DATA, "RADIO ", 6) == 0) - { - sprintf(buff->L2DATA, "%d %s", TNC->Port, &buff->L2DATA[6]); - - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK->CIRCUITINDEX, buff->L2DATA)) - { - } - else - { - PMSGWITHLEN buffptr = GetBuff(); - - if (buffptr == 0) return 1; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "%s", buff->L2DATA); - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - } - return 1; - } - - if (_memicmp(buff->L2DATA, "OVERRIDEBUSY", 12) == 0) - { - PMSGWITHLEN buffptr = GetBuff(); - - TNC->OverrideBusy = TRUE; - - if (buffptr) - { - buffptr->Len = sprintf(buffptr->Data, "VARA} OK\r"); - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - } - - return 0; - - } - - if (_memicmp(&buff->L2DATA[0], "SessionTimeLimit", 16) == 0) - { - if (buff->L2DATA[16] != 13) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - TNC->SessionTimeLimit = atoi(&buff->L2DATA[16]) * 60; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "VARA} OK\r"); - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - } - return 0; - } - } - - - if (_memicmp(&buff->L2DATA[0], "CODEC TRUE", 9) == 0) - TNC->StartSent = TRUE; - - if (_memicmp(&buff->L2DATA[0], "BW2300", 6) == 0) - { - TNC->ARDOPCurrentMode[0] = 'W'; // Save current state for scanning - TNC->WL2KMode = 50; - } - - if (_memicmp(&buff->L2DATA[0], "BW500", 5) == 0) - { - TNC->ARDOPCurrentMode[0] = 'N'; - TNC->WL2KMode = 53; - } - - if (_memicmp(&buff->L2DATA[0], "D\r", 2) == 0) - { - TNC->Streams[0].ReportDISC = TRUE; // Tell Node - return 0; - } - - // See if a Connect Command. If so set Connecting - - if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect - { - char Connect[80]; - char * ptr = strchr(&buff->L2DATA[2], 13); - - if (ptr) - *ptr = 0; - - _strupr(&buff->L2DATA[2]); - - sprintf(Connect, "CONNECT %s %s\r", TNC->Streams[0].MyCall, &buff->L2DATA[2]); - - // Need to set connecting here as if we delay for busy we may incorrectly process OK response - - TNC->Streams[0].Connecting = TRUE; - - // See if Busy - - if (InterlockedCheckBusy(TNC)) - { - // Channel Busy. Unless override set, wait - - if (TNC->OverrideBusy == 0) - { - // Save Command, and wait up to 10 secs - - sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - TNC->ConnectCmd = _strdup(Connect); - TNC->BusyDelay = TNC->BusyWait * 10; // BusyWait secs - return 0; - } - } - - TNC->OverrideBusy = FALSE; - - VARASendCommand(TNC, Connect, TRUE); - TNC->Streams[0].ConnectTime = time(NULL); - - - memset(TNC->Streams[0].RemoteCall, 0, 10); - strcpy(TNC->Streams[0].RemoteCall, &buff->L2DATA[2]); - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - } - else - { - buff->L2DATA[(txlen++) - 1] = 13; - buff->L2DATA[(txlen) - 1] = 0; - VARASendCommand(TNC, &buff->L2DATA[0], TRUE); - } - } - return (0); - - case 3: - - // CHECK IF OK TO SEND (And check TNC Status) - - if (TNC->Streams[0].Attached == 0) - return TNC->CONNECTED << 8 | 1; - - return (TNC->CONNECTED << 8 | TNC->Streams[0].Disconnecting << 15); // OK - - - case 4: // reinit - - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPSock); - - if (TNC->PID && TNC->WeStartedTNC) - { - KillTNC(TNC); - RestartTNC(TNC); - } - return 0; - - case 5: // Close - - if (TNC->CONNECTED) - { -// GetSemaphore(&Semaphore, 52); -// VARASendCommand(TNC, "CLOSE", FALSE); -// FreeSemaphore(&Semaphore); -// Sleep(100); - } - - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPSock); - if (TNC->WeStartedTNC) - KillTNC(TNC); - - return 0; - - - case 6: // Scan Stop Interface - - Param = (size_t)buff; - - if (Param == 2) // Check Permission (shouldn't happen) - { - Debugprintf("Scan Check Permission called on VARA"); - return 1; // OK to change - } - - if (!TNC->CONNECTED) - return 0; // No connection so no interlock - - if (Param == 1) // Request Permission - { - if (TNC->ConnectPending == 0 && TNC->PTTState == 0) - { - VARASendCommand(TNC, "LISTEN OFF\r", TRUE); - TNC->GavePermission = TRUE; - return 0; // OK to Change - } - - if (TNC->ConnectPending) - TNC->ConnectPending--; // Time out if set too long - - if (!TNC->ConnectPending) - return 0; // OK to Change - - return TRUE; - } - - if (Param == 3) // Release Permission - { - if (TNC->GavePermission) - { - TNC->GavePermission = FALSE; - if (TNC->ARDOPCurrentMode[0] != 'S') // Skip - VARASendCommand(TNC, "LISTEN ON\r", TRUE); - } - return 0; - } - - // Param is Address of a struct ScanEntry - - Scan = (struct ScanEntry *)buff; - - if (Scan->VARAMode != TNC->ARDOPCurrentMode[0]) - { - // Mode changed - - if (TNC->ARDOPCurrentMode[0] == 'S') - { - VARASendCommand(TNC, "LISTEN ON\r", TRUE); - } - - if (Scan->VARAMode == 'W') // Set Wide Mode - { - VARASendCommand(TNC, "BW2300\r", TRUE); - TNC->WL2KMode = 50; - } - if (Scan->VARAMode == 'T') // Set Wide Mode - { - VARASendCommand(TNC, "BW2750\r", TRUE); - TNC->WL2KMode = 54; - } - else if (Scan->VARAMode == 'N') // Set Narrow Mode - { - VARASendCommand(TNC, "BW500\r", TRUE); - TNC->WL2KMode = 53; - } - else if (Scan->VARAMode == 'S') // Skip - { - VARASendCommand(TNC, "LISTEN OFF\r", TRUE); - } - - TNC->ARDOPCurrentMode[0] = Scan->VARAMode; - } - return 0; - } - return 0; -} - -void CountRestarts(struct TNCINFO * TNC) -{ - struct tm * tm; - char Time[80]; - - TNC->Restarts++; - TNC->LastRestart = time(NULL); - - tm = gmtime(&TNC->LastRestart); - - sprintf_s(Time, sizeof(Time),"%04d/%02d/%02d %02d:%02dZ", - tm->tm_year +1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); - - //MySetWindowText(TNC->xIDC_RESTARTTIME, Time); - //strcpy(TNC->WEB_RESTARTTIME, Time); - - sprintf_s(Time, sizeof(Time),"%d", TNC->Restarts); - MySetWindowText(TNC->xIDC_RESTARTS, Time); - strcpy(TNC->WEB_RESTARTS, Time); -} -/* -char WebProcTemplate[] = "" - "\r\n" - "" - "%s" - "" - "%s" - ""; -*/ -char WebProcTemplate[] = "" - "\r\n" - "\r\n" - "%s\r\n" - "

%s

"; - -char Menubit[] = "" - "\r\n" - "" - "Abort Session" - "Kill TNC" - "Kill and Restart TNC" - ""; - -char sliderBit[] = " TX Offset %d" - "\r\n" - "\r\n"; - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, WebProcTemplate, TNC->Port, TNC->Port, "VARA Status", "VARA Status"); - - if (LOCAL) - Len += sprintf(&Buff[Len], Menubit, TNC->TXOffset, TNC->TXOffset); - - if (TNC->TXFreq) - Len += sprintf(&Buff[Len], sliderBit, TNC->TXOffset, TNC->TXOffset); - - Len += sprintf(&Buff[Len], ""); - - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); -// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
S/N%s
Traffic%s
TNC Restarts
"); - - Len += sprintf(&Buff[Len], "", TNC->WebBuffer); - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - -VOID VARASuspendPort(struct TNCINFO * TNC) -{ - VARASendCommand(TNC, "LISTEN OFF\r", TRUE); -} - -VOID VARAReleasePort(struct TNCINFO * TNC) -{ - VARASendCommand(TNC, "LISTEN ON\r", TRUE); -} - - -void * VARAExtInit(EXTPORTDATA * PortEntry) -{ - int i, port; - char Msg[255]; - char * ptr; - APPLCALLS * APPL; - struct TNCINFO * TNC; - int AuxCount = 0; - char Appl[11]; - char * TempScript; - int line; - struct PORTCONTROL * PORT = &PortEntry->PORTCONTROL; - // - // Will be called once for each VARA port - // - // The Socket to connect to is in IOBASE - // - - port = PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC->AutoStartDelay == 0) - TNC->AutoStartDelay = 2000; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); - WritetoConsole(Msg); - - return ExtProc; - } - - TNC->Port = port; - - TNC->ARDOPBuffer = malloc(8192); - TNC->ARDOPDataBuffer = malloc(8192); - - if (TNC->ProgramPath) - TNC->WeStartedTNC = 1; - - TNC->Hardware = H_VARA; - - if (TNC->BusyWait == 0) - TNC->BusyWait = 10; - - if (TNC->BusyHold == 0) - TNC->BusyHold = 1; - - TNC->PortRecord = PortEntry; - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - memcpy(TNC->NodeCall, MYNODECALL, 10); - else - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) - TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - PortEntry->MAXHOSTMODESESSIONS = 1; - PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only - - PortEntry->PORTCONTROL.UICAPABLE = FALSE; - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 236; - - TNC->SuspendPortProc = VARASuspendPort; - TNC->ReleasePortProc = VARAReleasePort; - - PortEntry->PORTCONTROL.PORTSTARTCODE = VARAStartPort; - PortEntry->PORTCONTROL.PORTSTOPCODE = VARAStopPort; - - TNC->ModemCentre = 1500; // WINMOR is always 1500 Offset - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - // Set Essential Params and MYCALL - - // Put overridable ones on front, essential ones on end - - TempScript = zalloc(1000); - -// strcat(TempScript, "ROBUST False\r"); - - // Set MYCALL(S) - - if (TNC->LISTENCALLS) - { - sprintf(Msg, "MYCALL %s", TNC->LISTENCALLS); - } - else - { - sprintf(Msg, "MYCALL %s", TNC->NodeCall); - - for (i = 0; i < 32; i++) - { - APPL=&APPLCALLTABLE[i]; - - if (APPL->APPLCALL_TEXT[0] > ' ') - { - char * ptr; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - { - // *ptr++ = ' '; - *ptr = 0; - } - strcat(Msg, " "); - strcat(Msg, Appl); - AuxCount++; - if (AuxCount == 4) // Max 5 in MYCALL - break; - } - } - } - - strcat(Msg, "\r"); - - strcat(TempScript, Msg); - - strcat(TempScript, TNC->InitScript); - - free(TNC->InitScript); - TNC->InitScript = TempScript; - - - strcat(TNC->InitScript,"LISTEN ON\r"); - - strcpy(TNC->CurrentMYC, TNC->NodeCall); - - if (TNC->WL2K == NULL) - if (PortEntry->PORTCONTROL.WL2KInfo.RMSCall[0]) // Alrerady decoded - TNC->WL2K = &PortEntry->PORTCONTROL.WL2KInfo; - - // if mode hasn't been set explicitly or via WL2KREPORT set to HF Wide mode (BW2300) - - if (TNC->DefaultMode == 0) - { - if (TNC->WL2K && TNC->WL2K->mode >= 50 && TNC->WL2K->mode <= 53) // A VARA Mode - TNC->DefaultMode = TNC->WL2KMode = TNC->WL2K->mode; - else - TNC->DefaultMode = TNC->WL2KMode = 50; // Default to 2300 - } - - if (TNC->destaddr.sin_family == 0) - { - // not defined in config file, so use localhost and port from IOBASE - - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(PortEntry->PORTCONTROL.IOBASE); - TNC->Datadestaddr.sin_family = AF_INET; - TNC->Datadestaddr.sin_port = htons(PortEntry->PORTCONTROL.IOBASE+1); - - TNC->HostName=malloc(10); - - if (TNC->HostName != NULL) - strcpy(TNC->HostName,"127.0.0.1"); - - } - - PortEntry->PORTCONTROL.TNC = TNC; - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 520; - TNC->WebWinY = 500; - TNC->WebBuffer = zalloc(5000); - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - TNC->WEB_CHANSTATE = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_PROTOSTATE = zalloc(100); - TNC->WEB_RESTARTTIME = zalloc(100); - TNC->WEB_RESTARTS = zalloc(100); - - TNC->WEB_MODE = zalloc(20); - TNC->WEB_TRAFFIC = zalloc(100); - - -#ifndef LINBPQ - - line = 6; - - if (TNC->TXFreq) - { - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow + 22, PacWndProc, 550, 450, ForcedClose); - - InitCommonControls(); // loads common control's DLL - - CreateWindowEx(0, "STATIC", "TX Tune", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNE = CreateWindowEx(0, TRACKBAR_CLASS, "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXTUNEVAL = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE, 320,line,30,20, TNC->hDlg, NULL, hInstance, NULL); - - SendMessage(TNC->xIDC_TXTUNE, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG(-200, 200)); // min. & max. positions - - line += 22; - } - else - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 450, ForcedClose); - - CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,line,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,386,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,line,106,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,520,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,line,110,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,line,144,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "S/N", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_PROTOSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,line,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,line,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,line,116,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,line,20,20 , TNC->hDlg, NULL, hInstance, NULL); - CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,line,100,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,line,200,20, TNC->hDlg, NULL, hInstance, NULL); - - line += 22; - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, - 0,line,250,300, TNC->hDlg, NULL, hInstance, NULL); - - TNC->ClientHeight = 450; - TNC->ClientWidth = 500; - - TNC->hMenu = CreatePopupMenu(); - - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill VARA TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart VARA TNC"); - AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after failed Connection"); - CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); - AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); - - MoveWindows(TNC); -#endif - Consoleprintf("VARA Host %s %d", TNC->HostName, htons(TNC->destaddr.sin_port)); - - ConnecttoVARA(port); - - time(&TNC->lasttime); // Get initial time value - - return ExtProc; -} - -int ConnecttoVARA(int port) -{ - if (TNCInfo[port]->CONNECTING || TNCInfo[port]->PortRecord->PORTCONTROL.PortStopped) - return 0; - - _beginthread(VARAThread, 0, (void *)(size_t)port); - - return 0; -} - -VOID VARAThread(void * portptr) -{ - // Opens sockets and looks for data on control and data sockets. - - int port = (int)(size_t)portptr; - char Msg[255]; - int err, i, ret; - u_long param=1; - BOOL bcopt=TRUE; - struct hostent * HostEnt; - struct TNCINFO * TNC = TNCInfo[port]; - fd_set readfs; - fd_set errorfs; - struct timeval timeout; - char * ptr1; - char * ptr2; - PMSGWITHLEN buffptr; - - if (TNC->HostName == NULL) - return; - - TNC->BusyFlags = 0; - - TNC->CONNECTING = TRUE; - - Sleep(3000); // Allow init to complete - - if (TNCInfo[port]->PortRecord->PORTCONTROL.PortStopped) - { - TNC->CONNECTING = FALSE; - return; - } - - -// printf("Starting VARA Thread\n"); - -// if on Windows and Localhost see if TNC is running - -#ifdef WIN32 - - if (strcmp(TNC->HostName, "127.0.0.1") == 0) - { - // can only check if running on local host - - TNC->PID = GetListeningPortsPID(TNC->destaddr.sin_port); - - if (TNC->PID == 0) - goto TNCNotRunning; - - // Get the File Name in case we want to restart it. - - if (TNC->ProgramPath == NULL) - { - if (GetModuleFileNameExPtr) - { - HANDLE hProc; - char ExeName[256] = ""; - - hProc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, TNC->PID); - - if (hProc) - { - GetModuleFileNameExPtr(hProc, 0, ExeName, 255); - CloseHandle(hProc); - - TNC->ProgramPath = _strdup(ExeName); - } - } - } - goto TNCRunning; - } - -#endif - -TNCNotRunning: - - // Not running or can't check, restart if we have a path - - if (TNC->ProgramPath) - { - Consoleprintf("Trying to (re)start TNC %s", TNC->ProgramPath); - - if (RestartTNC(TNC)) - CountRestarts(TNC); - - Sleep(TNC->AutoStartDelay); - } - -TNCRunning: - - if (TNC->Alerted == FALSE) - { - sprintf(TNC->WEB_COMMSSTATE, "Connecting to TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - - TNC->destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - TNC->Datadestaddr.sin_addr.s_addr = inet_addr(TNC->HostName); - - if (TNC->destaddr.sin_addr.s_addr == INADDR_NONE) - { - // Resolve name to address - - HostEnt = gethostbyname (TNC->HostName); - - if (!HostEnt) - { - TNC->CONNECTING = FALSE; - sprintf(Msg, "Resolve Failed for VARA socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - return; // Resolve failed - } - memcpy(&TNC->destaddr.sin_addr.s_addr,HostEnt->h_addr,4); - memcpy(&TNC->Datadestaddr.sin_addr.s_addr,HostEnt->h_addr,4); - } - -// closesocket(TNC->TCPSock); -// closesocket(TNC->TCPDataSock); - - TNC->TCPSock=socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for VARA socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->CONNECTING = FALSE; - return; - } - - TNC->TCPDataSock = socket(AF_INET,SOCK_STREAM,0); - - if (TNC->TCPDataSock == INVALID_SOCKET) - { - i=sprintf(Msg, "Socket Failed for VARA Data socket - error code = %d\r\n", WSAGetLastError()); - WritetoConsole(Msg); - - TNC->CONNECTING = FALSE; - closesocket(TNC->TCPSock); - - return; - } - - setsockopt(TNC->TCPSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); - setsockopt(TNC->TCPDataSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); -// setsockopt(TNC->TCPDataSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4); - - sinx.sin_family = AF_INET; - sinx.sin_addr.s_addr = INADDR_ANY; - sinx.sin_port = 0; - -// printf("Trying to connect to VARA TNC\n"); - - if (connect(TNC->TCPSock,(LPSOCKADDR) &TNC->destaddr,sizeof(TNC->destaddr)) == 0) - { - // Connected successful - - goto VConnected; - - } - - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - sprintf(Msg, "Connect Failed for VARA socket - error code = %d Port %d\n", - err, htons(TNC->destaddr.sin_port)); - - WritetoConsole(Msg); - TNC->Alerted = TRUE; - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - } - -// printf("VARA Connect failed\n"); - - closesocket(TNC->TCPSock); - closesocket(TNC->TCPDataSock); - - TNC->TCPSock = 0; - TNC->CONNECTING = FALSE; - return; - -VConnected: - - // Connect Data Port - - if (connect(TNC->TCPDataSock,(LPSOCKADDR) &TNC->Datadestaddr,sizeof(TNC->Datadestaddr)) == 0) - { - // - // Connected successful - // - } - else - { - if (TNC->Alerted == FALSE) - { - err=WSAGetLastError(); - i=sprintf(Msg, "Connect Failed for VARA Data socket - error code = %d\r\n", err); - WritetoConsole(Msg); - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - TNC->Alerted = TRUE; - } - - closesocket(TNC->TCPSock); - closesocket(TNC->TCPDataSock); - TNC->TCPSock = 0; - TNC->CONNECTING = FALSE; - - RestartTNC(TNC); - return; - } - - Sleep(1000); - - TNC->LastFreq = 0; - - TNC->CONNECTING = FALSE; - TNC->CONNECTED = TRUE; - TNC->BusyFlags = 0; - TNC->InputLen = 0; - - // Send INIT script - - // VARA needs each command in a separate send - - ptr1 = &TNC->InitScript[0]; - - // We should wait for first RDY. Cheat by queueing a null command - - GetSemaphore(&Semaphore, 52); - - while(TNC->BPQtoWINMOR_Q) - { - buffptr = Q_REM(&TNC->BPQtoWINMOR_Q); - - if (buffptr) - ReleaseBuffer(buffptr); - } - - - while (ptr1 && ptr1[0]) - { - unsigned char c; - - ptr2 = strchr(ptr1, 13); - - if (ptr2) - { - c = *(ptr2 + 1); // Save next char - *(ptr2 + 1) = 0; // Terminate string - } - VARASendCommand(TNC, ptr1, TRUE); - - if (ptr2) - *(1 + ptr2++) = c; // Put char back - - ptr1 = ptr2; - } - - TNC->Alerted = TRUE; - - sprintf(TNC->WEB_COMMSSTATE, "Connected to VARA TNC"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - FreeSemaphore(&Semaphore); - - sprintf(Msg, "Connected to VARA TNC Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - - #ifndef LINBPQ -// FreeSemaphore(&Semaphore); - Sleep(1000); // Give VARA time to update Window title - EnumWindows(EnumVARAWindowsProc, (LPARAM)TNC); -// GetSemaphore(&Semaphore, 52); -#endif - - while (TNC->CONNECTED) - { - FD_ZERO(&readfs); - FD_ZERO(&errorfs); - - FD_SET(TNC->TCPSock,&readfs); - FD_SET(TNC->TCPSock,&errorfs); - - if (TNC->CONNECTED) FD_SET(TNC->TCPDataSock,&readfs); - -// FD_ZERO(&writefs); - -// if (TNC->BPQtoWINMOR_Q) FD_SET(TNC->TCPDataSock,&writefs); // Need notification of busy clearing - - if (TNC->CONNECTING || TNC->CONNECTED) FD_SET(TNC->TCPDataSock,&errorfs); - - timeout.tv_sec = 90; - timeout.tv_usec = 0; // We should get messages more frequently that this - - ret = select((int)TNC->TCPDataSock + 1, &readfs, NULL, &errorfs, &timeout); - - if (ret == SOCKET_ERROR) - { - Debugprintf("VARA Select failed %d ", WSAGetLastError()); - goto Lost; - } - if (ret > 0) - { - // See what happened - - if (FD_ISSET(TNC->TCPSock, &readfs)) - { - GetSemaphore(&Semaphore, 52); - VARAProcessReceivedControl(TNC); - FreeSemaphore(&Semaphore); - } - - if (FD_ISSET(TNC->TCPDataSock, &readfs)) - { - GetSemaphore(&Semaphore, 52); - VARAProcessReceivedData(TNC); - FreeSemaphore(&Semaphore); - } - - if (FD_ISSET(TNC->TCPSock, &errorfs)) - { -Lost: - sprintf(Msg, "VARA Connection lost for Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->CONNECTED = FALSE; - TNC->Alerted = FALSE; - TNC->ConnectPending = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - closesocket(TNC->TCPSock); - closesocket(TNC->TCPDataSock); - TNC->TCPSock = 0; - break; - } - - if (FD_ISSET(TNC->TCPDataSock, &errorfs)) - { - sprintf(Msg, "VARA Connection lost for Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->CONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - closesocket(TNC->TCPSock); - closesocket(TNC->TCPDataSock); - TNC->TCPSock = 0; - break; - } - continue; - } - else - { - // 60 secs without data. Shouldn't happen - - continue; - - sprintf(Msg, "VARA No Data Timeout Port %d\r\n", TNC->Port); - WritetoConsole(Msg); - -// sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); -// GetSemaphore(&Semaphore, 52); -// MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); -// FreeSemaphore(&Semaphore); - - - TNC->CONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - -// GetSemaphore(&Semaphore, 52); -// VARASendCommand(TNC, "CODEC FALSE", FALSE); -// FreeSemaphore(&Semaphore); - - Sleep(100); - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - - closesocket(TNC->TCPSock); - - Sleep(100); - shutdown(TNC->TCPDataSock, SD_BOTH); - Sleep(100); - - closesocket(TNC->TCPDataSock); - -// if (TNC->PID && TNC->WeStartedTNC) -// { -// KillTNC(TNC); -// - break; - } - } - - if (TNC->TCPSock) - { - shutdown(TNC->TCPSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPSock); - } - - if (TNC->TCPDataSock) - { - shutdown(TNC->TCPDataSock, SD_BOTH); - Sleep(100); - closesocket(TNC->TCPDataSock); - } - - sprintf(Msg, "VARA Thread Terminated Port %d\r\n", TNC->Port); - WritetoConsole(Msg); -} - - -VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen) -{ - PMSGWITHLEN buffptr; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - Buffer[MsgLen - 1] = 0; // Remove CR - - TNC->TimeSinceLast = 0; - - if (_memicmp(Buffer, "PTT ON", 6) == 0) - { -// Debugprintf("PTT On"); - - TNC->Busy = TNC->BusyHold * 10; // BusyHold delay - - if (TNC->PTTMode) - Rig_PTT(TNC, TRUE); - - return; - } - - if (_memicmp(Buffer, "PTT OFF", 6) == 0) - { -// Debugprintf("PTT Off"); - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); - - return; - } - - if (_memicmp(Buffer, "SN ", 3) == 0) - { - strcpy(TNC->WEB_PROTOSTATE, &Buffer[3]); - MySetWindowText(TNC->xIDC_PROTOSTATE, TNC->WEB_PROTOSTATE); - - TNC->SNR = atof(&Buffer[3]); - return; - } - - if (_stricmp(Buffer, "BUSY ON") == 0) - { - TNC->BusyFlags |= CDBusy; - TNC->Busy = TNC->BusyHold * 10; // BusyHold delay - - MySetWindowText(TNC->xIDC_CHANSTATE, "Busy"); - strcpy(TNC->WEB_CHANSTATE, "Busy"); - - TNC->WinmorRestartCodecTimer = time(NULL); - return; - } - - if (_stricmp(Buffer, "BUSY OFF") == 0) - { - TNC->BusyFlags &= ~CDBusy; - if (TNC->BusyHold) - strcpy(TNC->WEB_CHANSTATE, "BusyHold"); - else - strcpy(TNC->WEB_CHANSTATE, "Clear"); - - MySetWindowText(TNC->xIDC_CHANSTATE, TNC->WEB_CHANSTATE); - TNC->WinmorRestartCodecTimer = time(NULL); - return; - } - - - if (_memicmp(&Buffer[0], "PENDING", 7) == 0) // Save Pending state for scan control - { - TNC->ConnectPending = 6; // Time out after 6 Scanintervals - Debugprintf(Buffer); -// WritetoTrace(TNC, Buffer, MsgLen - 1); - return; - } - - if (_memicmp(&Buffer[0], "CANCELPENDING", 13) == 0) - { - TNC->ConnectPending = FALSE; - Debugprintf(Buffer); - - // If a callsign is present it is the calling station - add to MH - - if (TNC->SeenCancelPending == 0) - { - WritetoTrace(TNC, Buffer, MsgLen - 1); - TNC->SeenCancelPending = 1; - } - - if (Buffer[13] == ' ') - UpdateMH(TNC, &Buffer[14], '!', 'I'); - - return; - } - - TNC->SeenCancelPending = 0; - - if (strcmp(Buffer, "OK") == 0) - { - // Need to discard response to LISTEN OFF after attach - - if (TNC->DiscardNextOK) - { - TNC->DiscardNextOK = 0; - return; - } - - if (TNC->Streams[0].Connecting == TRUE) - return; // Discard response or it will mess up connect scripts - } - - if (_memicmp(Buffer, "BUFFER", 6) == 0) - { - Debugprintf(Buffer); - - sscanf(&Buffer[7], "%d", &TNC->Streams[0].BytesOutstanding); - - if (TNC->Streams[0].BytesOutstanding == 0) - { - // all sent - - if (TNC->Streams[0].Disconnecting) // Disconnect when all sent - { - if (STREAM->NeedDisc == 0) - STREAM->NeedDisc = 60; // 6 secs - } - } - else - { - // Make sure Node Keepalive doesn't kill session. - - TRANSPORTENTRY * SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - if (SESS) - { - SESS->L4KILLTIMER = 0; - SESS = SESS->L4CROSSLINK; - if (SESS) - SESS->L4KILLTIMER = 0; - } - } - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %s", - STREAM->BytesTXed, STREAM->BytesRXed, &Buffer[7]); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - return; - } - - if (_memicmp(Buffer, "CONNECTED ", 10) == 0) - { - char Call[11]; - char * ptr; - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - struct WL2KInfo * WL2K = TNC->WL2K; - int Speed = 0; - - Debugprintf(Buffer); - WritetoTrace(TNC, Buffer, MsgLen - 1); - - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0; - - strcpy(TNC->WEB_MODE, ""); - - if (strstr(Buffer, "2300")) - { - Speed = 50; - strcpy(TNC->WEB_MODE, "2300"); - } - else if (strstr(Buffer, "NARROW")) - { - Speed = 51; - strcpy(TNC->WEB_MODE, "NARROW"); - } - else if (strstr(Buffer, "WIDE")) - { - Speed = 52; - strcpy(TNC->WEB_MODE, "WIDE"); - } - else if (strstr(Buffer, "500")) - { - Speed = 53; - strcpy(TNC->WEB_MODE, "500"); - } - else if (strstr(Buffer, "2750")) - { - Speed = 54; - strcpy(TNC->WEB_MODE, "2750"); - } - - MySetWindowText(TNC->xIDC_MODE, TNC->WEB_MODE); - memcpy(Call, &Buffer[10], 10); - - ptr = strchr(Call, ' '); - if (ptr) *ptr = 0; - - // Get Target Call - - ptr = strchr(&Buffer[10], ' '); - - if (ptr) - { - memcpy(TNC->TargetCall, ++ptr, 10); - strlop(TNC->TargetCall, ' '); - } - - TNC->HadConnect = TRUE; - - if (TNC->PortRecord->ATTACHEDSESSIONS[0] == 0) - { - TRANSPORTENTRY * SESS; - - // Incoming Connect - - // Stop other ports in same group - - SuspendOtherPorts(TNC); - - TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit - - ProcessIncommingConnectEx(TNC, Call, 0, TRUE, TRUE); - - SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; - - if (Speed) - SESS->Mode = Speed; - else - SESS->Mode = TNC->WL2KMode; - - TNC->ConnectPending = FALSE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", TNC->Streams[0].RemoteCall, TNC->TargetCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - if (SESS->Frequency == 1500) - { - // try to get from WL2K record - - if (WL2K) - SESS->Frequency = WL2K->Freq; - } - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", TNC->Streams[0].RemoteCall, TNC->TargetCall); - if (WL2K) - SESS->Frequency = WL2K->Freq; - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Check for ExcludeList - - if (ExcludeList[0]) - { - if (CheckExcludeList(SESS->L4USER) == FALSE) - { - char Status[64]; - - TidyClose(TNC, 0); - sprintf(Status, "%d SCANSTART 15", TNC->Port); - Rig_Command(-1, Status); - Debugprintf("VARA Call from %s rejected", Call); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(SESS->L4USER, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - char Status[64]; - - TidyClose(TNC, 0); - sprintf(Status, "%d SCANSTART 15", TNC->Port); - Rig_Command(-1, Status); - Debugprintf("VARA Call from %s not in ValidCalls - rejected", Call); - return; - } - } - } - - - // See which application the connect is for - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(TNC->TargetCall, Appl) == 0) - break; - } - - if (App < 32) - { - char AppName[13]; - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(Call, "-T" ) || strstr(Call, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - if (CheckAppl(TNC, AppName)) - { - MsgLen = sprintf(Buffer, "%s\r", AppName); - - buffptr = GetBuff(); - - if (buffptr == 0) - { - return; // No buffers, so ignore - } - - buffptr->Len = MsgLen; - memcpy(buffptr->Data, Buffer, MsgLen); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - TNC->SwallowSignon = TRUE; - - // Save Appl Call in case needed for - - } - else - { - char Msg[] = "Application not available\r"; - - // Send a Message, then a disconenct - - // Send CTEXT First - - - if (TNC->Streams[0].BPQtoPACTOR_Q) //Used for CTEXT - { - PMSGWITHLEN buffptr = Q_REM(&TNC->Streams[0].BPQtoPACTOR_Q); - int txlen = (int)buffptr->Len; - VARASendData(TNC, buffptr->Data, txlen); - ReleaseBuffer(buffptr); - } - - VARASendData(TNC, Msg, (int)strlen(Msg)); - STREAM->NeedDisc = 100; // 10 secs - } - } - return; - } - else - { - // Connect Complete - - char Reply[80]; - int ReplyLen; - - buffptr = GetBuff(); - - if (buffptr == 0) - { - return; // No buffers, so ignore - } - ReplyLen = sprintf(Reply, "*** Connected to %s\r", TNC->TargetCall); - - buffptr->Len = ReplyLen; - memcpy(buffptr->Data, Reply, ReplyLen); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - TNC->Streams[0].Connecting = FALSE; - TNC->Streams[0].Connected = TRUE; // Subsequent data to data channel - - if (TNC->RIG && TNC->RIG->Valchar[0]) - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound Freq %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall, TNC->RIG->Valchar); - else - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - UpdateMH(TNC, TNC->TargetCall, '+', 'O'); - return; - } - } - - - if (_memicmp(Buffer, "DISCONNECTED", 12) == 0) - { - Debugprintf(Buffer); - - TNC->ConnectPending = FALSE; // Cancel Scan Lock - - if (TNC->StartSent) - { - TNC->StartSent = FALSE; // Disconnect reported following start codec - return; - } - - if (TNC->Streams[0].Connecting) - { - // Report Connect Failed, and drop back to command mode - - TNC->Streams[0].Connecting = FALSE; - - buffptr = GetBuff(); - - if (buffptr == 0) - { - return; // No buffers, so ignore - } - - buffptr->Len = sprintf(buffptr->Data, "VARA} Failure with %s\r", STREAM->RemoteCall); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", TNC->Streams[0].MyCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - if (TNC->RestartAfterFailure) - { - if (TNC->ProgramPath) - KillTNC(TNC); - } - - return; - } - - WritetoTrace(TNC, Buffer, MsgLen - 1); - - // Release Session - - if (STREAM->Connected && STREAM->ConnectTime) - { - // Create a traffic record - - char logmsg[120]; - time_t Duration; - - Duration = time(NULL) - STREAM->ConnectTime; - - if (Duration == 0) - Duration = 1; - - sprintf(logmsg,"Port %2d %9s Bytes Sent %d BPS %d Bytes Received %d BPS %d Time %d Seconds", - TNC->Port, STREAM->RemoteCall, - STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration), - STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration); - - Debugprintf(logmsg); - - STREAM->ConnectTime= 0; //Prevent retrigger - } - - - STREAM->Connecting = FALSE; - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->ReportDISC = TRUE; // Tell Node - - if (STREAM->Disconnecting) // - VARAReleaseTNC(TNC); - - STREAM->Disconnecting = FALSE; - - return; - } - - - if (_memicmp(Buffer, "IAMALIVE", 8) == 0) - { -// strcat(Buffer, "\r\n"); -// WritetoTrace(TNC, Buffer, strlen(Buffer)); - return; - } - -// Debugprintf(Buffer); - - if (_memicmp(Buffer, "FAULT", 5) == 0) - { - WritetoTrace(TNC, Buffer, MsgLen - 3); -// return; - } - - if (_memicmp(Buffer, "REGISTERED", 9) == 0) - { - strcat(Buffer, "\r"); - WritetoTrace(TNC, Buffer, (int)strlen(Buffer)); - return; - } - - if (_memicmp(Buffer, "MISSING SOUNDCARD", 17) == 0) - { - strcat(Buffer, "\r"); - WritetoTrace(TNC, Buffer, (int)strlen(Buffer)); - return; - } - - // Others should be responses to commands - - // Return others to user (if attached but not connected) - - if (TNC->Streams[0].Attached == 0) - return; - - if (TNC->Streams[0].Connected) - return; - - if (MsgLen > 200) - MsgLen = 200; - - buffptr = GetBuff(); - - if (buffptr == 0) - { - return; // No buffers, so ignore - } - - buffptr->Len = sprintf(buffptr->Data, "VARA} %s\r", Buffer); - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); -} - -VOID VARAProcessReceivedData(struct TNCINFO * TNC) -{ - int InputLen; - - InputLen = recv(TNC->TCPDataSock, TNC->ARDOPDataBuffer, 8192, 0); - - if (InputLen == 0 || InputLen == SOCKET_ERROR) - { - // Does this mean closed? - -// closesocket(TNC->TCPSock); - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - TNC->CONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->PTTMode) - Rig_PTT(TNC, FALSE); // Make sure PTT is down - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - TNC->Streams[0].Disconnecting = FALSE; - - - closesocket(TNC->TCPDataSock); - TNC->TCPSock = 0; - - - return; - } - - TNC->DataInputLen += InputLen; - - VARAProcessDataPacket(TNC, TNC->ARDOPDataBuffer, TNC->DataInputLen); - TNC->DataInputLen=0; - return; -} - - - -VOID VARAProcessReceivedControl(struct TNCINFO * TNC) -{ - int InputLen, MsgLen; - char * ptr, * ptr2; - char Buffer[4096]; - - // shouldn't get several messages per packet, as each should need an ack - // May get message split over packets - - if (TNC->InputLen > 8000) // Shouldnt have packets longer than this - TNC->InputLen=0; - - InputLen=recv(TNC->TCPSock, &TNC->ARDOPBuffer[TNC->InputLen], 8192 - TNC->InputLen, 0); - - if (InputLen == 0 || InputLen == SOCKET_ERROR) - { - closesocket(TNC->TCPSock); - - TNC->TCPSock = 0; - - TNC->CONNECTED = FALSE; - TNC->Streams[0].ReportDISC = TRUE; - - TNC->Streams[0].Disconnecting = FALSE; - - sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); - MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - return; - } - - TNC->InputLen += InputLen; - -loop: - - ptr = memchr(TNC->ARDOPBuffer, '\r', TNC->InputLen); - - if (ptr == 0) // CR in buffer - return; // Wait for it - - ptr2 = &TNC->ARDOPBuffer[TNC->InputLen]; - - if ((ptr2 - ptr) == 1) // CR - { - // Usual Case - single msg in buffer - - VARAProcessResponse(TNC, TNC->ARDOPBuffer, TNC->InputLen); - TNC->InputLen=0; - return; - } - else - { - MsgLen = TNC->InputLen - (int)(ptr2-ptr) + 1; // Include CR - - memcpy(Buffer, TNC->ARDOPBuffer, MsgLen); - - VARAProcessResponse(TNC, Buffer, MsgLen); - - if (TNC->InputLen < MsgLen) - { - TNC->InputLen = 0; - return; - } - memmove(TNC->ARDOPBuffer, ptr + 1, TNC->InputLen-MsgLen); - - TNC->InputLen -= MsgLen; - goto loop; - } - return; -} - - - -VOID VARAProcessDataPacket(struct TNCINFO * TNC, UCHAR * Data, int Length) -{ - // Info on Data Socket - just packetize and send on - - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - int PacLen = 236; - PMSGWITHLEN buffptr; - - TNC->TimeSinceLast = 0; - - STREAM->BytesRXed += Length; - - Data[Length] = 0; - Debugprintf("VARA: RXD %d bytes", Length); - - sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", - STREAM->BytesTXed, STREAM->BytesRXed,STREAM->BytesOutstanding); - MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - - // May need to fragment - - while (Length) - { - int Fraglen = Length; - - if (Length > PACLEN) - Fraglen = PACLEN; - - Length -= Fraglen; - - buffptr = GetBuff(); - - if (buffptr == 0) - return; // No buffers, so ignore - - memcpy(buffptr->Data, Data, Fraglen); - - WritetoTrace(TNC, Data, Fraglen); - - Data += Fraglen; - - buffptr->Len = Fraglen; - - C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr); - } - return; -} - -static VOID TidyClose(struct TNCINFO * TNC, int Stream) -{ - // If all acked, send disc - - if (TNC->Streams[0].BytesOutstanding == 0) - VARASendCommand(TNC, "DISCONNECT\r", TRUE); -} - -static VOID ForcedClose(struct TNCINFO * TNC, int Stream) -{ - char Abort[] = "ABORT\r"; - - VARASendCommand(TNC, Abort, TRUE); - WritetoTrace(TNC, Abort, 5); -} - -static VOID CloseComplete(struct TNCINFO * TNC, int Stream) -{ - VARAReleaseTNC(TNC); - TNC->ARDOPCurrentMode[0] = 0; // Force Mode select on next scan change - - // Also reset mode in case incoming call has changed it - - if (TNC->DefaultMode == 50) - VARASendCommand(TNC, "BW2300\r", TRUE); - else if (TNC->DefaultMode == 53) - VARASendCommand(TNC, "BW500\r", TRUE); - else if (TNC->DefaultMode == 54) - VARASendCommand(TNC, "BW2750\r", TRUE); -} - - -VOID VARASendCommand(struct TNCINFO * TNC, char * Buff, BOOL Queue) -{ - int SentLen; - - if (Buff[0] == 0) // Terminal Keepalive? - return; - - if (memcmp(Buff, "LISTEN O", 8) == 0) - TNC->DiscardNextOK = TRUE; // Responding to LISTEN messes up forwarding - - if (TNC->CONNECTED == 0) - return; - - if (TNC->TCPSock) - { - SentLen = send(TNC->TCPSock, Buff, (int)strlen(Buff), 0); - - if (SentLen != strlen(Buff)) - { - int winerr=WSAGetLastError(); - char ErrMsg[80]; - - sprintf(ErrMsg, "VARA Write Failed for port %d - error code = %d\r\n", TNC->Port, winerr); - WritetoConsole(ErrMsg); - - closesocket(TNC->TCPSock); - TNC->TCPSock = 0; - TNC->CONNECTED = FALSE; - return; - } - } - return; -} - -int VARASendData(struct TNCINFO * TNC, UCHAR * Buff, int Len) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - int bytes=send(TNC->TCPDataSock,(const char FAR *)Buff, Len, 0); - STREAM->BytesTXed += bytes; - WritetoTrace(TNC, Buff, Len); - return bytes; -} - -#ifndef LINBPQ - -BOOL CALLBACK EnumVARAWindowsProc(HWND hwnd, LPARAM lParam) -{ - char wtext[128]; - struct TNCINFO * TNC = (struct TNCINFO *)lParam; - UINT ProcessId; - int n; - - n = GetWindowText(hwnd, wtext, 127); - - if (memcmp(wtext,"VARA", 4) == 0) - { - GetWindowThreadProcessId(hwnd, &ProcessId); - - if (TNC->PID == ProcessId) - { - // Our Process - - char msg[512]; - char ID[64] = ""; - int i = 29; - - memcpy(ID, TNC->PortRecord->PORTCONTROL.PORTDESCRIPTION, 30); - - while (ID[i] == ' ') - ID[i--] = 0; - - wtext[n] = 0; - sprintf (msg, "BPQ %s - %s", ID, wtext); - SetWindowText(hwnd, msg); - return FALSE; - } - } - - return (TRUE); -} -#endif - -VOID VARAReleaseTNC(struct TNCINFO * TNC) -{ - // Set mycall back to Node or Port Call, and Start Scanner - - UCHAR TXMsg[1000]; - -// ARDOPChangeMYC(TNC, TNC->NodeCall); - - VARASendCommand(TNC, "LISTEN ON\r", TRUE); - - strcpy(TNC->WEB_TNCSTATE, "Free"); - MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Start Scanner - - if (TNC->DefaultRadioCmd) - { - sprintf(TXMsg, "%d %s", TNC->Port, TNC->DefaultRadioCmd); - Rig_Command(-1, TXMsg); - } - - sprintf(TXMsg, "%d SCANSTART 15", TNC->Port); - Rig_Command(-1, TXMsg); - - ReleaseOtherPorts(TNC); -} - - - - - - diff --git a/Versions-HPLaptop.h b/Versions-HPLaptop.h deleted file mode 100644 index 42c9d9f..0000000 --- a/Versions-HPLaptop.h +++ /dev/null @@ -1,125 +0,0 @@ - -#ifdef Kernel - -#define Vers 5,2,9,2 -#define Verstring "5.2.9.2\0" -#define Datestring "September 2012" -#define VerComments "G8BPQ Packet Switch V5.2.9.2\0" -#define VerCopyright "Copyright © 2001-2012 John Wiseman G8BPQ\0" -#define VerDesc "BPQ32 Switch\0" - -#endif - -#define KVers 6,0,23,51 -#define KVerstring "6.0.23.51\0" - -#ifdef CKernel - -#define Vers KVers -#define Verstring KVerstring -#define Datestring "March 2023" -#define VerComments "G8BPQ Packet Switch (C Version)" KVerstring -#define VerCopyright "Copyright © 2001-2023 John Wiseman G8BPQ\0" -#define VerDesc "BPQ32 Switch\0" -#define VerProduct "BPQ32" - -#endif - -#ifdef TermTCP - -#define Vers 1,0,16,1 -#define Verstring "1.0.16.1\0" -#define VerComments "Internet Terminal for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2011-2023 John Wiseman G8BPQ\0" -#define VerDesc "Simple TCP Terminal Program for G8BPQ Switch\0" -#define VerProduct "BPQTermTCP" - -#endif - -#ifdef BPQTerm - -#define Vers 2,2,5,1 -#define Verstring "2.2.5.1\0" -#define VerComments "Simple Terminal for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 1999-2023 John Wiseman G8BPQ\0" -#define VerDesc "Simple Terminal Program for G8BPQ Switch\0" -#define VerProduct "BPQTerminal" - -#endif - -#ifdef BPQTermMDI - -#define Vers 2,2,0,3 -#define Verstring "2.2.0.3\0" -#define VerComments "MDI Terminal for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 1999-2023 John Wiseman G8BPQ\0" -#define VerDesc "MDI Terminal Program for G8BPQ Switch\0" - -#endif - -#ifdef MAIL - -#define Vers KVers -#define Verstring KVerstring -#define VerComments "Mail server for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2009-2023 John Wiseman G8BPQ\0" -#define VerDesc "Mail server for G8BPQ's 32 Bit Switch\0" -#define VerProduct "BPQMail" - -#endif - -#ifdef HOSTMODES - -#define Vers 1,1,8,1 -#define Verstring "1.1.8.1\0" -//#define SPECIALVERSION "Test 3" -#define VerComments "Host Modes Emulator for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2009-2019 John Wiseman G8BPQ\0" -#define VerDesc "Host Modes Emulator for G8BPQ's 32 Bit Switch\0" -#define VerProduct "BPQHostModes" - -#endif - - -#ifdef UIUTIL - -#define Vers 0,1,3,1 -#define Verstring "0.1.3.1\0" -#define VerComments "Beacon Utility for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2011-2019 John Wiseman G8BPQ\0" -#define VerDesc "Beacon Utility for G8BPQ Switch\0" -#define VerProduct "BPQUIUtil" - -#endif - -#ifdef AUTH - -#define Vers 0,1,0,0 -#define Verstring "0.1.0.0\0" -#define VerComments "Password Generation Utility for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2011-2023 John Wiseman G8BPQ\0" -#define VerDesc "Password Generation Utility for G8BPQ Switch\0" - -#endif - -#ifdef APRS - -#define Vers KVers -#define Verstring KVerstring -#define VerComments "APRS Client for G8BPQ Switch\0" -#define VerCopyright "Copyright © 2012-2023 John Wiseman G8BPQ\0" -#define VerDesc "APRS Client for G8BPQ Switch\0" -#define VerProduct "BPQAPRS" - -#endif - -#ifdef CHAT - -#define Vers KVers -#define Verstring KVerstring -#define VerComments "Chat server for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2009-2023 John Wiseman G8BPQ\0" -#define VerDesc "Chat server for G8BPQ's 32 Bit Switch\0" -#define VerProduct "BPQChat" - -#endif diff --git a/WebMail-HPLaptop.c b/WebMail-HPLaptop.c deleted file mode 100644 index f76584b..0000000 --- a/WebMail-HPLaptop.c +++ /dev/null @@ -1,6171 +0,0 @@ -/* -Copyright 2001-2018 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 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 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -#define _CRT_SECURE_NO_DEPRECATE - -#include "CHeaders.h" -#include "bpqmail.h" - -#define MAIL -#include "httpconnectioninfo.h" - -#ifdef WIN32 -//#include "C:\Program Files (x86)\GnuWin32\include\iconv.h" -#else -#include -#include -#endif - -static struct HTTPConnectionInfo * FindSession(char * Key); -int APIENTRY SessionControl(int stream, int command, int param); -int SetupNodeMenu(char * Buff); -VOID SetMultiStringValue(char ** values, char * Multi); -char * GetTemplateFromFile(int Version, char * FN); -VOID FormatTime(char * Time, time_t cTime); -struct MsgInfo * GetMsgFromNumber(int msgno); -BOOL CheckUserMsg(struct MsgInfo * Msg, char * Call, BOOL SYSOP); -BOOL OkToKillMessage(BOOL SYSOP, char * Call, struct MsgInfo * Msg); -int DisplayWebForm(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, char * FileName, char * XML, char * Reply, char * RawMessage, int RawLen); -struct HTTPConnectionInfo * AllocateWebMailSession(); -VOID SaveNewMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest, int InputLen); -void ConvertTitletoUTF8(char * Title, char * UTF8Title); -char *stristr (char *ch1, char *ch2); -char * ReadTemplate(char * FormSet, char * DirName, char * FileName); -VOID DoStandardTemplateSubsitutions(struct HTTPConnectionInfo * Session, char * txtFile); -BOOL CheckifPacket(char * Via); -int GetHTMLFormSet(char * FormSet); -void ProcessFormInput(struct HTTPConnectionInfo * Session, char * input, char * Reply, int * RLen, int InputLen); -char * WebFindPart(char ** Msg, char * Boundary, int * PartLen, char * End); -struct HTTPConnectionInfo * FindWMSession(char * Key); -int SendWebMailHeaderEx(char * Reply, char * Key, struct HTTPConnectionInfo * Session, char * Alert); -char * BuildFormMessage(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, char * Keys[1000], char * Values[1000], int NumKeys); -char * FindXMLVariable(WebMailInfo * WebMail, char * Var); -int ReplyToFormsMessage(struct HTTPConnectionInfo * Session, struct MsgInfo * Msg, char * Reply, BOOL Reenter); -BOOL ParsetxtTemplate(struct HTTPConnectionInfo * Session, struct HtmlFormDir * Dir, char * FN, BOOL isReply); -VOID UpdateFormAction(char * Template, char * Key); -BOOL APIENTRY GetAPRSLatLon(double * PLat, double * PLon); -BOOL APIENTRY GetAPRSLatLonString(char * PLat, char * PLon); -void FreeWebMailFields(WebMailInfo * WebMail); -VOID BuildXMLAttachment(struct HTTPConnectionInfo * Session, char * Keys[1000], char * Values[1000], int NumKeys); -VOID SaveTemplateMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest); -VOID DownloadAttachments(struct HTTPConnectionInfo * Session, char * Reply, int * RLen, char * Rest); -VOID getAttachmentList(struct HTTPConnectionInfo * Session, char * Reply, int * RLen, char * Rest); -char * BuildB2Header(WebMailInfo * WebMail, struct MsgInfo * Msg, char ** ToCalls, int Calls); -VOID FormatTime2(char * Time, time_t cTime); -VOID ProcessSelectResponse(struct HTTPConnectionInfo * Session, char * URLParams); -VOID ProcessAskResponse(struct HTTPConnectionInfo * Session, char * URLParams); -char * CheckFile(struct HtmlFormDir * Dir, char * FN); -VOID GetPage(struct HTTPConnectionInfo * Session, char * NodeURL); -VOID SendTemplateSelectScreen(struct HTTPConnectionInfo * Session, char *URLParams, int InputLen); -BOOL isAMPRMsg(char * Addr); -char * doXMLTransparency(char * string); -Dll BOOL APIENTRY APISendAPRSMessage(char * Text, char * ToCall); - -extern char NodeTail[]; -extern char BBSName[10]; - -extern char LTFROMString[2048]; -extern char LTTOString[2048]; -extern char LTATString[2048]; - - UCHAR BPQDirectory[260]; - -int LineCount = 35; // Lines per page on message list - -// Forms - -struct HtmlFormDir ** HtmlFormDirs = NULL; -int FormDirCount = 0; - -struct HtmlForm -{ - char * FileName; - BOOL HasInitial; - BOOL HasViewer; - BOOL HasReply; - BOOL HasReplyViewer; -}; - -struct HtmlFormDir -{ - char * FormSet; - char * DirName; - struct HtmlForm ** Forms; - int FormCount; - struct HtmlFormDir ** Dirs; // Nested Directories - int DirCount; -}; - - -char FormDirList[4][MAX_PATH] = {"Standard_Templates", "Standard Templates", "Local_Templates"}; - -static char PassError[] = "

Sorry, User or Password is invalid - please try again

"; -static char BusyError[] = "

Sorry, No sessions available - please try later

"; - -extern char MailSignon[]; - -char WebMailSignon[] = "BPQ32 Mail Server Access" - "

BPQ32 Mail Server %s Access

" - "

Please enter Callsign and Password to access WebMail

" - "
" - "" - "" - "
User
Password
" - "

"; - -static char MsgInputPage[] = "" - "" - "" - "" - "" - "

Webmail Interface - Message Input Form

" - "
" - "
" - "To      %s
" - "Subject      " -// "" -// "
" - "" - "
Type    " - "" - " BID
" - "" - "" - "
" - "
" - "
"; - -static char CheckFormMsgPage[] = "" - "" - "" - "

Webmail Forms Interface - Check Message

" - "
" - - "
" - "To      
" - "CC      
" - "Subject " -//"" - "
Type    " - "" - " BID

" - "
" - - "
" - "
"; - - -extern char * WebMailTemplate; -extern char * WebMailMsgTemplate; -extern char * jsTemplate; - -static char *dat[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; -char *longday[] = {"Sunday", "Monday", "Tusday", "Wednesday", "Thusday", "Friday", "Saturday"}; - -static struct HTTPConnectionInfo * WebSessionList = NULL; // active WebMail sessions - -#ifdef LINBPQ -UCHAR * GetBPQDirectory(); -#endif - -void UndoTransparency(char * input); - -#ifndef LINBPQ - -void UndoTransparency(char * input) -{ - char * ptr1, * ptr2; - char c; - int hex; - - if (input == NULL) - return; - - ptr1 = ptr2 = input; - - // Convert any %xx constructs - - while (1) - { - c = *(ptr1++); - - if (c == 0) - break; - - if (c == '%') - { - c = *(ptr1++); - if(isdigit(c)) - hex = (c - '0') << 4; - else - hex = (tolower(c) - 'a' + 10) << 4; - - c = *(ptr1++); - if(isdigit(c)) - hex += (c - '0'); - else - hex += (tolower(c) - 'a' + 10); - - *(ptr2++) = hex; - } - else if (c == '+') - *(ptr2++) = 32; - else - *(ptr2++) = c; - } - *ptr2 = 0; -} -#endif - -void ReleaseWebMailStruct(WebMailInfo * WebMail) -{ - // release any malloc'ed resources - - if (WebMail == NULL) - return; - - FreeWebMailFields(WebMail); - free(WebMail); - return; -} - -VOID FreeWebMailMallocs() -{ - // called when closing. Not really needed, but simplifies tracking down real memory leaks - - struct HTTPConnectionInfo * Session, * SaveNext; - int i; - Session = WebSessionList; - - while (Session) - { - SaveNext = Session->Next; - - // Release amy malloc'ed resouces - - ReleaseWebMailStruct(Session->WebMail); - free(Session); - Session = SaveNext; - } - - for (i = 0; i < FormDirCount; i++) - { - struct HtmlFormDir * Dir = HtmlFormDirs[i]; - - int j; - - for (j = 0; j < Dir->FormCount; j++) - { - free(Dir->Forms[j]->FileName); - free(Dir->Forms[j]); - } - - if (Dir->DirCount) - { - struct HtmlFormDir * SubDir; - - int k, l; - - for (l = 0; l < Dir->DirCount; l++) - { - SubDir = Dir->Dirs[l]; - - for (k = 0; k < Dir->Dirs[l]->FormCount; k++) - { - free(SubDir->Forms[k]->FileName); - free(SubDir->Forms[k]); - } - free(SubDir->DirName); - free(SubDir->Forms); - free(SubDir->FormSet); - - free(Dir->Dirs[l]); - } - } - free(Dir->DirName); - free(Dir->Forms); - free(Dir->FormSet); - free(Dir); - } - - free(HtmlFormDirs); - return; -} - -char * initMultipartUnpack(char ** Input) -{ - // Check if Multipart and return Boundary. Update Input to first part - - // look through header for Content-Type line, and if multipart - // find boundary string. - - char * ptr, * ptr2; - char Boundary[128]; - BOOL Multipart = FALSE; - - ptr = *Input; - - while(*ptr != 13) - { - ptr2 = strchr(ptr, 10); // Find CR - - while(ptr2[1] == ' ' || ptr2[1] == 9) // Whitespace - continuation line - ptr2 = strchr(&ptr2[1], 10); // Find CR - - if (_memicmp(ptr, "Content-Type: ", 14) == 0) - { - char Line[256] = ""; - char * ptr3; - size_t len = ptr2-ptr-14; - - if (len >255) - return NULL; - - memcpy(Line, &ptr[14], len); - - if (_memicmp(Line, "Multipart/", 10) == 0) - { - ptr3 = stristr(Line, "boundary"); - if (ptr3) - { - ptr3+=9; - - if ((*ptr3) == '"') - ptr3++; - - strcpy(Boundary, ptr3); - ptr3 = strchr(Boundary, '"'); - if (ptr3) *ptr3 = 0; - ptr3 = strchr(Boundary, 13); // CR - if (ptr3) *ptr3 = 0; - break; - } - else - return NULL; // Can't do anything without a boundary ?? - } - } - ptr = ptr2; - ptr++; - } - - // Find First part - there is a boundary before it - - ptr = strstr(ptr2, Boundary); - - // Next should be crlf then part - - ptr = strstr(ptr, "\r\n"); - - if (ptr) - ptr += 2; // Over CRLF - - *Input = ptr; // Return first part or NULL - return _strdup(Boundary); -} - -BOOL unpackPart(char * Boundary, char ** Input, char ** Name, char ** Value, int * ValLen, char * End) -{ - // Format seems to be -/* - ------WebKitFormBoundaryABJaEbBWB5SuAHmq - Content-Disposition: form-data; name="Subj" - - subj - ------WebKitFormBoundaryABJaEbBWB5SuAHmq - Content-Disposition: form-data; name="myFile[]"; filename="exiftool.txt" - Content-Type: text/plain - - c:\exiftool "-filenameTo = _strdup(Value); - else if (strcmp(Name, "CC") == 0) - WebMail->CC = _strdup(Value); - else if (strcmp(Name, "Subj") == 0) - WebMail->Subject = _strdup(Value); - else if (strcmp(Name, "Type") == 0) - WebMail->Type = Value[0]; - else if (strcmp(Name, "BID") == 0) - WebMail->BID = _strdup(Value); - else if (strcmp(Name, "Msg") == 0) - WebMail->Body = _strdup(Value); - - else if (_memicmp(Name, "myFile[]", 8) == 0) - { - // Get File Name from param string - myFile[]"; filename="exiftool.txt" \r\nContent-Type: text/plain - - char * fn = strstr(Name, "filename="); - char * endfn; - if (fn) - { - fn += 10; - - endfn = strchr(fn, '"'); - if (endfn) - { - *endfn = 0; - - if (strlen(fn)) - { - WebMail->FileName[WebMail->Files] = _strdup(fn); - WebMail->FileBody[WebMail->Files] = malloc(ValLength); - memcpy(WebMail->FileBody[WebMail->Files], Value, ValLength); - WebMail->FileLen[WebMail->Files++] = ValLength; - } - } - } - } - - else if (_memicmp(Name, "myFile2[]", 8) == 0) - { - // Get File Name from param string - myFile[]"; filename="exiftool.txt" \r\nContent-Type: text/plain - - char * fn = strstr(Name, "filename="); - char * endfn; - if (fn) - { - fn += 10; - - endfn = strchr(fn, '"'); - if (endfn) - { - *endfn = 0; - - if (strlen(fn)) - { - WebMail->Header = malloc(ValLength + 1); - memcpy(WebMail->Header, Value, ValLength + 1); - WebMail->HeaderLen = RemoveLF(WebMail->Header, ValLength); - } - } - } - } - - else if (_memicmp(Name, "myFile3[]", 8) == 0) - { - // Get File Name from param string - myFile[]"; filename="exiftool.txt" \r\nContent-Type: text/plain - - char * fn = strstr(Name, "filename="); - char * endfn; - if (fn) - { - fn += 10; - - endfn = strchr(fn, '"'); - if (endfn) - { - *endfn = 0; - - if (strlen(fn)) - { - WebMail->Footer = malloc(ValLength + 1); - memcpy(WebMail->Footer, Value, ValLength + 1); - WebMail->FooterLen = RemoveLF(WebMail->Footer, ValLength); - } - } - } - } - - return TRUE; -} - - -struct HTTPConnectionInfo * AllocateWebMailSession() -{ - int KeyVal; - struct HTTPConnectionInfo * Session, * SaveNext; - time_t NOW = time(NULL); - - // First see if any session records havent been used for a while - - Session = WebSessionList; - - while (Session) - { - if (NOW - Session->WebMailLastUsed > 1200) // 20 Mins - { - SaveNext = Session->Next; - - // Release amy malloc'ed resouces - - ReleaseWebMailStruct(Session->WebMail); - - memset(Session, 0, sizeof(struct HTTPConnectionInfo)); - - Session->Next = SaveNext; - goto UseThis; - } - Session = Session->Next; - } - - Session = zalloc(sizeof(struct HTTPConnectionInfo)); - - if (Session == NULL) - return NULL; - - if (WebSessionList) - Session->Next = WebSessionList; - - WebSessionList = Session; - -UseThis: - - Session->WebMail = zalloc(sizeof(WebMailInfo)); - - KeyVal = ((rand() % 100) + 1); - - KeyVal *= (int)time(NULL); - - sprintf(Session->Key, "%c%08X", 'W', KeyVal); - - return Session; -} - -struct HTTPConnectionInfo * FindWMSession(char * Key) -{ - struct HTTPConnectionInfo * Session = WebSessionList; - - while (Session) - { - if (strcmp(Session->Key, Key) == 0) - { - Session->WebMailLastUsed = time(NULL); - return Session; - } - Session = Session->Next; - } - - return NULL; -} - - -// Build list of available forms - -VOID ProcessFormDir(char * FormSet, char * DirName, struct HtmlFormDir *** xxx, int * DirCount) -{ - struct HtmlFormDir * FormDir; - struct HtmlFormDir ** FormDirs = *xxx; - struct HtmlForm * Form; - char Search[MAX_PATH]; - int count = *DirCount; - -#ifdef WIN32 - HANDLE hFind = INVALID_HANDLE_VALUE; - WIN32_FIND_DATA ffd; -#else - DIR *dir; - struct dirent *entry; - char name[256]; -#endif - - FormDir = zalloc(sizeof (struct HtmlFormDir)); - - FormDir->DirName = _strdup(DirName); - FormDir->FormSet = _strdup(FormSet); - FormDirs=realloc(FormDirs, (count + 1) * sizeof(void *)); - FormDirs[count++] = FormDir; - - *DirCount = count; - *xxx = FormDirs; - - - // Scan Directory for .txt files - - sprintf(Search, "%s/%s/%s/*", GetBPQDirectory(), FormSet, DirName); - - // Find the first file in the directory. - -#ifdef WIN32 - - hFind = FindFirstFile(Search, &ffd); - - if (INVALID_HANDLE_VALUE == hFind) - return; - - do - { - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - char Dir[MAX_PATH]; - - if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) - continue; - - // Recurse in subdir - - sprintf(Dir, "%s/%s", DirName, ffd.cFileName); - - ProcessFormDir(FormSet, Dir, &FormDir->Dirs, &FormDir->DirCount); - - continue; - - } - - // Add to list - - Form = zalloc(sizeof (struct HtmlForm)); - - Form->FileName = _strdup(ffd.cFileName); - - FormDir->Forms=realloc(FormDir->Forms, (FormDir->FormCount + 1) * sizeof(void *)); - FormDir->Forms[FormDir->FormCount++] = Form; - } - - while (FindNextFile(hFind, &ffd) != 0); - - FindClose(hFind); - -#else - - sprintf(Search, "%s/%s/%s", GetBPQDirectory(), FormSet, DirName); - - if (!(dir = opendir(Search))) - { - Debugprintf("%s %d %d", "cant open forms dir", errno, dir); - return ; - } - while ((entry = readdir(dir)) != NULL) - { - if (entry->d_type == DT_DIR) - { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - Debugprintf("Recurse %s/%s/%s", FormSet, DirName, entry->d_name); - continue; - - } - // see if initial html - -// if (stristr(entry->d_name, "initial.html")) - { - // Add to list - - Form = zalloc(sizeof (struct HtmlForm)); - - Form->FileName = _strdup(entry->d_name); - - FormDir->Forms=realloc(FormDir->Forms, (FormDir->FormCount + 1) * sizeof(void *)); - FormDir->Forms[FormDir->FormCount++] = Form; - } - } - closedir(dir); -#endif - return; -} - -int GetHTMLForms() -{ - int n = 0; - - while (FormDirList[n][0]) - GetHTMLFormSet(FormDirList[n++]); - - return 0; -} - -int GetHTMLFormSet(char * FormSet) -{ - int i; - -#ifdef WIN32 - - WIN32_FIND_DATA ffd; - char szDir[MAX_PATH]; - HANDLE hFind = INVALID_HANDLE_VALUE; - DWORD dwError=0; - - sprintf(szDir, "%s/%s/*", BPQDirectory, FormSet); - - // Find the first file in the directory. - - hFind = FindFirstFile(szDir, &ffd); - - if (INVALID_HANDLE_VALUE == hFind) - { - // Accept either - return 0; - } - - // Scan all directories looking for file - - do - { - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) - continue; - - // Add to Directory List - - ProcessFormDir(FormSet, ffd.cFileName, &HtmlFormDirs, &FormDirCount); - } - } - - while (FindNextFile(hFind, &ffd) != 0); - - FindClose(hFind); - -#else - - DIR *dir; - struct dirent *entry; - char name[256]; - - sprintf(name, "%s/%s", BPQDirectory, FormSet); - - if (!(dir = opendir(name))) - { - Debugprintf("cant open forms dir %s %d %d", name, errno, dir); - return 0; - } - - while ((entry = readdir(dir)) != NULL) - { - if (entry->d_type == DT_DIR) - { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - // Add to Directory List - - ProcessFormDir(FormSet, entry->d_name, &HtmlFormDirs, &FormDirCount); - } - } - closedir(dir); -#endif - - // List for testing - - return 0; - - Debugprintf("%d form dirs", FormDirCount); - - for (i = 0; i < FormDirCount; i++) - { - struct HtmlFormDir * Dir = HtmlFormDirs[i]; - - int j; - Debugprintf("%3d %s", Dir->FormCount, Dir->DirName); - - for (j = 0; j < Dir->FormCount; j++) - Debugprintf(" %s", Dir->Forms[j]->FileName); - - if (Dir->DirCount) - { - int k, l; - - for (l = 0; l < Dir->DirCount; l++) - { - Debugprintf("Subdir %3d %s", Dir->Dirs[l]->DirCount, Dir->Dirs[l]->DirName); - for (k = 0; k < Dir->Dirs[l]->FormCount; k++) - Debugprintf(" %s", Dir->Dirs[l]->Forms[k]->FileName); - } - } - } - - - return 0; -} - - -static int compare(const void *arg1, const void *arg2) -{ - // Compare Calls. Fortunately call is at start of stuct - - return _stricmp(*(char**)arg1 , *(char**)arg2); -} - - -int SendWebMailHeader(char * Reply, char * Key, struct HTTPConnectionInfo * Session) -{ - return SendWebMailHeaderEx(Reply, Key, Session, NULL); -} - - -int SendWebMailHeaderEx(char * Reply, char * Key, struct HTTPConnectionInfo * Session, char * Alert) -{ - // Ex includes an alert string to be sent before message - - struct UserInfo * User = Session->User; - char Messages[245000]; - int m; - struct MsgInfo * Msg; - char * ptr = Messages; - int n = NumberofMessages; //LineCount; - char Via[64]; - int Count = 0; - - Messages[0] = 0; - - if (Alert && Alert[0]) - ptr += sprintf(Messages, "", Alert, Key); - - ptr += sprintf(ptr, "%s", " # Date XX Len To @ From Subject\r\n\r\n"); - - for (m = LatestMsg; m >= 1; m--) - { - if (ptr > &Messages[244000]) - break; // protect buffer - - Msg = GetMsgFromNumber(m); - - if (Msg == 0 || Msg->type == 0 || Msg->status == 0) - continue; // Protect against corrupt messages - - if (Msg && CheckUserMsg(Msg, User->Call, User->flags & F_SYSOP)) - { - char UTF8Title[128]; - char * EncodedTitle; - - // List if it is the right type and in the page range we want - - if (Session->WebMailTypes[0] && strchr(Session->WebMailTypes, Msg->type) == 0) - continue; - - // All Types or right Type. Check Mine Flag - - if (Session->WebMailMine) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->to) != 0 && strcmp(User->Call, Msg->from) != 0) - continue; - } - - if (Count++ < Session->WebMailSkip) - continue; - - strcpy(Via, Msg->via); - strlop(Via, '.'); - - // make sure title is HTML safe (no < > etc) and UTF 8 encoded - - EncodedTitle = doXMLTransparency(Msg->title); - - ConvertTitletoUTF8(EncodedTitle, UTF8Title); - - free(EncodedTitle); - - ptr += sprintf(ptr, "%6d %s %c%c %5d %-8s%-8s%-8s%s\r\n", - Key, Msg->number, Msg->number, - FormatDateAndTime((time_t)Msg->datecreated, TRUE), Msg->type, - Msg->status, Msg->length, Msg->to, Via, - Msg->from, UTF8Title); - - n--; - - if (n == 0) - break; - } - } - - if (WebMailTemplate == NULL) - WebMailTemplate = GetTemplateFromFile(6, "WebMailPage.txt"); - - return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Key, Messages); -} - -int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Number, BOOL DisplayHTML) -{ - char * Key = Session->Key; - struct UserInfo * User = Session->User; - WebMailInfo * WebMail = Session->WebMail; - char * DisplayStyle; - - char Message[200000] = ""; - struct MsgInfo * Msg; - char * ptr = Message; - char * MsgBytes, * Save; - int msgLen; - - char FullTo[100]; - char UTF8Title[128]; - int Index; - char * crcrptr; - char DownLoad[256] = ""; - - DisplayStyle = "textarea"; // Prevents interpretation of html and xml - - Msg = GetMsgFromNumber(Number); - - if (Msg == NULL) - { - ptr += sprintf(ptr, "Message %d not found\r\n", Number); - return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Message); - } - - // New Display so free any old values - - FreeWebMailFields(WebMail); - - WebMail->CurrentMessageIndex = Number; - - - if (!CheckUserMsg(Msg, User->Call, User->flags & F_SYSOP)) - { - ptr += sprintf(ptr, "Message %d not for you\r", Number); - return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Message); - } - - if (_stricmp(Msg->to, "RMS") == 0) - sprintf(FullTo, "RMS:%s", Msg->via); - else - if (Msg->to[0] == 0) - sprintf(FullTo, "smtp:%s", Msg->via); - else - strcpy(FullTo, Msg->to); - - // make sure title is UTF 8 encoded - - ConvertTitletoUTF8(Msg->title, UTF8Title); - - // if a B2 message diplay B2 Header instead of a locally generated one - - if ((Msg->B2Flags & B2Msg) == 0) - { - ptr += sprintf(ptr, "From: %s%s\nTo: %s\nType/Status: %c%c\nDate/Time: %s\nBid: %s\nTitle: %s\n\n", - Msg->from, Msg->emailfrom, FullTo, Msg->type, Msg->status, FormatDateAndTime((time_t)Msg->datecreated, FALSE), Msg->bid, UTF8Title); - } - - MsgBytes = Save = ReadMessageFile(Number); - - msgLen = Msg->length; - - if (Msg->type == 'P') - Index = PMSG; - else if (Msg->type == 'B') - Index = BMSG; - else - Index = TMSG; - - if (MsgBytes) - { - if (Msg->B2Flags & B2Msg) - { - char * ptr1; - - // if message has attachments, display them if plain text - - if (Msg->B2Flags & Attachments) - { - int BodyLen, NewLen; - int i; - char *ptr2, *attptr; - - sprintf(DownLoad, "Save Attachments", Key, Msg->number); - - WebMail->Files = 0; - - ptr1 = MsgBytes; - - // ptr += sprintf(ptr, "Message has Attachments\r\n\r\n"); - - while(*ptr1 != 13) - { - ptr2 = strchr(ptr1, 10); // Find CR - - if (memcmp(ptr1, "Body: ", 6) == 0) - { - BodyLen = atoi(&ptr1[6]); - } - - if (memcmp(ptr1, "File: ", 6) == 0) - { - char * ptr3 = strchr(&ptr1[6], ' '); // Find Space - *(ptr2 - 1) = 0; - - WebMail->FileLen[WebMail->Files] = atoi(&ptr1[6]); - WebMail->FileName[WebMail->Files++] = _strdup(&ptr3[1]); - *(ptr2 - 1) = ' '; // put space back - } - - ptr1 = ptr2; - ptr1++; - } - - ptr1 += 2; // Over Blank Line and Separator - - // ptr1 is pointing to body. Save for possible reply - - WebMail->Body = malloc(BodyLen + 2); - memcpy(WebMail->Body, ptr1, BodyLen); - WebMail->Body[BodyLen] = 0; - - *(ptr1 + BodyLen) = 0; - - ptr += sprintf(ptr, "%s", MsgBytes); // B2 Header and Body - - ptr1 += BodyLen + 2; // to first file - - // Save pointers to file - - attptr = ptr1; - - for (i = 0; i < WebMail->Files; i++) - { - WebMail->FileBody[i] = malloc(WebMail->FileLen[i]); - memcpy(WebMail->FileBody[i], attptr, WebMail->FileLen[i]); - attptr += (WebMail->FileLen[i] + 2); - } - - // if first (only??) attachment is XML and filename - // starts "RMS_Express_Form" process as HTML Form - - if (DisplayHTML && _memicmp(ptr1, "FileName[0], "RMS_Express_Form_", 16) == 0) - { - int Len = DisplayWebForm(Session, Msg, WebMail->FileName[0], ptr1, Reply, MsgBytes, BodyLen + 32); // 32 for added "has attachments" - free(MsgBytes); - - // Flag as read - - if ((_stricmp(Msg->to, User->Call) == 0) || ((User->flags & F_SYSOP) && (_stricmp(Msg->to, "SYSOP") == 0))) - { - if ((Msg->status != 'K') && (Msg->status != 'H') && (Msg->status != 'F') && (Msg->status != 'D')) - { - if (Msg->status != 'Y') - { - Msg->status = 'Y'; - Msg->datechanged=time(NULL); - SaveMessageDatabase(); - - } - } - } - - return Len; - } - - for (i = 0; i < WebMail->Files; i++) - { - int n; - char * p = ptr1; - char c; - - // Check if message is probably binary - - int BinCount = 0; - - NewLen = WebMail->FileLen[i]; - - for (n = 0; n < NewLen; n++) - { - c = *p; - - if (c==0 || (c & 128)) - BinCount++; - - p++; - - } - - if (BinCount > NewLen/10) - { - // File is probably Binary - - ptr += sprintf(ptr, "\rAttachment %s is a binary file\r", WebMail->FileName[i]); - } - else - { - *(ptr1 + NewLen) = 0; - ptr += sprintf(ptr, "\rAttachment %s\r\r", WebMail->FileName[i]); - RemoveLF(ptr1, NewLen + 1); // Removes LF after CR but not on its own - - ptr += sprintf(ptr, "%s\r\r", ptr1); - - User->Total.MsgsSent[Index] ++; - User->Total.BytesForwardedOut[Index] += NewLen; - } - - ptr1 += WebMail->FileLen[i]; - ptr1 +=2; // Over separator - } - - free(Save); - - ptr += sprintf(ptr, "\r\r[End of Message #%d from %s]\r", Number, Msg->from); - - RemoveLF(Message, (int)strlen(Message) + 1); // Removes LF after CR but not on its own - - if ((_stricmp(Msg->to, User->Call) == 0) || ((User->flags & F_SYSOP) && (_stricmp(Msg->to, "SYSOP") == 0))) - { - if ((Msg->status != 'K') && (Msg->status != 'H') && (Msg->status != 'F') && (Msg->status != 'D')) - { - if (Msg->status != 'Y') - { - Msg->status = 'Y'; - Msg->datechanged=time(NULL); - SaveMessageDatabase(); - } - } - } - return sprintf(Reply, WebMailMsgTemplate, BBSName, User->Call, Msg->number, Msg->number, Key, Msg->number, Key, DownLoad, Key, Key, Key, DisplayStyle, Message, DisplayStyle); - } - - // Remove B2 Headers (up to the File: Line) - - // ptr1 = strstr(MsgBytes, "Body:"); - - // if (ptr1) - // MsgBytes = ptr1; - } - - // Body may have cr cr lf which causes double space - - crcrptr = strstr(MsgBytes, "\r\r\n"); - - while (crcrptr) - { - *crcrptr = ' '; - crcrptr = strstr(crcrptr, "\r\r\n"); - } - - // Remove lf chars - - msgLen = RemoveLF(MsgBytes, msgLen); - - User->Total.MsgsSent[Index] ++; - // User->Total.BytesForwardedOut[Index] += Length; - - - // if body not UTF-8, convert it - - if (WebIsUTF8(MsgBytes, msgLen) == FALSE) - { - // With Windows it is simple - convert using current codepage - // I think the only reliable way is to convert to unicode and back - - size_t origlen = msgLen + 1; - - UCHAR * BufferB = malloc(2 * origlen); - -#ifdef WIN32 - - WCHAR * BufferW = malloc(2 * origlen); - int wlen; - int len = (int)origlen; - - wlen = MultiByteToWideChar(CP_ACP, 0, MsgBytes, len, BufferW, (int)(origlen * 2)); - len = WideCharToMultiByte(CP_UTF8, 0, BufferW, wlen, BufferB, (int)(origlen * 2), NULL, NULL); - - free(Save); - Save = MsgBytes = BufferB; - free(BufferW); - msgLen = len - 1; // exclude NULL - -#else - int left = 2 * msgLen; - int len = msgLen; - UCHAR * BufferBP = BufferB; - iconv_t * icu = NULL; - - if (icu == NULL) - icu = iconv_open("UTF-8", "CP1252"); - - iconv(icu, NULL, NULL, NULL, NULL); // Reset State Machine - iconv(icu, &MsgBytes, &len, (char ** __restrict__)&BufferBP, &left); - - free(Save); - Save = MsgBytes = BufferB; - msgLen = strlen(MsgBytes); - -#endif - - } - - - // ptr += sprintf(ptr, "%s", MsgBytes); - - memcpy(ptr, MsgBytes, msgLen); - ptr += msgLen; - ptr[0] = 0; - - free(Save); - - ptr += sprintf(ptr, "\r\r[End of Message #%d from %s]\r", Number, Msg->from); - - if ((_stricmp(Msg->to, User->Call) == 0) || ((User->flags & F_SYSOP) && (_stricmp(Msg->to, "SYSOP") == 0))) - { - if ((Msg->status != 'K') && (Msg->status != 'H') && (Msg->status != 'F') && (Msg->status != 'D')) - { - if (Msg->status != 'Y') - { - Msg->status = 'Y'; - Msg->datechanged=time(NULL); - SaveMessageDatabase(); - } - } - } - } - else - { - ptr += sprintf(ptr, "File for Message %d not found\r", Number); - } - - if (DisplayHTML && stristr(Message, "html>")) - DisplayStyle = "div"; // Use div so HTML and XML are interpreted - - - - - - return sprintf(Reply, WebMailMsgTemplate, BBSName, User->Call, Msg->number, Msg->number, Key, Msg->number, Key, DownLoad, Key, Key, Key, DisplayStyle, Message, DisplayStyle); -} - -int KillWebMailMessage(char * Reply, char * Key, struct UserInfo * User, int Number) -{ - struct MsgInfo * Msg; - char Message[100] = ""; - - Msg = GetMsgFromNumber(Number); - - if (Msg == NULL) - { - sprintf(Message, "Message %d not found", Number); - goto returnit; - } - - if (OkToKillMessage(User->flags & F_SYSOP, User->Call, Msg)) - { - FlagAsKilled(Msg, TRUE); - sprintf(Message, "Message #%d Killed\r", Number); - goto returnit; - } - - sprintf(Message, "Not your message\r"); - -returnit: - return sprintf(Reply, WebMailMsgTemplate, BBSName, User->Call, Msg->number, Msg->number, Key, Msg->number, Key, "", Key, Key, Key, "div", Message, "div"); -} - -void freeKeys(KeyValues * Keys) -{ - while (Keys->Key) - { - free(Keys->Key); - free(Keys->Value); - Keys++; - } -} - -void FreeWebMailFields(WebMailInfo * WebMail) -{ - // release any malloc'ed resources - - int i; - char * SaveReply; - int * SaveRlen; - - if (WebMail == NULL) - return; - - if (WebMail->txtFile) - free(WebMail->txtFile); - - if (WebMail->txtFileName) - free(WebMail->txtFileName); - - if (WebMail->InputHTMLName) - free(WebMail->InputHTMLName); - - if (WebMail->DisplayHTMLName) - free(WebMail->DisplayHTMLName); - - if (WebMail->ReplyHTMLName) - free(WebMail->ReplyHTMLName); - - if (WebMail->To) - free(WebMail->To); - if (WebMail->CC) - free(WebMail->CC); - if (WebMail->Subject) - free(WebMail->Subject); - if (WebMail->BID) - free(WebMail->BID); - if (WebMail->Body) - free(WebMail->Body); - if (WebMail->XML) - free(WebMail->XML); - if (WebMail->XMLName) - free(WebMail->XMLName); - - if (WebMail->OrigTo) - free(WebMail->OrigTo); - if (WebMail->OrigSubject) - free(WebMail->OrigSubject); - if (WebMail->OrigBID) - free(WebMail->OrigBID); - if (WebMail->OrigBody) - free(WebMail->OrigBody); - - freeKeys(WebMail->txtKeys); - freeKeys(WebMail->XMLKeys); - - for (i = 0; i < WebMail->Files; i++) - { - free(WebMail->FileBody[i]); - free(WebMail->FileName[i]); - } - - if (WebMail->Header) - free(WebMail->Header); - if (WebMail->Footer) - free(WebMail->Footer); - - SaveReply = WebMail->Reply; - SaveRlen = WebMail->RLen; - - memset(WebMail, 0, sizeof(WebMailInfo)); - - WebMail->Reply = SaveReply; - WebMail->RLen = SaveRlen; - - return; -} - - -void ProcessWebMailMessage(struct HTTPConnectionInfo * Session, char * Key, BOOL LOCAL, char * Method, char * NodeURL, char * input, char * Reply, int * RLen, int InputLen) -{ - char * URLParams = strlop(Key, '&'); - int ReplyLen; - char Appl = 'M'; - - // Webmail doesn't use the normal Mail Key. - - // webscript.js doesn't need a key - - if (_stricmp(NodeURL, "/WebMail/webscript.js") == 0) - { - if (jsTemplate) - free(jsTemplate); - - jsTemplate = GetTemplateFromFile(2, "webscript.js"); - - ReplyLen = sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n" - "Cache-Control: max-age=60\r\nContent-Type: text/javascript\r\n\r\n%s", (int)strlen(jsTemplate), jsTemplate); - *RLen = ReplyLen; - return; - } - - // Neither do js or file downloads - - if (_memicmp(NodeURL, "/WebMail/WMFile/", 16) == 0) - { - int FileSize; - char * MsgBytes; - char MsgFile[512]; - FILE * hFile; - size_t ReadLen; - char TimeString[64]; - char FileTimeString[64]; - struct stat STAT; - char * FN = &NodeURL[16]; - char * fileBit = FN; - char * ext; - - UndoTransparency(FN); - ext = strchr(FN, '.'); - - sprintf(MsgFile, "%s/%s", BPQDirectory, FN); - - while (strchr(fileBit, '/')) - fileBit = strlop(fileBit, '/'); - - if (stat(MsgFile, &STAT) == -1) - { - *RLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 16\r\n\r\nPage not found\r\n"); - return; - } - - hFile = fopen(MsgFile, "rb"); - - if (hFile == 0) - { - *RLen = sprintf(Reply, "HTTP/1.1 404 Not Found\r\nContent-Length: 16\r\n\r\nPage not found\r\n"); - return; - } - - FileSize = STAT.st_size; - MsgBytes = malloc(FileSize + 1); - ReadLen = fread(MsgBytes, 1, FileSize, hFile); - - fclose(hFile); - - FormatTime2(FileTimeString, STAT.st_ctime); - FormatTime2(TimeString, time(NULL)); - - if (_stricmp(ext, ".htm") == 0 || _stricmp(ext, ".html") == 0 || _stricmp(ext, ".css") == 0 || _stricmp(ext, ".js") == 0) - { - *RLen = sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n" - "Content-Type: text/css\r\n" - "Date: %s\r\n" - "Last-Modified: %s\r\n" - "\r\n%s", FileSize, TimeString, FileTimeString, MsgBytes); - } - else - { - *RLen = sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n" - "Content-Type: application/octet-stream\r\n" - "Content-Disposition: attachment; filename=\"%s\"\r\n" - "Date: %s\r\n" - "Last-Modified: %s\r\n" - "\r\n%s", FileSize, fileBit, TimeString, FileTimeString, MsgBytes); - - } - free (MsgBytes); - return; - } - - Session = NULL; - - if (Key && Key[0]) - Session = FindWMSession(Key); - - if (Session == NULL) - { - // Lost Session - - if (LOCAL) - { - Session = AllocateWebMailSession(); - - Key = Session->Key; - - if (SYSOPCall[0]) - Session->User = LookupCall(SYSOPCall); - else - Session->User = LookupCall(BBSName); - - if (Session->User) - { - strcpy(NodeURL, "/WebMail/WebMail"); - Session->WebMailSkip = 0; - Session->WebMailLastUsed = time(NULL); - } - } - else - { - // Send Login Page unless Signon request - - if (_stricmp(NodeURL, "/WebMail/Signon") != 0 || strcmp(Method, "POST") != 0) - { - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - } - } - - if (strcmp(Method, "POST") == 0) - { - if (_stricmp(NodeURL, "/WebMail/Signon") == 0) - { - char * msg = strstr(input, "\r\n\r\n"); // End of headers - char * user, * password, * Key; - char Msg[128]; - int n; - - if (msg) - { - struct UserInfo * User; - - if (strstr(msg, "Cancel=Cancel")) - { - *RLen = sprintf(Reply, ""); - return; - } - // Webmail Gets Here with a dummy Session - - Session = AllocateWebMailSession(); - Session->WebMail->Reply = Reply; - Session->WebMail->RLen = RLen; - - - Key = Session->Key; - - user = strtok_s(&msg[9], "&", &Key); - password = strtok_s(NULL, "=", &Key); - password = Key; - - Session->User = User = LookupCall(user); - - if (User) - { - // Check Password - - if (password[0] && strcmp(User->pass, password) == 0) - { - // send Message Index - - Session->WebMailLastUsed = time(NULL); - Session->WebMailSkip = 0; - Session->WebMailMine = FALSE; - - if (WebMailTemplate) - { - free(WebMailTemplate); - WebMailTemplate = NULL; - } - - if (User->flags & F_Excluded) - { - n = sprintf_s(Msg, sizeof(Msg), "Webmail Connect from %s Rejected by Exclude Flag", _strupr(user)); - WriteLogLine(NULL, '|',Msg, n, LOG_BBS); - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - n=sprintf_s(Msg, sizeof(Msg), "Webmail Connect from %s", _strupr(user)); - WriteLogLine(NULL, '|',Msg, n, LOG_BBS); - - return; - } - - } - - // Bad User or Pass - - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - } - - Session->WebMail->Reply = Reply; - Session->WebMail->RLen = RLen; - - if (_stricmp(NodeURL, "/WebMail/EMSave") == 0) - { - // Save New Message - - SaveNewMessage(Session, input, Reply, RLen, Key, InputLen); - return; - } - - if (_stricmp(NodeURL, "/WebMail/Submit") == 0) - { - // Get the POST data from the page and place in message - - char * param = strstr(input, "\r\n\r\n"); // End of headers - WebMailInfo * WebMail = Session->WebMail; - - if (WebMail == NULL) - return; // Can't proceed if we have no info on form - - ProcessFormInput(Session, input, Reply, RLen, InputLen); - return; - } - - if (_stricmp(NodeURL, "/WebMail/FormMsgSave") == 0) - { - // Save New Message - - SaveTemplateMessage(Session, input, Reply, RLen, Key); - return; - } - - if (_stricmp(NodeURL, "/WebMail/GetTemplates") == 0) - { - SendTemplateSelectScreen(Session, input, InputLen); - return; - } - - // End of POST section - } - - if (_stricmp(NodeURL, "/WebMail/WMLogout") == 0) - { - Session->Key[0] = 0; - Session->WebMailLastUsed = 0; - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - - if ((_stricmp(NodeURL, "/WebMail/MailEntry") == 0) || - (_stricmp(NodeURL, "/WebMail") == 0) || - (_stricmp(NodeURL, "/WebMail/") == 0)) - { - // Entry from Menu if signed in, continue. If not and Localhost - // signin as sysop. - - if (Session->User == NULL) - { - // Not yet signed in - - if (LOCAL) - { - // Webmail Gets Here with a dummy Session - - Session = AllocateWebMailSession(); - Session->WebMail->Reply = Reply; - Session->WebMail->RLen = RLen; - - Key = Session->Key; - - if (SYSOPCall[0]) - Session->User = LookupCall(SYSOPCall); - else - Session->User = LookupCall(BBSName); - - if (Session->User) - { - strcpy(NodeURL, "/WebMail/WebMail"); - Session->WebMailSkip = 0; - Session->WebMailLastUsed = time(NULL); - } - } - else - { - // Send Login Page - - ReplyLen = sprintf(Reply, WebMailSignon, BBSName, BBSName); - *RLen = ReplyLen; - return; - } - } - } - - Session->WebMail->Reply = Reply; - Session->WebMail->RLen = RLen; - - if (_stricmp(NodeURL, "/WebMail/WebMail") == 0) - { - if (WebMailTemplate) - { - free(WebMailTemplate); - WebMailTemplate = NULL; - } - - Session->WebMailSkip = 0; - Session->WebMailMine = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMAll") == 0) - { - Session->WebMailSkip = 0; - Session->WebMailTypes[0] = 0; - Session->WebMailMine = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMB") == 0) - { - Session->WebMailSkip = 0; - strcpy(Session->WebMailTypes, "B"); - Session->WebMailMine = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMP") == 0) - { - Session->WebMailSkip = 0; - strcpy(Session->WebMailTypes, "P"); - Session->WebMailMine = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMT") == 0) - { - Session->WebMailSkip = 0; - strcpy(Session->WebMailTypes, "T"); - Session->WebMailMine = FALSE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMMine") == 0) - { - Session->WebMailSkip = 0; - Session->WebMailTypes[0] = 0; - Session->WebMailMine = TRUE; - - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - - if (_stricmp(NodeURL, "/WebMail/WMSame") == 0) - { - *RLen = SendWebMailHeader(Reply, Session->Key, Session); - return; - } - - if (_stricmp(NodeURL, "/WebMail/WMAuto") == 0) - { - // Auto Refresh Version of index page. Uses Web Sockets - - char Page[4096]; - - char WebSockPage[] = - "\r\n" - " \r\n" - " \r\n" - " \r\n" - " \r\n" - "\r\n" - "\r\n" - - "\r\n" - "WebMail \r\n" - "\r\n" - - "\r\n" - "

%s Webmail Interface - User %s - Message List

\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "
BullsPersonalNTSAll TypesMineAuto RefreshSend MessageLogoutNode Menu
\r\n" - "
\r\n" - - "
Waiting for data...
\r\n" - "\r\n"; - - sprintf(Page, WebSockPage, Key, Key ,BBSName, Session->User->Call, Key, Key, Key, Key, Key, Key, Key, Key); - - *RLen = sprintf(Reply, "%s", Page); - return; - } - - - if (memcmp(NodeURL, "/WebMail/QuoteOriginal/", 15) == 0) - { - // Reply to Message - - int n, len; - struct MsgInfo * Msg; - char Message[100] = ""; - char Title[100]; - char * MsgBytes, * Save, * NewBytes; - char * ptr; - char * ptr1, * ptr2; - char * EncodedTitle; - - n = Session->WebMail->CurrentMessageIndex; - - Msg = GetMsgFromNumber(n); - - if (Msg == NULL) - { - sprintf(Message, "Message %d not found", n); - *RLen = sprintf(Reply, "%s", Message); - return; - } - - Session->WebMail->Msg = Msg; - - if (stristr(Msg->title, "Re:") == 0) - sprintf(Title, "Re:%s", Msg->title); - else - sprintf(Title, "%s", Msg->title); - - MsgBytes = Save = ReadMessageFile(n); - - - ptr = NewBytes = malloc((Msg->length * 2) + 256); - - // Copy a line at a time with "> " in front of each - - ptr += sprintf(ptr, "%s", "\r\n\r\n\r\n\r\n\r\nOriginal Message\r\n\r\n> "); - - ptr1 = ptr2 = MsgBytes; - len = (int)strlen(MsgBytes); - - while (len-- > 0) - { - *ptr++ = *ptr1; - - if (*(ptr1) == '\n') - { - *ptr++ = '>'; - *ptr++ = ' '; - } - - ptr1++; - } - - *ptr++ = 0; - - EncodedTitle = doXMLTransparency(Msg->title); - - *RLen = sprintf(Reply, MsgInputPage, Key, Msg->from, "", EncodedTitle , NewBytes); - - free(EncodedTitle); - - free(MsgBytes); - free(NewBytes); - - return; - } - - - - if (memcmp(NodeURL, "/WebMail/Reply/", 15) == 0) - { - // Reply to Message - - int n = atoi(&NodeURL[15]); - struct MsgInfo * Msg; - char Message[100] = ""; - char Title[100]; - char * EncodedTitle; - - // Quote Original - - char Button[] = - "      " - ""; - - char Temp[1024]; - char ReplyAddr[128]; - - Msg = GetMsgFromNumber(n); - - if (Msg == NULL) - { - sprintf(Message, "Message %d not found", n); - *RLen = sprintf(Reply, "%s", Message); - return; - } - - Session->WebMail->Msg = Msg; - - // See if the message was displayed in an HTML form with a reply template - - *RLen = ReplyToFormsMessage(Session, Msg, Reply, FALSE); - - // If couldn't build reply form use normal text reply - - if (*RLen) - return; - - - sprintf(Temp, Button, Key); - - if (stristr(Msg->title, "Re:") == 0) - sprintf(Title, "Re:%s", Msg->title); - else - sprintf(Title, "%s", Msg->title); - - strcpy(ReplyAddr, Msg->from); - strcat(ReplyAddr, Msg->emailfrom); - - EncodedTitle = doXMLTransparency(Msg->title); - - *RLen = sprintf(Reply, MsgInputPage, Key, Msg->from, Temp, EncodedTitle , ""); - - free(EncodedTitle); - return; - } - - if (strcmp(NodeURL, "/WebMail/WM") == 0) - { - // Read Message - - int n = 0; - - if (URLParams) - n = atoi(URLParams); - - if (WebMailMsgTemplate) - free(WebMailMsgTemplate); - - WebMailMsgTemplate = GetTemplateFromFile(5, "WebMailMsg.txt"); - - *RLen = ViewWebMailMessage(Session, Reply, n, TRUE); - - return; - } - - if (strcmp(NodeURL, "/WebMail/WMPrev") == 0) - { - // Read Previous Message - - int m; - struct MsgInfo * Msg; - struct UserInfo * User = Session->User; - - - for (m = Session->WebMail->CurrentMessageIndex - 1; m >= 1; m--) - { - - Msg = GetMsgFromNumber(m); - - if (Msg == 0 || Msg->type == 0 || Msg->status == 0) - continue; // Protect against corrupt messages - - if (Msg && CheckUserMsg(Msg, User->Call, User->flags & F_SYSOP)) - { - // Display if it is the right type and in the page range we want - - if (Session->WebMailTypes[0] && strchr(Session->WebMailTypes, Msg->type) == 0) - continue; - - // All Types or right Type. Check Mine Flag - - if (Session->WebMailMine) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->to) != 0 && strcmp(User->Call, Msg->from) != 0) - continue; - } - - *RLen = ViewWebMailMessage(Session, Reply, m, TRUE); - - return; - } - } - - // No More - - *RLen = sprintf(Reply, "", Session->Key); - return; - - } - - if (strcmp(NodeURL, "/WebMail/WMNext") == 0) - { - // Read Previous Message - - int m; - struct MsgInfo * Msg; - struct UserInfo * User = Session->User; - - for (m = Session->WebMail->CurrentMessageIndex + 1; m <= LatestMsg; m++) - { - Msg = GetMsgFromNumber(m); - - if (Msg == 0 || Msg->type == 0 || Msg->status == 0) - continue; // Protect against corrupt messages - - if (Msg && CheckUserMsg(Msg, User->Call, User->flags & F_SYSOP)) - { - // Display if it is the right type and in the page range we want - - if (Session->WebMailTypes[0] && strchr(Session->WebMailTypes, Msg->type) == 0) - continue; - - // All Types or right Type. Check Mine Flag - - if (Session->WebMailMine) - { - // Only list if to or from me - - if (strcmp(User->Call, Msg->to) != 0 && strcmp(User->Call, Msg->from) != 0) - continue; - } - - *RLen = ViewWebMailMessage(Session, Reply, m, TRUE); - - return; - } - } - - // No More - - *RLen = sprintf(Reply, "", Session->Key); - return; - - } - - - if (strcmp(NodeURL, "/WebMail/DisplayText") == 0) - { - // Read Message - - int n = 0; - - if (URLParams) - n = atoi(URLParams); - - if (WebMailMsgTemplate) - free(WebMailMsgTemplate); - - WebMailMsgTemplate = GetTemplateFromFile(5, "WebMailMsg.txt"); - - *RLen = ViewWebMailMessage(Session, Reply, n, FALSE); - - return; - } - if (memcmp(NodeURL, "/WebMail/WMDel/", 15) == 0) - { - // Kill Message - - int n = atoi(&NodeURL[15]); - - *RLen = KillWebMailMessage(Reply, Session->Key, Session->User, n); - - return; - } - - if (_stricmp(NodeURL, "/WebMail/NewMsg") == 0) - { - // Add HTML Template Button if we have any HTML Form - - char Button[] = - "      " - ""; - - char Temp[1024]; - - FreeWebMailFields(Session->WebMail); // Tidy up for new message - - sprintf(Temp, Button, Key); - - if (FormDirCount == 0) - *RLen = sprintf(Reply, MsgInputPage, Key, "", "", "", ""); - else - *RLen = sprintf(Reply, MsgInputPage, Key, "", Temp, "", ""); - - return; - } - - if (_memicmp(NodeURL, "/WebMail/GetPage/", 17) == 0) - { - // Read and Parse Template File - - GetPage(Session, NodeURL); - return; - } - - if (_memicmp(NodeURL, "/WebMail/GetList/", 17) == 0) - { - // Send Select Template Popup - - char * SubDir; - int DirNo = 0; - int SubDirNo = 0; - char popup[10000]; - - char popuphddr[] = - - "" - "" - "

" - "Select Required Template from %s

" - "

", popup); - - *RLen = sprintf(Reply, "%s", popup); - return; - } - - if (_stricmp(NodeURL, "/WebMail/DL") == 0) - { - getAttachmentList(Session, Reply, RLen, URLParams); - return; - } - - if (_stricmp(NodeURL, "/WebMail/GetDownLoad") == 0) - { - DownloadAttachments(Session, Reply, RLen, URLParams); - return; - } - - if (_stricmp(NodeURL, "/WebMail/DoSelect") == 0) - { - // User has selected item from Template "; - - char NewGroup [] = - "" - "

", popup); - - *WebMail->RLen = sprintf(WebMail->Reply, "%s", popup); - - free(Boundary); - return; -} - -static char WinlinkAddr[] = "WINLINK.ORG"; - -VOID SaveNewMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest, int InputLen) -{ - int i, ReplyLen = 0; - struct MsgInfo * Msg; - FILE * hFile; - int Template=0; - char * via = NULL; - BIDRec * BIDRec; - char MsgFile[MAX_PATH]; - size_t WriteLen=0; - char * HDest; - char * HDestCopy; - char * HDestRest; - char * Vptr = NULL; - char * FileList = NULL; - char Prompt[256] = "Message Saved"; - char OrigTo[256]; - WebMailInfo * WebMail = Session->WebMail; - struct UserInfo * user; - CIRCUIT conn; - - // So we can have attachments input is now Content-Type: multipart/form-data; - - char * Input; - size_t MsgLen = 0; - char * Boundary; - - strcpy(conn.Callsign, Session->User->Call); - - Input = MsgPtr; - - Boundary = initMultipartUnpack(&Input); - - if (Boundary == NULL) - return; // Can't work without one - - // Input points to start of part. Normally preceeded by \r\n which is Boundary Terminator. If preceeded by -- we have used last part - - while(Input && Input[-1] != '-') - { - char * Name, * Value; - int ValLen; - - if (unpackPart(Boundary, &Input, &Name, &Value, &ValLen, MsgPtr + InputLen) == FALSE) - { - // ReportCorrupt(WebMail); - free(Boundary); - return; - } - if (SaveInputValue(WebMail, Name, Value, ValLen) == FALSE) - { - *RLen = sprintf(Reply, "", Session->Key); - return; - } - } - - - if (WebMail->txtFileName) - { - // Processing Form Input - - SaveTemplateMessage(Session, MsgPtr, Reply, RLen, Rest); - - // Prevent re-entry - - free(WebMail->txtFileName); - WebMail->txtFileName = NULL; - - return; - } - - // If we aren't using a template then all the information is in the WebMail fields, as we haven't been here before. - - strlop(WebMail->BID, ' '); - if (strlen(WebMail->BID) > 12) - WebMail->BID[12] = 0; - - UndoTransparency(WebMail->BID); - UndoTransparency(WebMail->To); - UndoTransparency(WebMail->Subject); - UndoTransparency(WebMail->Body); - - MsgLen = strlen(WebMail->Body); - - // We will need to mess about with To field. Create a copy so the original can go in B2 header if we use one - - if (WebMail->To[0] == 0) - { - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - } - - if (strlen(WebMail->To) > 255) - { - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - } - - HDest = _strdup(WebMail->To); - - if (strlen(WebMail->BID)) - { - if (LookupBID(WebMail->BID)) - { - // Duplicate bid - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - } - } - - if (WebMail->Type == 'B') - { - if (RefuseBulls) - { - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - } - } - - // ?? Can we just loop though the rest of the code to allow multiple dests ?? - - HDestCopy = HDest; - - while (HDest && HDest[0]) - { - HDestRest = strlop(HDest, ';'); - - Msg = AllocateMsgRecord(); - - // Set number here so they remain in sequence - - Msg->number = ++LatestMsg; - MsgnotoMsg[Msg->number] = Msg; - - strcpy(Msg->from, Session->User->Call); - - if (_memicmp(HDest, "rms:", 4) == 0 || _memicmp(HDest, "rms/", 4) == 0) - { - Vptr=&HDest[4]; - strcpy(Msg->to, "RMS"); - } - else if (_memicmp(HDest, "smtp:", 5) == 0) - { - if (ISP_Gateway_Enabled) - { - Vptr=&HDest[5]; - Msg->to[0] = 0; - } - } - else if (strchr(HDest, '@')) - { - strcpy(OrigTo, HDest); - - Vptr = strlop(HDest, '@'); - - if (Vptr) - { - // If looks like a valid email address, treat as such - - if (strlen(HDest) > 6 || !CheckifPacket(Vptr)) - { - // Assume Email address - - Vptr = OrigTo; - - if (FindRMS() || strchr(Vptr, '!')) // have RMS or source route - strcpy(Msg->to, "RMS"); - else if (ISP_Gateway_Enabled) - Msg->to[0] = 0; - else if (isAMPRMsg(OrigTo)) - strcpy(Msg->to, "RMS"); // Routing will redirect it - else - { - *RLen = sprintf(Reply, "%s", ""); - FreeWebMailFields(WebMail); // We will reprocess message and attachments so reinitialise - return; - - } - } - else - strcpy(Msg->to, _strupr(HDest)); - } - } - else - { - // No @ - - if (strlen(HDest) > 6) - HDest[6] = 0; - - strcpy(Msg->to, _strupr(HDest)); - } - - if (SendBBStoSYSOPCall) - if (_stricmp(HDest, BBSName) == 0) - strcpy(Msg->to, SYSOPCall); - - if (Vptr) - { - if (strlen(Vptr) > 40) - Vptr[40] = 0; - - strcpy(Msg->via, _strupr(Vptr)); - } - else - { - // No via. If not local user try to add BBS - - struct UserInfo * ToUser = LookupCall(Msg->to); - - if (ToUser) - { - // Local User. If Home BBS is specified, use it - - if (ToUser->flags & F_RMSREDIRECT) - { - // sent to Winlink - - strcpy(Msg->via, WinlinkAddr); - sprintf(Prompt, "Redirecting to winlink.org\r"); - } - else if (ToUser->HomeBBS[0]) - { - strcpy(Msg->via, ToUser->HomeBBS); - sprintf(Prompt, "%s added from HomeBBS. Message Saved", Msg->via); - } - } - else - { - // Not local user - Check WP - - WPRecP WP = LookupWP(Msg->to); - - if (WP) - { - strcpy(Msg->via, WP->first_homebbs); - sprintf(Prompt, "%s added from WP", Msg->via); - } - } - } - - if (strlen(WebMail->Subject) > 60) - WebMail->Subject[60] = 0; - - strcpy(Msg->title, WebMail->Subject); - Msg->type = WebMail->Type; - - if (Session->User->flags & F_HOLDMAIL) - { - int Length=0; - char * MailBuffer = malloc(100); - char Title[100]; - - Msg->status = 'H'; - - Length = sprintf(MailBuffer, "Message %d Held\r\n", Msg->number); - sprintf(Title, "Message %d Held - %s", Msg->number, "User has Hold Messages flag set"); - SendMessageToSYSOP(Title, MailBuffer, Length); - } - else - Msg->status = 'N'; - - if (strlen(WebMail->BID) == 0) - sprintf(Msg->bid, "%d_%s", LatestMsg, BBSName); - else - strcpy(Msg->bid, WebMail->BID); - - Msg->datereceived = Msg->datechanged = Msg->datecreated = time(NULL); - - BIDRec = AllocateBIDRecord(); - - strcpy(BIDRec->BID, Msg->bid); - BIDRec->mode = Msg->type; - BIDRec->u.msgno = LOWORD(Msg->number); - BIDRec->u.timestamp = LOWORD(time(NULL)/86400); - - Msg->length = (int)MsgLen + WebMail->HeaderLen + WebMail->FooterLen; - - sprintf_s(MsgFile, sizeof(MsgFile), "%s/m_%06d.mes", MailDir, Msg->number); - - // BuildFormMessage(Session, Msg); - - if (WebMail->Files) - { - // Send as B2 - - char * B2Header = BuildB2Header(WebMail, Msg, NULL, 0); - - hFile = fopen(MsgFile, "wb"); - - if (hFile) - { - WriteLen = fwrite(B2Header, 1, strlen(B2Header), hFile); - WriteLen += fwrite(WebMail->Header, 1, WebMail->HeaderLen, hFile); - WriteLen += fwrite(WebMail->Body, 1, MsgLen, hFile); - WriteLen += fwrite(WebMail->Footer, 1, WebMail->FooterLen, hFile); - WriteLen += fwrite("\r\n", 1, 2, hFile); - - for (i = 0; i < WebMail->Files; i++) - { - WriteLen += fwrite(WebMail->FileBody[i], 1, WebMail->FileLen[i], hFile); - WriteLen += fwrite("\r\n", 1, 2, hFile); - } - fclose(hFile); - free(B2Header); - - Msg->length = (int)WriteLen; - } - } - else - { - hFile = fopen(MsgFile, "wb"); - - if (hFile) - { - WriteLen += fwrite(WebMail->Header, 1, WebMail->HeaderLen, hFile); - WriteLen += fwrite(WebMail->Body, 1, MsgLen, hFile); - WriteLen += fwrite(WebMail->Footer, 1, WebMail->FooterLen, hFile); - fclose(hFile); - } - } - MatchMessagetoBBSList(Msg, &conn); - - BuildNNTPList(Msg); // Build NNTP Groups list - - if (EnableUI) - SendMsgUI(Msg); - - user = LookupCall(Msg->to); - - if (user && (user->flags & F_APRSMFOR)) - { - char APRS[128]; - char Call[16]; - int SSID = user->flags >> 28; - - if (SSID) - sprintf(Call, "%s-%d", Msg->to, SSID); - else - strcpy(Call, Msg->to); - - sprintf(APRS, "New BBS Message %s From %s", Msg->title, Msg->from); - APISendAPRSMessage(APRS, Call); - } - - HDest = HDestRest; - } - - *RLen = SendWebMailHeaderEx(Reply, Session->Key, Session, Prompt); - - SaveMessageDatabase(); - SaveBIDDatabase(); - FreeWebMailFields(WebMail); - free(HDestCopy); - - return; -} - - - - - - -// RMS Express Forms Support - -char * GetHTMLViewerTemplate(char * FN) -{ - int i, j, k, l; - - // Seach list of forms for base file (without .html) - - for (i = 0; i < FormDirCount; i++) - { - struct HtmlFormDir * Dir = HtmlFormDirs[i]; - - for (j = 0; j < Dir->FormCount; j++) - { - if (strcmp(FN, Dir->Forms[j]->FileName) == 0) - { - return CheckFile(Dir, FN); - } - } - - if (Dir->DirCount) - { - for (l = 0; l < Dir->DirCount; l++) - { - for (k = 0; k < Dir->Dirs[l]->FormCount; k++) - { - if (strcmp(FN, Dir->Dirs[l]->Forms[k]->FileName) == 0) - { - return CheckFile(Dir, Dir->Dirs[l]->Forms[k]->FileName); - } - } - } - } - } - - return NULL; -} -VOID GetReply(struct HTTPConnectionInfo * Session, char * NodeURL) -{ -} - -VOID GetPage(struct HTTPConnectionInfo * Session, char * NodeURL) -{ - // Read the HTML Template file and do any needed substitutions - - WebMailInfo * WebMail = Session->WebMail; - KeyValues * txtKey = WebMail->txtKeys; - - int DirNo; - char * ptr; - int FileNo = 0; - char * SubDir; - int SubDirNo; - int i; - struct HtmlFormDir * Dir; - char * Template; - char * inptr; - char FormDir[MAX_PATH] = ""; - char FN[MAX_PATH] = ""; - char * InputName = NULL; // HTML to input message - char * ReplyName = NULL; - char * To = NULL; - char * CC = NULL; - char * BID = NULL; - char Type = 0; - char * Subject = NULL; - char * MsgBody = NULL; - char * varptr; - char * endptr; - size_t varlen, vallen = 0; - char val[256]=""; // replacement text - char var[100] = "\""; - char * MsgBytes; - char Submit[64]; - - if (NodeURL == NULL) - { - //rentry after processing or substitutions - - // if Dir not specified search all for Filename - - if (Dir == NULL) - { - for (i = 0; i < FormDirCount; i++) - { - int n; - - Dir = HtmlFormDirs[i]; - - MsgBytes = CheckFile(Dir, WebMail->txtFileName); - if (MsgBytes) - goto gotFile; - - // Recurse any Subdirs - - n = 0; - while (n < Dir->DirCount) - { - MsgBytes = CheckFile(Dir->Dirs[n], FN); - if (MsgBytes) - { - Dir = Dir->Dirs[n]; - goto gotFile; - } - n++; - } - } - return; - } - else - MsgBytes = CheckFile(Dir, WebMail->txtFileName); - -gotFile: - - WebMail->Dir = Dir; - - if (WebMail->txtFile) - free(WebMail->txtFile); - - WebMail->txtFile = MsgBytes; - -reEnter: - - if (ParsetxtTemplate(Session, Dir, WebMail->txtFileName, FALSE) == FALSE) - { - // Template has or - - if (WebMail->InputHTMLName == NULL) - { - // This is a plain text template without HTML -/* - if (To == NULL) - To = ""; - - if (To[0] == 0 && WebMail->To && WebMail->To[0]) - To = WebMail->To; - - if (CC == NULL) - CC = ""; - - if (CC[0] == 0 && WebMail->CC && WebMail->CC[0]) - CC = WebMail->CC; - - if (Subject == NULL) - Subject = ""; - - if (Subject[0] == 0 && WebMail->Subject && WebMail->Subject[0]) - Subject = WebMail->Subject; - - if (MsgBody == NULL) - MsgBody = ""; - - if (MsgBody[0] == 0 && WebMail->Body && WebMail->Body[0]) - MsgBody = WebMail->Body; - - *WebMail->RLen = sprintf(WebMail->Reply, CheckFormMsgPage, Session->Key, To, CC, Subject, MsgBody); - */ - return *WebMail->RLen; - } - - Template = CheckFile(WebMail->Dir, WebMail->InputHTMLName); - - if (Template == NULL) - { - // Missing HTML - - *WebMail->RLen = sprintf(WebMail->Reply, "", WebMail->InputHTMLName); - return *WebMail->RLen; - } - - // I've going to update the template in situ, as I can't see a better way - // of making sure all occurances of variables in any order are substituted. - // The space allocated to Template is twice the size of the file - // to allow for insertions - - UpdateFormAction(Template, Session->Key); // Update "Submit" Action - - // Search for "{var }" strings in form and replace with - // corresponding variable from XML - - while (txtKey->Key) - { - char Key[256] = "{var "; - - strcpy(&Key[5], txtKey->Key); - strcat(Key, "}"); - - inptr = Template; - varptr = stristr(inptr, Key); - - while (varptr) - { - // Move the remaining message up/down the buffer to make space for substitution - - varlen = (int)strlen(Key); - if (txtKey->Value) - vallen = (int)strlen(txtKey->Value); - else vallen = 0; - - endptr = varptr + varlen; - - memmove(varptr + vallen, endptr, strlen(endptr) + 1); // copy null on end - memcpy(varptr, txtKey->Value, vallen); - - inptr = endptr + 1; - - varptr = stristr(inptr, Key); - } - txtKey++; - } - - // Remove from end as we add it on later - - ptr = stristr(Template, ""); - - if (ptr) - *ptr = 0; - - Len = sprintf(Reply, "%s", Template); - free(Template); - return Len; -} - -char * CheckFile(struct HtmlFormDir * Dir, char * FN) -{ - struct stat STAT; - FILE * hFile; - char MsgFile[MAX_PATH]; - char * MsgBytes; - int ReadLen; - int FileSize; - -#ifndef WIN32 - - // Need to do case insensitive file search - - DIR *dir; - struct dirent *entry; - char name[256]; - - sprintf(name, "%s/%s/%s", BPQDirectory, Dir->FormSet, Dir->DirName); - - if (!(dir = opendir(name))) - { - Debugprintf("cant open forms dir %s %s %d", Dir->DirName, name, errno); - return 0; - } - - while ((entry = readdir(dir)) != NULL) - { - if (entry->d_type == DT_DIR) - continue; - - if (stricmp(entry->d_name, FN) == 0) - { - sprintf(MsgFile, "%s/%s/%s/%s", GetBPQDirectory(), Dir->FormSet, Dir->DirName, entry->d_name); - break; - } - } - closedir(dir); - -#else - - sprintf(MsgFile, "%s/%s/%s/%s", GetBPQDirectory(), Dir->FormSet, Dir->DirName, FN); - -#endif - - if (stat(MsgFile, &STAT) != -1) - { - hFile = fopen(MsgFile, "rb"); - - if (hFile == 0) - { - MsgBytes = _strdup("File is missing"); - return MsgBytes; - } - - FileSize = STAT.st_size; - MsgBytes = malloc(FileSize * 10); // Allow plenty of room for template substitution - ReadLen = (int)fread(MsgBytes, 1, FileSize, hFile); - MsgBytes[FileSize] = 0; - fclose(hFile); - - return MsgBytes; - } - return NULL; -} - -BOOL DoSelectPrompt(struct HTTPConnectionInfo * Session, char * Select) -{ - // Send a Popup window to select value. Reply handling code will update template then reenter ParsetxtTemplate - - char popuphddr[] = - - "" - "" - "
%s

" - "" - "
'); - - if (ptr) - *ptr = 0; - - ptr = SelCopy; - - if (*ptr == '"') - { - // String has " " round it - - ptr++; - - ptr1 = strchr(ptr, '"'); - if (ptr1 == NULL) - goto returnDuff; - - *(ptr1++) = 0; - prompt = ptr; - } - else - { - // Normal comma terminated - - ptr1 = strchr(ptr, ','); - if (ptr1 == NULL) - goto returnDuff; - - *(ptr1++) = 0; - prompt = ptr; - } - - ptr = ptr1; - - while (ptr && ptr[0]) - { - if (*ptr == '"') - { - // String has " " round it - - ptr++; - - ptr1 = strchr(ptr, '"'); - if (ptr1 == NULL) - goto returnDuff; - - *(ptr1++) = 0; - while(ptr1 && *ptr1 == ',') - ptr1++; - } - else - { - // Normal comma terminated - - ptr1 = strchr(ptr, ','); - if (ptr1) - *(ptr1++) = 0; - } - - var[vars++] = ptr; - - ptr = ptr1; - } - - sprintf(popup, popuphddr, Session->Key, prompt, vars + 1); - - for (i = 0; i < vars; i++) - { - char * key = strlop(var[i], '='); - - if (key == NULL) - key = var[i]; - - sprintf(popup, "%s

", popup); - - *WebMail->RLen = sprintf(WebMail->Reply, "%s", popup); - free(SelCopy); - return TRUE; - -returnDuff: - *WebMail->RLen = sprintf(WebMail->Reply, "", Session->Key); - free(SelCopy); - return TRUE; - -} - -BOOL DoAskPrompt(struct HTTPConnectionInfo * Session, char * Select) -{ - return TRUE; -} - -VOID ProcessSelectResponse(struct HTTPConnectionInfo * Session, char * URLParams) -{ - // User has entered a response for a Template RLen = sprintf(WebMail->Reply, "", Session->Key); - return; - } - - varptr = Select; - endptr = strchr(Select, '>'); - - if (endptr == NULL) - { - *WebMail->RLen = sprintf(WebMail->Reply, "", Session->Key); - return; - } - - *endptr = 0; - varlen = endptr - varptr; - - - valptr = URLParams; - - // Move the remaining message up/down the buffer to make space for substitution - - vallen = strlen(valptr); - - endptr = varptr + varlen; - - memcpy(varptr, valptr, vallen); - memmove(varptr + vallen, endptr + 1, strlen(endptr + 1) + 1); // copy null on end - - if (WebMail->isReply) - *WebMail->RLen = ReplyToFormsMessage(Session, Session->Msg, WebMail->Reply, TRUE); - else - GetPage(Session, NULL); - - return ; -} - -BOOL ParsetxtTemplate(struct HTTPConnectionInfo * Session, struct HtmlFormDir * Dir, char * FN, BOOL isReply) -{ - WebMailInfo * WebMail = Session->WebMail; - KeyValues * txtKey = WebMail->txtKeys; - - char * MsgBytes; - - char * txtFile; - char * ptr, *ptr1; - char * InputName = NULL; // HTML to input message - char * ReplyName = NULL; - char * To = NULL; - char * Subject = NULL; - char * MsgBody = NULL; - char * Select = NULL; - char * Ask = NULL; - - char Date[16]; - char UDate[16]; - char DateTime[32]; - char UDateTime[32]; - char Day[16]; - char UDay[16]; - char UDTG[32]; - char Seq[16]; - char FormDir[MAX_PATH]; - double Lat; - double Lon; - char LatString[32], LonString[32], GPSString[32]; - BOOL GPSOK; - - struct tm * tm; - time_t NOW; - - // Template is now read before entering here - - MsgBytes = WebMail->txtFile; - - // if Template uses tm_year + 1900,tm->tm_mon + 1, tm->tm_mday); - - sprintf(DateTime, "%04d-%02d-%02d %02d:%02d:%02d", - tm->tm_year + 1900,tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - - strcpy(Day, longday[tm->tm_wday]); - - tm = gmtime(&NOW); - - sprintf(UDate, "%04d-%02d-%02dZ", - tm->tm_year + 1900,tm->tm_mon + 1, tm->tm_mday); - - sprintf(UDateTime, "%04d-%02d-%02d %02d:%02d:%02dZ", - tm->tm_year + 100,tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - - sprintf(UDTG, "%02d%02d%02dZ %s %04d", - tm->tm_mday, tm->tm_hour, tm->tm_min, month[tm->tm_mon], tm->tm_year + 1900); - - strcpy(UDay, longday[tm->tm_wday]); - - sprintf(Seq, "%d", Session->User->WebSeqNo); - sprintf(FormDir, "/WebMail/WMFile/%s/%s/", WebMail->Dir->FormSet, WebMail->Dir->DirName); - - // Keep SeqNo at front - - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(Seq); - - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(DateTime); - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(UDateTime); - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(Date); - txtKey->Key = _strdup(""); - txtKey++->Value = _strdup(UDate); - txtKey->Key = _strdup("