diff --git a/docs/AGWPE_TCP_IP_API.md b/docs/AGWPE_TCP_IP_API.md index e691175..55112e4 100644 --- a/docs/AGWPE_TCP_IP_API.md +++ b/docs/AGWPE_TCP_IP_API.md @@ -1,1492 +1,806 @@ - - - - #### AGWPE TCP/IP API Tutorial - - **by Ing. Pedro E. Colla (LU7DID) and George Rossopoulos (SV2AGW)** - - -*Last Revised* *December 12, 2000* +_Last Revised_ _December 12, 2000_ ##### Copyright © P.E. Colla (LU7DID) and G.Rossopoulos (SV2AGW) 2000 - - - - # Abstract - +The AGW Packet Engine (**\*AGWPE\***) by George Rossopoulos (**\*SV2AGW\***) is a powerful AX.25 Layer 2 Manager running under Windows 95/98/NT as a “state-of-the-art” 32 bits application. - +At this time **\*AGWPE\*** supports two completely different APIs; one based in DDE (Dynamic Data Exchange) which is the first implemented and another based on TCP/IP which has been introduced recently. -The AGW Packet Engine (***AGWPE\***) by George Rossopoulos (***SV2AGW\***) is a powerful AX.25 Layer 2 Manager running under Windows 95/98/NT as a “state-of-the-art” 32 bits application. +This document would concentrate on the TCP/IP API, the intended audience for it are application programmers looking for information on how to write (or adapt) their programs to take advantage of the **\*AGWPE\*** services. - - -At this time ***AGWPE\*** supports two completely different APIs; one based in DDE (Dynamic Data Exchange) which is the first implemented and another based on TCP/IP which has been introduced recently. - - - -This document would concentrate on the TCP/IP API, the intended audience for it are application programmers looking for information on how to write (or adapt) their programs to take advantage of the ***AGWPE\*** services. - - - -The information provided in this document is valid as per ***AGWPE\*** Version 2000.20 or higher; previous versions might not support some of the functions so checking the release information is necessary; it’s likely that future versions would be backward compatible unless documented otherwise. - - - - - - - -# Table of Contents - - - -[Abstract](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723768) - -[Table of Contents](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723769) - -[Overview](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723770) - -[Communicating with AGWPE using the TCP/IP API](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723771) - -[Enabling](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723772) - -[AGWPE GUI](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723773) - -[AGWPE.INI](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723774) - -[Communications](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723775) - -[API Application Interface Security](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723776) - -[TCP/IP Exchange](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723777) - -[AGWPE API Reference](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723778) - -[Frame Structure](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723779) - -[Frames sent by the Application to AGWPE](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723780) - -[Application Login (‘P’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723781) - -[Register CallSign (‘X’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723782) - -[Unregister CallSign (‘x’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723783) - -[Ask Port Information (‘G’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723784) - -[Enable Reception of Monitoring Frames (‘m’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723785) - -[AGWPE Version Info (‘R’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723786) - -[Ask Port Capabilities (‘g’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723787) - -[Callsign Heard on a Port (‘H’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723788) - -[Ask Outstanding frames waiting on a Port (‘y’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723789) - -[Ask Outstanding frames waiting for a connection (‘Y’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723790) - -[Send UNPROTO Information (‘M’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723791) - -[Connect, Start an AX.25 Connection (‘C’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723792) - -[Send Connected Data (‘D’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723793) - -[Disconnect, Terminate an AX.25 Connection (‘d’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723794) - -[Connect VIA, Start an AX.25 circuit thru digipeaters (‘v’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723795) - -[Send UNPROTO VIA (‘V’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723796) - -[Non-Standard Connections, Connection with PID (‘c’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723797) - -[Send Data in “raw” AX.25 format (‘K’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723798) - -[Activate reception of Frames in “raw” format (‘k’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723799) - -[Frames Sent by AGWPE to the Application](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723800) - -[Version Number (‘R’ frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723801) - -[Callsign Registration (‘X’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723802) - -[Port Information (‘G’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723803) - -[Capabilities of a Port (‘g’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723804) - -[Frames Outstanding on a Port (‘y’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723805) - -[Frames Outstanding on a Connection (‘Y’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723806) - -[Heard Stations on a Port (‘H’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723807) - -[AX.25 Connection Received (‘C’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723808) - -[Connected AX.25 Data (‘D’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723809) - -[Monitored Connected Information (‘I’ Frame)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723810) - -[Monitored Supervisory Information (‘S’ Frames)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723811) - -[Monitored Unproto Information (‘U’ Frames)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723812) - -[Monitoring Own Information (‘T’ Frames)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723813) - -[Monitored Information in Raw Format (‘K’ Frames)](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723814) - -[Frame Cross-Reference](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723815) - -[Programming Hints, Tips and Techniques](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723816) - -[Programming Language](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723817) - -[Talking with AGWPE](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723818) - -[Using C++](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723819) - -[Using Delphi4/5](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723820) - -[Overall Communication Cycle](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723821) - -[Frames Fiesta](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723822) - -[Sending Frames](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723823) - -[Receive Frames](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723824) - -[Format VIA Areas](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723825) - -[Parsing Port Information](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723826) - -[Port Capabilities](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723827) - -[Heard Information for a Port](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723828) - -[Raw Frames](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723829) - -[Tracking Frames](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723830) - -[Managing Connections](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723831) - -[One Callsign, Many Connections](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723832) - -[Many CallSigns, Many Connections](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723833) - -[Down the Tubes, Climb the Ladder](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723834) - -[Credits and other stuff](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_Toc500723835) - - - - - - +The information provided in this document is valid as per **\*AGWPE\*** Version 2000.20 or higher; previous versions might not support some of the functions so checking the release information is necessary; it’s likely that future versions would be backward compatible unless documented otherwise. # Overview - +As an AX.25 Layer 2 (L2 for short) Manager it could control a huge number of AX.25 devices such as many TNC models (most of the commonly used), BayCom modems (most incarnations), quite a few really specialized high speed modems and the SoundBlaster card as a Packet device, **\*AGWPE\*** also provides an special “internal” port called loopback that could be used to interchange information among different applications running under the same **\*AGWPE\*** or (very useful) for test purposes; moreover, an almost unlimited number of them could be used at the **same** time each one being a “**port**” (well, sort of, George claims a maximum number of 100 ports, which is “unlimited” under every stretch of the concept). -As an AX.25 Layer 2 (L2 for short) Manager it could control a huge number of AX.25 devices such as many TNC models (most of the commonly used), BayCom modems (most incarnations), quite a few really specialized high speed modems and the SoundBlaster card as a Packet device, ***AGWPE\*** also provides an special “internal” port called loopback that could be used to interchange information among different applications running under the same ***AGWPE\*** or (very useful) for test purposes; moreover, an almost unlimited number of them could be used at the **same** time each one being a “**port**” (well, sort of, George claims a maximum number of 100 ports, which is “unlimited” under every stretch of the concept). - - - -As a manager, ***AGWPE\*** is not functional per-se, meaning, the end user **need** to have it loaded but doesn’t make any direct **use** of it other than to configure it or to get a glimpse of the current status of the different AX.25 links and ports. - - +As a manager, **\*AGWPE\*** is not functional per-se, meaning, the end user **need** to have it loaded but doesn’t make any direct **use** of it other than to configure it or to get a glimpse of the current status of the different AX.25 links and ports. What uses the AGW Packet Engine are **applications** enabled to talk with it which in turn are used by end users to sustain activity over Packet Radio. - +**\*AGWPE\*** comes with a basic “suite” of applications comprising a Packet Terminal program (AGWTerm), a monitor program (AGWMonitor), a mail client (AGWBBS/AGWFWD), a cluster program (AGWCLU) and a digipeater (AGWDigipeater), all of them written by George (**\*SV2AGW\***); this suite is a complete albeit somewhat limited set for any end-user to sustain Packet operations. -***AGWPE\*** comes with a basic “suite” of applications comprising a Packet Terminal program (AGWTerm), a monitor program (AGWMonitor), a mail client (AGWBBS/AGWFWD), a cluster program (AGWCLU) and a digipeater (AGWDigipeater), all of them written by George (***SV2AGW\***); this suite is a complete albeit somewhat limited set for any end-user to sustain Packet operations. +A growing number of third party applications are starting to support the **\*AGWPE\*** also either directly (i.e.WinPack) or thru additional libraries (Tsthwin, WinFBB,etc); a fair number of authors had announced the future support of this platform with new versions of their programs. - - -A growing number of third party applications are starting to support the ***AGWPE\*** also either directly (i.e.WinPack) or thru additional libraries (Tsthwin, WinFBB,etc); a fair number of authors had announced the future support of this platform with new versions of their programs. - - - -The applications would see the ***AGWPE\*** as a provider of services, those services are accessed thru a set of conventions named collectively the **Application Program Interface (API)**. - - +The applications would see the **\*AGWPE\*** as a provider of services, those services are accessed thru a set of conventions named collectively the **Application Program Interface (API)**. The application request services thru blocks of information called API Frames (or Frames, for short, but don’t confuse them with AX.25 L2 Frames), those blocks are just a chunk of data with a predefined length and contents. - - The frames are always composed by a section named header (36 bytes long) and depending on the action required another section named data (any length). - +Frames could be generated for the application and sent to **\*AGWPE\*** to request an specific service (such as sending data or to configure a particular aspect of the **\*AGWPE\*** functional behaviour or to require information about the current status). -Frames could be generated for the application and sent to ***AGWPE\*** to request an specific service (such as sending data or to configure a particular aspect of the ***AGWPE\*** functional behaviour or to require information about the current status). +**\*AGWPE\*** could, in turn, send also frames to the application; either as an answer to a given service (i.e. query of some value) or as an unsolicited block of information (i.e. a block of data just received at some port). - - -***AGWPE\*** could, in turn, send also frames to the application; either as an answer to a given service (i.e. query of some value) or as an unsolicited block of information (i.e. a block of data just received at some port). - - - -Both the frames sent to ***AGWPE\*** by the application and the frames sent by ***AGWPE\*** to the application has the same format. - - - - +Both the frames sent to **\*AGWPE\*** by the application and the frames sent by **\*AGWPE\*** to the application has the same format. # Communicating with AGWPE using the TCP/IP API - - ## Enabling - - The TCP/IP API must be enabled to be functional, the default API for AGWPE still is the old DDE based. - - There are basicall two ways to enable the TCP/IP API, thru the AGWPE GUI or modifying the AGWPE.INI configuration file. - - Both methods would be useful, the AGWPE GUI for manual configurations while the AGWPE.INI modification could be seen more appropriate for automatic setups. - - ### AGWPE GUI - - Upon loading click on the AGWPE icon at the task bar, go to the “Setup Interfaces” entry and on the “WinSock Interface Security” tab be sure the menu item “Enable Winsock TCP/IP Application Interface” is checked, verify which is the TCP Port where AGWPE listen for applications (should be 8000 unless you changed it). - - Once checked the change would be Accepted to be effective. ### AGWPE.INI - - -The following entry has to be added on the configuration file ***AGWPE\***.INI (usually at the same directory than the executable). - - +The following entry has to be added on the configuration file **\*AGWPE\***.INI (usually at the same directory than the executable). [TCPIPINTERCONNECT] ENABLE=1 - +Without this entry **\*AGWPE\*** will not operate with the TCP/IP API, it is recommended that an application program willing to use the TCP/IP API should check this configuration value to ensure it is set properly and either set it directly or provide instructions to the end-user on the need to set it as a part of the installation. -Without this entry ***AGWPE\*** will not operate with the TCP/IP API, it is recommended that an application program willing to use the TCP/IP API should check this configuration value to ensure it is set properly and either set it directly or provide instructions to the end-user on the need to set it as a part of the installation. +**\*AGWPE\*** doesn’t provide a way to activate the TCP/IP API thru any of the GUI dialogs, so the entry on the _AGWPE.INI_ must be configured and it is the only way to activate the TCP/IP API. - - -***AGWPE\*** doesn’t provide a way to activate the TCP/IP API thru any of the GUI dialogs, so the entry on the *AGWPE.INI* must be configured and it is the only way to activate the TCP/IP API. - - - -***AGWPE\*** reads this information only at startup, so for any change to be made effective the program has to be stopped and started. - - +**\*AGWPE\*** reads this information only at startup, so for any change to be made effective the program has to be stopped and started. ## Communications - +When starting with this configuration **\*AGWPE\*** starts to serve the TCP/IP port 8000 for incoming requests from applications, see the previous section (AGWPE GUI) on how to change it.. -When starting with this configuration ***AGWPE\*** starts to serve the TCP/IP port 8000 for incoming requests from applications, see the previous section (AGWPE GUI) on how to change it.. +Every application would start as many TCP/IP connections (sockets) with the **\*AGWPE\*** as required (usually one will be enough), multiple applications could have open connections with **\*AGWPE\*** at the same time; the limit on the number of sockets or connections **\*AGWPE\*** could sustain is defined by the TCP/IP stack of the machine where **\*AGWPE\*** is running (every socket “tax” the system resources, mostly in terms of memory and CPU cycles, till eventually no additional sockets could be opened). - +On machines with a modern configuration this limit is not easily achievable under practical uses; **\*AGWPE\*** itself is extremely efficient in terms of the memory used and CPU cycles taken by itself([[1\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn1)). -Every application would start as many TCP/IP connections (sockets) with the ***AGWPE\*** as required (usually one will be enough), multiple applications could have open connections with ***AGWPE\*** at the same time; the limit on the number of sockets or connections ***AGWPE\*** could sustain is defined by the TCP/IP stack of the machine where ***AGWPE\*** is running (every socket “tax” the system resources, mostly in terms of memory and CPU cycles, till eventually no additional sockets could be opened). +Each application is a typical TCP/IP client, as usually referred to in the bibliography, while **\*AGWPE\*** itself is a TCP/IP server. - +In order to open a socket the application should start a TCP/IP connection to the IP address of the machine where **\*AGWPE\*** is running and the TCP Port 8000. -On machines with a modern configuration this limit is not easily achievable under practical uses; ***AGWPE\*** itself is extremely efficient in terms of the memory used and CPU cycles taken by itself([[1\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn1)). +One of the very powerful aspects of the TCP/IP API is the fact that no restriction bounds the application and **\*AGWPE\*** to be run on the same machine, as long as a TCP/IP connection could be established the **\*AGWPE\*** and the Application program could be run on the same machine, on close machines operating in some LAN or half a world appart. - +The traffic (amount of data transferred between **\*AGWPE\*** and the Application) is quite substantial indeed, in order to achieve reasonable performance the bandwidth between **\*AGWPE\*** and the Application (each application) should be in the order of 3 to 4 times the combined bandwidth of all the AX.25 ports being serviced, this could be served in excess either running **\*AGWPE\*** and the application on the same machine or being linked by some Ethernet or TokenRing LAN (typical speeds between 10 and 100 Mbps), dial-up connections might be marginal depending on the total load planned to be serviced([[2\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn2)). -Each application is a typical TCP/IP client, as usually referred to in the bibliography, while ***AGWPE\*** itself is a TCP/IP server. +An interesting (theoretical) possiblity is to run **\*AGWPE\*** and an application program being appart and linked thru Packet Radio (TCP/IP over AX.25), albeit most current networks won’t have enough speed to provide even a minimum functionality in real world terms. - +In order for the TCP/IP communication to be established the IP Address of the machine where **\*AGWPE\*** is running is assumed to be known (this is a pre-requisite), the TCP port is as stated usually 8000. -In order to open a socket the application should start a TCP/IP connection to the IP address of the machine where ***AGWPE\*** is running and the TCP Port 8000. +The IP address of the machine could be easily obtained with the Windows utility named **\*winipcfg\***, in case the machine has many adapters (each one eventually having one different IP address) you could use the one associated with the adapter that could “see” the machine running **\*AGWPE\***. - - -One of the very powerful aspects of the TCP/IP API is the fact that no restriction bounds the application and ***AGWPE\*** to be run on the same machine, as long as a TCP/IP connection could be established the ***AGWPE\*** and the Application program could be run on the same machine, on close machines operating in some LAN or half a world appart. - - - -The traffic (amount of data transferred between ***AGWPE\*** and the Application) is quite substantial indeed, in order to achieve reasonable performance the bandwidth between ***AGWPE\*** and the Application (each application) should be in the order of 3 to 4 times the combined bandwidth of all the AX.25 ports being serviced, this could be served in excess either running ***AGWPE\*** and the application on the same machine or being linked by some Ethernet or TokenRing LAN (typical speeds between 10 and 100 Mbps), dial-up connections might be marginal depending on the total load planned to be serviced([[2\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn2)). - - - -An interesting (theoretical) possiblity is to run ***AGWPE\*** and an application program being appart and linked thru Packet Radio (TCP/IP over AX.25), albeit most current networks won’t have enough speed to provide even a minimum functionality in real world terms. - - - -In order for the TCP/IP communication to be established the IP Address of the machine where ***AGWPE\*** is running is assumed to be known (this is a pre-requisite), the TCP port is as stated usually 8000. - - - -The IP address of the machine could be easily obtained with the Windows utility named ***winipcfg\***, in case the machine has many adapters (each one eventually having one different IP address) you could use the one associated with the adapter that could “see” the machine running ***AGWPE\***. - - - -In the case the application and ***AGWPE\*** runs on the same machine the definition of the IP address becomes trivial since the IP loopback address (***127.0.0.1\***) should be always used; since most of the time ***AGWPE\*** and the application will be run on the same machine the loopback IP address should be the one used by the application by default[[3\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn3) - - +In the case the application and **\*AGWPE\*** runs on the same machine the definition of the IP address becomes trivial since the IP loopback address (**\*127.0.0.1\***) should be always used; since most of the time **\*AGWPE\*** and the application will be run on the same machine the loopback IP address should be the one used by the application by default[[3\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn3) ## API Application Interface Security - - Starting on version 2000.78 AGWPE brings security features that must be taken into account, the behaviour of the security model is controlled by the settings at the “WinSock Interface Security” tab on the “Interface Setup” menu entry. - - - - - - - AGWPE allows applications to be: - Local only (entry “Accept only from MyComputer”. - Intranet only (entry “Accept Only From MyLAN (standard)”. - Internet (entry “Accept from Anywhere”). - Applications could override the default security setting as stated above by means of sending an special “login” frame. - - - - Be aware that if the application is being ran from a machine that doesn’t comply with the security setting it has to provide a frame of type “P” to be able to interact with AGWPE, more on this later. - - This security model allows flexibility to make visible a node to a big (uncontrolled) environment such as the Internet and still enable the system operator to control who is using his resources. - - ## TCP/IP Exchange - - The basics on how to program using TCP/IP are far beyond the scope of this document to explain, however, TCP/IP is a technology so pervasive and widely used that no modern language intended for the Windows environment lacks support for it. - - -Usually this support is in the form of a set of calls (the TCP/IP API or the programming conventions to use TCP/IP, do not get confused with the ***AGWPE\*** TCP/IP API which is the way to communicate with ***AGWPE\*** using TCP/IP). - - +Usually this support is in the form of a set of calls (the TCP/IP API or the programming conventions to use TCP/IP, do not get confused with the **\*AGWPE\*** TCP/IP API which is the way to communicate with **\*AGWPE\*** using TCP/IP). The implementation varies from programming language to programming language, and even within them there are often many alternative implementations based on different vendors. - +TCP/IP programming could be a mind boggling exercise at its limits, fortunately only a subset of all the functions are needed to establish and maintain a successful connection with **\*AGWPE\*** under most circumstances. -TCP/IP programming could be a mind boggling exercise at its limits, fortunately only a subset of all the functions are needed to establish and maintain a successful connection with ***AGWPE\*** under most circumstances. +Communications with **\*AGWPE\*** will use TCP sockets only, so on most implementations of TCP/IP you would require to use just 3 API calls: - - -Communications with ***AGWPE\*** will use TCP sockets only, so on most implementations of TCP/IP you would require to use just 3 API calls: - - - -- A call to *OPEN* a socket. -- A call to *SEND* information thru an opened socket (usually a binary block of data). -- A call to *CLOSE* the socket upon termination. - - +- A call to _OPEN_ a socket. +- A call to _SEND_ information thru an opened socket (usually a binary block of data). +- A call to _CLOSE_ the socket upon termination. Your program would also need to handle a minimum of 3 events related to an open socket: - - - An event confirming the socket has been opened. - An event informing when some error occurs. -- An event informing data had arrived from ***AGWPE\*** and it’s available for processing (usually a block of data). - - +- An event informing data had arrived from **\*AGWPE\*** and it’s available for processing (usually a block of data). Depending on the language and the library the above basic elements might vary, through this document all techniques would be explained conceptually based on this set. - +The sequence of a dialog between an application and **\*AGWPE\*** always steps thru the following major activities: -The sequence of a dialog between an application and ***AGWPE\*** always steps thru the following major activities: - - - -- A TCP/IP socket is established with ***AGWPE\***, errors in this process must be handled. -- Some initial interchange of information with ***AGWPE\*** in order to get or set configurations. +- A TCP/IP socket is established with **\*AGWPE\***, errors in this process must be handled. +- Some initial interchange of information with **\*AGWPE\*** in order to get or set configurations. - The AX.25 activity itself (send and receive data+status). -- Some final configuration clean-up between the application and ***AGWPE\***. +- Some final configuration clean-up between the application and **\*AGWPE\***. - The TCP/IP socket is closed. - - - - - - - - - - # AGWPE API Reference - - ## Frame Structure - +Information between **\*AGWPE\*** and the application flows in both directions using an overall format composed by a header (fixed) and a variable data area depending on the particular frame being sent (many frames are just formed by a header). -Information between ***AGWPE\*** and the application flows in both directions using an overall format composed by a header (fixed) and a variable data area depending on the particular frame being sent (many frames are just formed by a header). - - - - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | [0..n] the least significant value comes in the first byte while the most significant in the second. I.E. Port 2 would be expressed as0x01 ([[4\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn4)) | -| Reserved | 3 Bytes | Usually 0x00 0x00 0x00 | -| DataKind | 1 Byte | Is the frame code, reflects the purpose of the frame. The meaning of the DataKind DO VARY depending on whether the frame flows from the application to ***AGWPE\*** or viceversa. | -| Reserved | 1 Byte | Usually 0x00 | -| PID | 1 Byte | Frame PID, it’s usage is valid only under certain frames only. Should be 0x00 when not used. | -| Reserved | 1 Byte | Usually 0x00 | -| CallFrom | 10 Bytes | CallSign FROM of the packet, in ASCII, using the format {CALLSIGN}-{SSID}(i.e. ***LU7DID\***-8)it is “null terminated” (it ends with 0x00). ([[5\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn5))The field ALWAYS is 10 bytes long.It’s filled on packets where it has some meaning. | -| CallTo | 10 Bytes | CallSign TO of the packet, same as above. | -| DataLen | 4 Bytes | Data Length as a 32 bits unsigned integer.If zero means no data follows the header. | -| User (Reserved) | 4 Bytes | 32 bits unsigned integer, not used. Reserved for future use. | - - +| Field | Length | Meaning | +| ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | [0..n] the least significant value comes in the first byte while the most significant in the second. I.E. Port 2 would be expressed as0x01 ([[4\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn4)) | +| Reserved | 3 Bytes | Usually 0x00 0x00 0x00 | +| DataKind | 1 Byte | Is the frame code, reflects the purpose of the frame. The meaning of the DataKind DO VARY depending on whether the frame flows from the application to **\*AGWPE\*** or viceversa. | +| Reserved | 1 Byte | Usually 0x00 | +| PID | 1 Byte | Frame PID, it’s usage is valid only under certain frames only. Should be 0x00 when not used. | +| Reserved | 1 Byte | Usually 0x00 | +| CallFrom | 10 Bytes | CallSign FROM of the packet, in ASCII, using the format {CALLSIGN}-{SSID}(i.e. **\*LU7DID\***-8)it is “null terminated” (it ends with 0x00). ([[5\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn5))The field ALWAYS is 10 bytes long.It’s filled on packets where it has some meaning. | +| CallTo | 10 Bytes | CallSign TO of the packet, same as above. | +| DataLen | 4 Bytes | Data Length as a 32 bits unsigned integer.If zero means no data follows the header. | +| User (Reserved) | 4 Bytes | 32 bits unsigned integer, not used. Reserved for future use. | All reserved fields must not be used by application programs in any form, they should be initialized to -binary zeros (0x00) on frames sent by the application to ***AGWPE\***, undefined values could be present on frames sent by ***AGWPE\*** to the application on those frames. +binary zeros (0x00) on frames sent by the application to **\*AGWPE\***, undefined values could be present on frames sent by **\*AGWPE\*** to the application on those frames. - - -***AGWPE\*** is fairly tolerant on unused fields (either reserved or not used on a particular frame format) to held almost anything, so the need for proper initialize them reflected on this documentation aims towards proper programming practices rather than actual needs from ***AGWPE\***. - - +**\*AGWPE\*** is fairly tolerant on unused fields (either reserved or not used on a particular frame format) to held almost anything, so the need for proper initialize them reflected on this documentation aims towards proper programming practices rather than actual needs from **\*AGWPE\***. Frames sent from the Application to AGWPE where the CallFrom/CallTo values are relevant must contain our callsign in the CallFrom and the other end callsign in the CallTo fields. The other way around, frames from AGWPE to the Application would contain the other end callsign+SSID in the CallFrom and our callsign+SSID in the CallTo fields. - - When the frame has data associated with it (DataLen <> 0) the bytes up to the number expressed by DataLen follows inmediately after the last byte of the header. - - In order to allow for a fully transparent transport of data no delimiters of any kind are used on the data area, so binary information of any kind could be effectively transported. - +A typical example of a frame (header+data) sent by **\*AGWPE\*** looks like this: -A typical example of a frame (header+data) sent by ***AGWPE\*** looks like this: +|01 00 00 00 4D 00 CF 00 4C 55 37 44 49 44 2D 34 |....M...**\*LU7DID\***-4 - +|00 00 4E 4F 44 45 53 00 00 00 00 00 07 00 00 00 |..NODES......... - +|00 00 00 00 FF 41 42 52 4F 57 4E -- -- -- -- -- |.....ABROWN - |01 00 00 00 4D 00 CF 00 4C 55 37 44 49 44 2D 34 |....M...***LU7DID\***-4 +An example of a frame with just a header sent by **\*AGWPE\*** looks like this: - |00 00 4E 4F 44 45 53 00 00 00 00 00 07 00 00 00 |..NODES......... - - |00 00 00 00 FF 41 42 52 4F 57 4E -- -- -- -- -- |.....ABROWN - - - -An example of a frame with just a header sent by ***AGWPE\*** looks like this: - - - -|00 00 00 00 58 00 00 00 4C 55 37 44 49 44 2D 34 |....X...***LU7DID\***-4 +|00 00 00 00 58 00 00 00 4C 55 37 44 49 44 2D 34 |....X...**\*LU7DID\***-4 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ |00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - It’s worth to notice that in the second example not all fields (actually the ones not relevant to the function requested as we would see) have not been completed. - - - - ## Frames sent by the Application to AGWPE - - -Application might (or must, sometimes) send data to ***AGWPE\*** in order to retrieve configuration information or to sustain communication over any of the ports. - - +Application might (or must, sometimes) send data to **\*AGWPE\*** in order to retrieve configuration information or to sustain communication over any of the ports. Colloquially, the frames are identified by it’s **DataKind** (so a frame with a DataKind=’X’ is referred in this documentation as an ‘X’ frame). - - -The same DataKind could be used on a frame sent by the application to ***AGWPE\*** or from ***AGWPE\*** to the application (however, the meaning of a DataKind is unique in any given direction), usually the frames with the same DataKind on both directions are Query-Answer pairs (so, i.e., a ‘G’ frame sent by the application is replied by ***AGWPE\*** with a ‘G’ frame filled with the information required). - - +The same DataKind could be used on a frame sent by the application to **\*AGWPE\*** or from **\*AGWPE\*** to the application (however, the meaning of a DataKind is unique in any given direction), usually the frames with the same DataKind on both directions are Query-Answer pairs (so, i.e., a ‘G’ frame sent by the application is replied by **\*AGWPE\*** with a ‘G’ frame filled with the information required). Care has to be taken by the application program to handle sent and received frames separately. - - -Follows all the frame formats supported for the application to send to ***AGWPE\***. - - +Follows all the frame formats supported for the application to send to **\*AGWPE\***. ### Application Login (‘P’ frame) - - An application needs to login when the “WinSock Interface Security” setting rules doesn’t allow the machine where the application is being ran to access the AGWPE directly; it should not bother applications running on the same machine where AGWPE is executing. Still applications should allow the user to define this security setting and be flexible to be run on machines other than the one AGWPE is running (and thus, potentially not enabled directly by the security settings to access AGWPE). - - This frame is mandatory when the application is being run from a machine that doesn’t comply with the security rules, without it AGWPE will not accept nor send frames to the application. - - The login is made with a frame with an empty header and the login data into the Information part of the frame with the following format. - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------ | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘P’ (ASCII 0x50) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | Length of User+Password including 0x00’s | +| User & Password | N Bytes | UserId ended with 0x00 filled till 255 bytesPassword ended with 0x00 filled with 255 bytes | -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘P’ (ASCII 0x50) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | Length of User+Password including 0x00’s | -| User & Password | N Bytes | UserId ended with 0x00 filled till 255 bytesPassword ended with 0x00 filled with 255 bytes | - - - -***AGWPE\*** do not inform the application about the success. - - +**\*AGWPE\*** do not inform the application about the success. Please note an application must send one of the UserId/Password combinations as stated in the “WinSock Interface Security” tab “User Setup” section in order to be validated and allowed by AGWPE to interact with it thru the WinSocks API. - - Follows a sample content of the information area of the frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|4C 55 37 44 49 44 00 00 00 00 00 00 00 00 00 00 |LU7DID.......... - +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |4C 55 37 44 49 44 00 00 00 00 00 00 00 00 00 00 |LU7DID.......... +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4C |...............L - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|49 5A 41 52 44 00 00 00 00 00 00 00 00 00 00 00 |IZARD........... - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4C |...............L +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |49 5A 41 52 44 00 00 00 00 00 00 00 00 00 00 00 |IZARD........... +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - - |00 00 00 00 00 00 00 00 00 00 00 00 00 00 -- -- |.............. - - - - +|00 00 00 00 00 00 00 00 00 00 00 00 00 00 -- -- |.............. ### Register CallSign (‘X’ frame) - - -An application needs to register at least one callsign with ***AGWPE\*** as a pre-requisite to be able to send data thru any AX.25 port or to sustain any connection and before any attempt on doing so. - - +An application needs to register at least one callsign with **\*AGWPE\*** as a pre-requisite to be able to send data thru any AX.25 port or to sustain any connection and before any attempt on doing so. To receive (monitor) information heard at the different ports the “m” frame should be used instead. - - There is no limits on the number of callsigns that could be registered by a single application, each registration would require a separate frame. - - -When an application registers a callsign ***AGWPE\*** “listen” on the radio ports for any packet frame directed to that callsign and when detected it would be sent to the application using the suitable frame format (depending on the type). - - +When an application registers a callsign **\*AGWPE\*** “listen” on the radio ports for any packet frame directed to that callsign and when detected it would be sent to the application using the suitable frame format (depending on the type). The registration is made with a frame with just a header (no data) with the following format. - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘X’ (ASCII 0x58) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | CallSign-SSID to register | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------- | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘X’ (ASCII 0x58) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | CallSign-SSID to register | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | +A given callsign and SSID combination is allowed to be registered just once by an application (actually among all the applications connected to the same **\*AGWPE\*** at any given moment). - - -A given callsign and SSID combination is allowed to be registered just once by an application (actually among all the applications connected to the same ***AGWPE\*** at any given moment). - -***AGWPE\*** informs the application about the success (callsign+SSID registered) or failure (callsign+SSID already in use) by means of an “X” frame sent to the application in response of this one. - - +**\*AGWPE\*** informs the application about the success (callsign+SSID registered) or failure (callsign+SSID already in use) by means of an “X” frame sent to the application in response of this one. Please note an application could register almost “anything” as a callsign+SSID (not necessarily a true callsign), so if for some reason is relevant to the application to receive frames directed to (i.e.) the “NODES” destination that could be accomplished registering the “NODES” callsign, in a way that any frames (likely UI frames) directed to the “NODES” destination (NODES-0 actually) would be directed to the application who registered it. As in with the case of true callsigns a given “destination”+SSID is allowed to be registered just once. - - A registration could be performed at any time by the application. - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - -|00 00 00 00 58 00 00 00 4C 55 37 44 49 44 2D 34 |....X...***LU7DID\***-4 +|00 00 00 00 58 00 00 00 4C 55 37 44 49 44 2D 34 |....X...**\*LU7DID\***-4 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Unregister CallSign (‘x’ frame) - +This is the opposite function than to register a callsign, it means the callsign and SSID combination is not longer used by the application and it’s free for further use, from the moment of the application become unregistered and till it’s registred again all activity heard by **\*AGWPE\*** on the AX.25 ports directed to that callsign is ignored. -This is the opposite function than to register a callsign, it means the callsign and SSID combination is not longer used by the application and it’s free for further use, from the moment of the application become unregistered and till it’s registred again all activity heard by ***AGWPE\*** on the AX.25 ports directed to that callsign is ignored. - - - -Also, all information sent by the application to ***AGWPE\*** involving the unregistered callsign is ignored. - - +Also, all information sent by the application to **\*AGWPE\*** involving the unregistered callsign is ignored. The overall format is very similar to the registration frame, just the DataKind is changed, as follows: - +| Field | Length | Meaning | +| ------------------ | -------- | --------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘x’ (ASCII 0x78) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | CallSign-SSID to unregister | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | --------------------------- | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘x’ (ASCII 0x78) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | CallSign-SSID to unregister | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - - -As a difference with the registration frame the application should not expect any answer from ***AGWPE\*** as a confirmation of the successful unregistration. - - +As a difference with the registration frame the application should not expect any answer from **\*AGWPE\*** as a confirmation of the successful unregistration. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - -|00 00 00 00 78 00 00 00 4C 55 37 44 49 44 2D 34 |....x...***LU7DID\***-4 +|00 00 00 00 78 00 00 00 4C 55 37 44 49 44 2D 34 |....x...**\*LU7DID\***-4 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Ask Port Information (‘G’ frame) - +Using this frame the application could query **\*AGWPE\*** to provide information about the currently defined ports. -Using this frame the application could query ***AGWPE\*** to provide information about the currently defined ports. - - - -This information is usually handy at the start of the application program in order to know the number of ports available and eventually use that information for functional or presentation purposes, the port information could not be changed dynamically on ***AGWPE\*** (it requires ***AGWPE\*** to be stopped and re-started) so this information should also be queried every time the TCP/IP connection is re-established. - - +This information is usually handy at the start of the application program in order to know the number of ports available and eventually use that information for functional or presentation purposes, the port information could not be changed dynamically on **\*AGWPE\*** (it requires **\*AGWPE\*** to be stopped and re-started) so this information should also be queried every time the TCP/IP connection is re-established. The frame format comprises a header only with the following information. - +| Field | Length | Meaning | +| ------------------ | -------- | ---------------- | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘G’ (ASCII 0x47) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ---------------- | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘G’ (ASCII 0x47) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - - -***AGWPE\*** answer this request with a “G” frame. - - +**\*AGWPE\*** answer this request with a “G” frame. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - |00 00 00 00 47 00 00 00 00 00 00 00 00 00 00 00 |....G........... |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - - - - - - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Enable Reception of Monitoring Frames (‘m’ frame) - - -In order for monitoring frames to be sent to the application this condition has to be signaled to ***AGWPE\*** using this frame. - - +In order for monitoring frames to be sent to the application this condition has to be signaled to **\*AGWPE\*** using this frame. From the moment this frame is sent activity at all ports would be made available to the application (Frames S,I and U). - - This function could be used even if the application didn’t registered any callsign. - +| Field | Length | Meaning | +| ------------------ | -------- | ---------------- | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘m’ (ASCII 0x6D) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ---------------- | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘m’ (ASCII 0x6D) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - - -***AGWPE\*** didn’t confirm specifically this frame, however, the flow of monitored information should start inmediately after it has been sent by the application. - - +**\*AGWPE\*** didn’t confirm specifically this frame, however, the flow of monitored information should start inmediately after it has been sent by the application. This frame acts like a switch, the first time issued it enables the reception of monitoring frames while the second disables it and so on; in general on odd times it would enable and on even times it would disable. - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - |00 00 00 00 6D 00 00 00 00 00 00 00 00 00 00 00 |....m........... |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - - - - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### AGWPE Version Info (‘R’ frame) - +It’s sometimes important (at least it’s is a good programming recommended practice) to care about the level of the **\*AGWPE\*** which the application is connecting to. -It’s sometimes important (at least it’s is a good programming recommended practice) to care about the level of the ***AGWPE\*** which the application is connecting to. +Several reasons support that practice, but the most important is to be sure the **\*AGWPE\*** will support all the frames and functions the application program would require to work properly; as a fast evolving platform **\*AGWPE\*** is being continuously upgraded with new functions and fixes for old ones. - +The application programmer should not be surprised to find almost all version historically released of **\*AGWPE\*** thru the time, not all of them supporting the full set of frames documented here (which are valid as per version 2000.20 or higher). -Several reasons support that practice, but the most important is to be sure the ***AGWPE\*** will support all the frames and functions the application program would require to work properly; as a fast evolving platform ***AGWPE\*** is being continuously upgraded with new functions and fixes for old ones. +The **\*AGWPE\*** version is queried with a frame with the following format: - +| Field | Length | Meaning | +| ------------------ | -------- | ---------------- | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘R’ (ASCII 0x52) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -The application programmer should not be surprised to find almost all version historically released of ***AGWPE\*** thru the time, not all of them supporting the full set of frames documented here (which are valid as per version 2000.20 or higher). +In any case, this frame should be sent at least once per execution by the application program (even if the **\*AGWPE\*** connection could be stopped and restarted it’s not unreasonable to assume the version didn’t changed, doesn’t hurt to query and confirm the version on each connection with **\*AGWPE\*** though). - - -The ***AGWPE\*** version is queried with a frame with the following format: - - - -| Field | Length | Meaning | -| ----------------- | -------- | ---------------- | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘R’ (ASCII 0x52) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - - -In any case, this frame should be sent at least once per execution by the application program (even if the ***AGWPE\*** connection could be stopped and restarted it’s not unreasonable to assume the version didn’t changed, doesn’t hurt to query and confirm the version on each connection with ***AGWPE\*** though). - - - -This frame is answerd by ***AGWPE\*** with an ‘R’ frame. - - +This frame is answerd by **\*AGWPE\*** with an ‘R’ frame. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - |00 00 00 00 52 00 00 00 00 00 00 00 00 00 00 00 |....R........... |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Ask Port Capabilities (‘g’ frame) - +An useful complement of the “G” frame (Ask Port Information) is to query **\*AGWPE\*** about the particular configuration for every specific port. -An useful complement of the “G” frame (Ask Port Information) is to query ***AGWPE\*** about the particular configuration for every specific port. - - - -Albeit ***AGWPE\*** doesn’t allow an application to change its configuration thru the API it’s usually necessary or useful to get that information anyway for (mostly) presentation purposes. - - +Albeit **\*AGWPE\*** doesn’t allow an application to change its configuration thru the API it’s usually necessary or useful to get that information anyway for (mostly) presentation purposes. This frame has the following format - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------ | +| **\*AGWPE\*** Port | 1 Bytes | Port to query0=Port1,1=Port2,… | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘g’ (ASCII 0x6D) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to query0=Port1,1=Port2,… | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘g’ (ASCII 0x6D) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | +**\*AGWPE\*** answers this request with a “g” frame. - +Some values are static and could not be changed without re-starting **\*AGWPE\***, but others reflects dynamically the current status of a given port in terms of traffic. -***AGWPE\*** answers this request with a “g” frame. - - - -Some values are static and could not be changed without re-starting ***AGWPE\***, but others reflects dynamically the current status of a given port in terms of traffic. - - - -This function should be called at least once every time a connection with ***AGWPE\*** is established, there is no limit on how many times this information could be queried, however, a practical limit from the performance (and usefulness) standpoint should limit this query to be performed once every minute or so. - - +This function should be called at least once every time a connection with **\*AGWPE\*** is established, there is no limit on how many times this information could be queried, however, a practical limit from the performance (and usefulness) standpoint should limit this query to be performed once every minute or so. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - |00 00 00 00 67 00 00 00 00 00 00 00 00 00 00 00 |....g........... |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Callsign Heard on a Port (‘H’ frame) - - A very useful service required (or nice to have) on most applications is a list of the stations “heard” on a given port; this could be achieved by the application just collecting monitoring information. - - -However, this is not required since ***AGWPE\*** helds such a list and makes it available to the application upon request (at any time). - - +However, this is not required since **\*AGWPE\*** helds such a list and makes it available to the application upon request (at any time). In order to request the updated list of stations heard on a given port the following frame has to be sent. - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------ | +| **\*AGWPE\*** Port | 1 Bytes | Port to query0=Port1,1=Port2,… | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘H’ (ASCII 0x48) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to query0=Port1,1=Port2,… | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘H’ (ASCII 0x48) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - - -This function makes ***AGWPE\*** to answer the Heard information thru an “H” frame. - - +This function makes **\*AGWPE\*** to answer the Heard information thru an “H” frame. This frame could be sent as many times as required during the lifespan of a connection, every time the information provided will be updated to reflect the traffic actually heard. - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - |01 00 00 00 48 00 00 00 00 00 00 00 00 00 00 00 |....H........... |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Ask Outstanding frames waiting on a Port (‘y’ Frame) - +This frame could be used by the application at any time to query **\*AGWPE\*** about the number of frames (from all sources, not only this application) that are queued and waiting to be transmitted by **\*AGWPE\*** thru a given port. -This frame could be used by the application at any time to query ***AGWPE\*** about the number of frames (from all sources, not only this application) that are queued and waiting to be transmitted by ***AGWPE\*** thru a given port. - - - -This would be useful to regulate the rate used to send information to ***AGWPE\*** and to keep it realistic with the actual bandwidth of the destination port. - - +This would be useful to regulate the rate used to send information to **\*AGWPE\*** and to keep it realistic with the actual bandwidth of the destination port. The information could be queried using the following frame: - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------ | +| **\*AGWPE\*** Port | 1 Bytes | Port to query0=Port1,1=Port2,… | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘y’ (ASCII 0x79) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to query0=Port1,1=Port2,… | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘y’ (ASCII 0x79) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - - -This frame is answered by ***AGWPE\*** with an ‘y’ frame. - - +This frame is answered by **\*AGWPE\*** with an ‘y’ frame. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - |00 00 00 00 79 00 00 00 00 00 00 00 00 00 00 00 |....y........... |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Ask Outstanding frames waiting for a connection (‘Y’ frame) - - -This frame could be used with similar purposes than the ‘y’ frame but to query ***AGWPE\*** about the outstanding frames waiting sourced on a given (and specific) connection as opposed to the overall activity of a port without any clue on how it had been sourced. - - +This frame could be used with similar purposes than the ‘y’ frame but to query **\*AGWPE\*** about the outstanding frames waiting sourced on a given (and specific) connection as opposed to the overall activity of a port without any clue on how it had been sourced. The information could be queried using the following frame: - +| Field | Length | Meaning | +| ------------------ | -------- | --------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port to query0=Port1,1=Port2,… | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘Y’ (ASCII 0x59) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. **\*LU7DID\***-11 ended withnull (0x00) | +| CallTo | 10 Bytes | Other CallSign-SSIDi.e. **\*SV2AGW\***-14 ended withnull (0x00) | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to query0=Port1,1=Port2,… | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘Y’ (ASCII 0x59) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. ***LU7DID\***-11 ended withnull (0x00) | -| CallTo | 10 Bytes | Other CallSign-SSIDi.e. ***SV2AGW\***-14 ended withnull (0x00) | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | +**\*AGWPE\*** would answer this frame with a ‘Y’ frame himself if the connection referred by the CallFrom/CallTo fields do exists currently. - - -***AGWPE\*** would answer this frame with a ‘Y’ frame himself if the connection referred by the CallFrom/CallTo fields do exists currently. - - - -Careful must be exercised to fill correctly both the CallFrom and CallTo fields to match the ones of an existing connection, otherwise ***AGWPE\*** won’t return any information at all from this query. - - +Careful must be exercised to fill correctly both the CallFrom and CallTo fields to match the ones of an existing connection, otherwise **\*AGWPE\*** won’t return any information at all from this query. The order of the CallFrom and CallTo is not trivial, it should reflect the order used to start the connection, so - - - If we started the connection CallFrom=US and CallTo=THEM - If the other end started the connection CallFrom=THEM and CallTo=US - - -Please refer to the ‘C’ frame sent by ***AGWPE\*** upon connection to understand how to identify who initiated a connection. - - +Please refer to the ‘C’ frame sent by **\*AGWPE\*** upon connection to understand how to identify who initiated a connection. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|01 00 00 00 59 00 00 00 4C 55 37 44 49 44 2D 34 |....Y...**\*LU7DID\***-4 - +|00 00 4C 55 37 44 49 44 00 00 00 00 00 00 00 00 |..**\*LU7DID\***........ -|01 00 00 00 59 00 00 00 4C 55 37 44 49 44 2D 34 |....Y...***LU7DID\***-4 - -|00 00 4C 55 37 44 49 44 00 00 00 00 00 00 00 00 |..***LU7DID\***........ - -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Send UNPROTO Information (‘M’ frame) - - This frame could be used by the application when an AX.25 unproto (UI) frame must be sent by the application. - - -For an application to send unproto information no registration is needed, however unproto information heard on the ports directed to it won’t be made available by ***AGWPE\*** and information exchange won’t be possible (unless the application extract frames directed to it thru the inspection of monitoring frames, which is not utterly practical but still possible). - - +For an application to send unproto information no registration is needed, however unproto information heard on the ports directed to it won’t be made available by **\*AGWPE\*** and information exchange won’t be possible (unless the application extract frames directed to it thru the inspection of monitoring frames, which is not utterly practical but still possible). Typical uses for an unproto frame are beacon or any other broadcast message, it’s also widely used by NETROM L3 broadcast, TCP/IP over AX.25 and the FBB mail client protocol among others. - - In order to send an unproto frame the header to be used is - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to send the unproto frame thru {0=Port1,1=Port2,…} | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘M’ (ASCII 0x4D) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | AX.25 PID0x00 or 0xF0 for AX.250xCF NETROMand others | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. ***LU7DID\***-11 ended withnull (0x00) used | -| CallTo | 10 Bytes | Destination of the unprotoframe. Not necessarily acallsign+SSID (could be i.e. CQ, ID, another callsign+SSID), etc… | -| DataLen | 4 Bytes | Number of Bytes to be sent | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port to send the unproto frame thru {0=Port1,1=Port2,…} | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘M’ (ASCII 0x4D) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | AX.25 PID0x00 or 0xF0 for AX.250xCF NETROMand others | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. **\*LU7DID\***-11 ended withnull (0x00) used | +| CallTo | 10 Bytes | Destination of the unprotoframe. Not necessarily acallsign+SSID (could be i.e. CQ, ID, another callsign+SSID), etc… | +| DataLen | 4 Bytes | Number of Bytes to be sent | +| User (Reserved) | 4 Bytes | 0 | Following the header the (exact) amount of bytes indicated in DataLen should follow. - +**\*AGWPE\*** would indirectly inform the success of the unproto send thru both an ‘I’ frame, a ‘U’ frame and a ‘T’ frame (if monitoring is enabled thru the ‘m’ frame). -***AGWPE\*** would indirectly inform the success of the unproto send thru both an ‘I’ frame, a ‘U’ frame and a ‘T’ frame (if monitoring is enabled thru the ‘m’ frame). - - - -Even if ***AGWPE\*** handles AX.25 frames larger than 255 bytes not so many other programs could over the air, so it’s a reasonably programming practice to ensure than the length of the data to be transferred is equal to or less than 255 bytes. - - +Even if **\*AGWPE\*** handles AX.25 frames larger than 255 bytes not so many other programs could over the air, so it’s a reasonably programming practice to ensure than the length of the data to be transferred is equal to or less than 255 bytes. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - -|00 00 00 00 4D 00 F0 00 4C 55 37 44 49 44 2D 34 |....M...***LU7DID\***-4 +|00 00 00 00 4D 00 F0 00 4C 55 37 44 49 44 2D 34 |....M...**\*LU7DID\***-4 |00 00 4E 45 54 4D 45 00 00 00 00 00 39 00 00 00 |..NETME.....9... |00 00 00 00 0D 0A 42 65 61 63 6F 6E 20 64 65 20 |......Beacon de -|4E 6F 64 6F 20 4C 55 37 44 49 44 2D 34 20 41 64 |Nodo ***LU7DID\***-4 Ad +|4E 6F 64 6F 20 4C 55 37 44 49 44 2D 34 20 41 64 |Nodo **\*LU7DID\***-4 Ad |72 6F 67 75 65 20 42 41 20 41 72 67 65 6E 74 69 |rogue BA Argenti -|6E 61 20 5B 47 46 30 35 54 45 5D 0D 0A -- -- -- |na [GF05TE].. - - - - - - +|6E 61 20 5B 47 46 30 35 54 45 5D 0D 0A -- -- -- |na [GF05TE].. ### Connect, Start an AX.25 Connection (‘C’ frame) - +This frame is sent to **\*AGWPE\*** when an AX.25 connection with other station is required. -This frame is sent to ***AGWPE\*** when an AX.25 connection with other station is required. - - - -The station originating the connection (CallFrom) **must had been previously registered** with ***AGWPE\*** (‘X’ frame) for the connection to be successfully established. - - +The station originating the connection (CallFrom) **must had been previously registered** with **\*AGWPE\*** (‘X’ frame) for the connection to be successfully established. The connection started with this frame would always be a normal AX.25 connection (information frames with PID=0xF0). - - The application is responsible to identify the port to be used for this connection and to properly inform it on the frame. - - The format of the frame follows: - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port to send the connection request frame thru {0=Port1,1=Port2,…} | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘C’ (ASCII 0x43) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. **\*LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | +| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to send the connection request frame thru {0=Port1,1=Port2,…} | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘C’ (ASCII 0x43) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. ***LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | -| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - - -***AGWPE\*** would start inmediately to connect the destination callsign-SSID (it could be monitored, if monitoring has been enabled) thru the ‘S’ frames. - - +**\*AGWPE\*** would start inmediately to connect the destination callsign-SSID (it could be monitored, if monitoring has been enabled) thru the ‘S’ frames. Upon connection or failure the application would receive a ‘C’ frame or a “Retryout message”. - - An application could sustain one connection per distinctive callsigns+SSID for both origin and destination pairs (only one connection by a given callsign+SSID on origin and destination is allowed by the AX.25 protocol). - - No practical limit do exists on the number of connections an application could sustain with different destinations, even from the same originating callsign+SSID. This concept, of course, is extended when many callsigns+SSID are registered by the same application. - - -It is an application duty, as we’ll see on the relevant frames sent by ***AGWPE\***, to discriminate among data coming from diferent connections. - - +It is an application duty, as we’ll see on the relevant frames sent by **\*AGWPE\***, to discriminate among data coming from diferent connections. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|01 00 00 00 43 00 00 00 4C 55 37 44 49 44 2D 34 |....C...**\*LU7DID\***-4 - +|00 00 4C 55 37 44 49 44 00 00 00 00 00 00 00 00 |..**\*LU7DID\***........ -|01 00 00 00 43 00 00 00 4C 55 37 44 49 44 2D 34 |....C...***LU7DID\***-4 - -|00 00 4C 55 37 44 49 44 00 00 00 00 00 00 00 00 |..***LU7DID\***........ - -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Send Connected Data (‘D’ frame) - - Once a connection had been successfully established data could be exchanged, the application could then send data to the other end by means of data frames. - - The format of the frame would be - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to send the data frame thru {0=Port1,1=Port2,…} | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘D’ (ASCII 0x44) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. ***LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | -| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | -| DataLen | 4 Bytes | Number of Data Bytes to be transferred. | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port to send the data frame thru {0=Port1,1=Port2,…} | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘D’ (ASCII 0x44) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. **\*LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | +| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | +| DataLen | 4 Bytes | Number of Data Bytes to be transferred. | +| User (Reserved) | 4 Bytes | 0 | Following the header the (exact) amount of bytes indicated in DataLen should follow. - +**\*AGWPE\*** would indirectly inform the success of the unproto send thru both an ‘I’ frame, a ‘U’ frame and a ‘T’ frame (if monitoring is enabled thru the ‘m’ frame). -***AGWPE\*** would indirectly inform the success of the unproto send thru both an ‘I’ frame, a ‘U’ frame and a ‘T’ frame (if monitoring is enabled thru the ‘m’ frame). +Data exchanged would be under a standard AX.25 Information PID (0xF0) unless the connection had been specifically started signalling **\*AGWPE\*** about a non-standard PID (connection started with the ‘c’ frame instead of the ‘C’ frame), on such situations the application must place the relevant PID on the respective field of the header. In all other situations the PID field is ignored by **\*AGWPE\*** and 0xF0 is used instead. - - -Data exchanged would be under a standard AX.25 Information PID (0xF0) unless the connection had been specifically started signalling ***AGWPE\*** about a non-standard PID (connection started with the ‘c’ frame instead of the ‘C’ frame), on such situations the application must place the relevant PID on the respective field of the header. In all other situations the PID field is ignored by ***AGWPE\*** and 0xF0 is used instead. - - - -If a ‘D’ frame is sent by the application without an established connection the frame is ignored by ***AGWPE\***. - - +If a ‘D’ frame is sent by the application without an established connection the frame is ignored by **\*AGWPE\***. It is the application responsibility to keep using the proper AGWPort and CallFrom/CallTo values on all the frames of a given connection than the used to establish it. - - -Even if ***AGWPE\*** handles AX.25 frames larger than 255 bytes not so many other programs could over the air, so it’s a reasonably programming practice to ensure than the length of the data to be transferred is equal to or less than 255 bytes. - - +Even if **\*AGWPE\*** handles AX.25 frames larger than 255 bytes not so many other programs could over the air, so it’s a reasonably programming practice to ensure than the length of the data to be transferred is equal to or less than 255 bytes. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|01 00 00 00 44 00 F0 00 4C 55 37 44 49 44 00 00 |....D...**\*LU7DID\***.. - - -|01 00 00 00 44 00 F0 00 4C 55 37 44 49 44 00 00 |....D...***LU7DID\***.. - -|F0 15 4C 55 37 44 49 44 2D 34 00 00 02 00 00 00 |..***LU7DID\***-4...... +|F0 15 4C 55 37 44 49 44 2D 34 00 00 02 00 00 00 |..**\*LU7DID\***-4...... |A8 6D 45 00 3F 0D -- -- -- -- -- -- -- -- -- -- |.mE.?. - - - - ### Disconnect, Terminate an AX.25 Connection (‘d’ frame) - - When an AX.25 connection (started with a ‘C’ frame) needs to be terminated a disconnection frame must be sent by the application. - - To send data between a connection and a disconnection is, of course, optional; however, the main purpose of a connection would be most of the time to exchange data with another station. - - The format of the frame would be: - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to send the data frame thru {0=Port1,1=Port2,…} | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘d’ (ASCII 0x64) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. ***LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | -| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port to send the data frame thru {0=Port1,1=Port2,…} | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘d’ (ASCII 0x64) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. **\*LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | +| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | No data is associated with this frame. - +**\*AGWPE\*** will inform the completion of this request thru a ‘d’ frame[[6\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn6) -***AGWPE\*** will inform the completion of this request thru a ‘d’ frame[[6\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftn6) - - - -If a ‘d’ frame is sent by the application without an established connection the frame is ignored by ***AGWPE\***. - - +If a ‘d’ frame is sent by the application without an established connection the frame is ignored by **\*AGWPE\***. It is the application responsibility to keep using the proper AGWPort and CallFrom/CallTo values on all the frames of a given connection than the used to establish it. - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|01 00 00 00 64 00 00 00 4C 55 37 44 49 44 2D 34 |....d...**\*LU7DID\***-4 - +|00 00 4C 55 37 44 49 44 00 00 00 00 00 00 00 00 |..**\*LU7DID\***........ -|01 00 00 00 64 00 00 00 4C 55 37 44 49 44 2D 34 |....d...***LU7DID\***-4 - -|00 00 4C 55 37 44 49 44 00 00 00 00 00 00 00 00 |..***LU7DID\***........ - -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ### Connect VIA, Start an AX.25 circuit thru digipeaters (‘v’ frame) - - This frame is used with similar purposes than the ‘C’ frame, but as it creates a “direct” connection this frame must be used when intermediate AX.25 digipeaters must be used to establish a connection. - - It’s the application responsibility to determine, based on it’s functionality and user interface, whether a given connection should be started direct (‘C’ frame) or thru digipeaters (‘v’ frame). - - Once the connection is established data is transferred between both ends with the same frame (‘D’ frame) and disconnection is started also with the same frame (‘d’ frame) on both. - - The format of this frame would be - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to send the data frame thru {0=Port1,1=Port2,…} | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘v’ (ASCII 0x76) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. ***LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | -| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | -| DataLen | 4 Bytes | Length of the VIA information | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port to send the data frame thru {0=Port1,1=Port2,…} | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘v’ (ASCII 0x76) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. **\*LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | +| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | +| DataLen | 4 Bytes | Length of the VIA information | +| User (Reserved) | 4 Bytes | 0 | The VIA (number and sequence of digipeaters to be used) is informed in the data part of the frame inmediately following the header, the length of this area would vary depending on the number of digipeaters to be used, the exact length must be informed in the DataLen field. - - The data area must contain the VIA information in the following format - - | Offset | Length | Meaning | | ------- | -------- | ------------------------------------------------------------ | | +00 | 1 Bytes | Total number of digipeaters to be used (max 7) | @@ -1495,47 +809,31 @@ The data area must contain the VIA information in the following format | …… | …… | ….. | | +10XN+1 | 10 Byte | CallSign+SSID of the Nnd digipeater ended with null (0x00) | - - Of course, only the number of needed digipeaters has to be informed (but at least ONE must be informed, otherwise a direct connection should be used instead). - - -The successful completion of the connection is informed by ***AGWPE\*** thru the ‘C’ frame. - - +The successful completion of the connection is informed by **\*AGWPE\*** thru the ‘C’ frame. ### Send UNPROTO VIA (‘V’ frame) - - When the application needs to send unproto information (as in the ‘M’ frame) but using a chain of repeaters to do so this frame format should be used instead. - - The frame format is as follows: - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to send the unproto frame thru {0=Port1,1=Port2,…} | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘V’ (ASCII 0x76) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. ***LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | -| CallTo | 10 Bytes | Destination callsign+SSID or ID of the unproto frame (i.e. CQ, ID, MAIL, etc) | -| DataLen | 4 Bytes | Length of the VIA information and the data to be sent | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port to send the unproto frame thru {0=Port1,1=Port2,…} | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘V’ (ASCII 0x76) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | AX.25 PID (0xF0 or 0x00) | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. **\*LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | +| CallTo | 10 Bytes | Destination callsign+SSID or ID of the unproto frame (i.e. CQ, ID, MAIL, etc) | +| DataLen | 4 Bytes | Length of the VIA information and the data to be sent | +| User (Reserved) | 4 Bytes | 0 | Right after the header the chain of digipeaters to be used is sent as the first part of the data area using the format already discussed for the Connect VIA (‘v’ frame) - - | Offset | Length | Meaning | | ------- | -------- | ------------------------------------------------------------ | | +00 | 1 Bytes | Total number of digipeaters to be used (max 7) | @@ -1544,280 +842,160 @@ Right after the header the chain of digipeaters to be used is sent as the first | …… | …… | ….. | | +10XN+1 | 10 Byte | CallSign+SSID of the Nnd digipeater ended with null (0x00) | - - As before, only the number of digipeaters to be used needs to be included (with at least one being informed). - - After the VIA information the actual data to be sent is included, please note the DataLen field on the header should reflect the exact size of both the VIA information and the data information to be sent. - +Even if **\*AGWPE\*** handles AX.25 frames larger than 255 bytes not so many other programs could over the air, so it’s a reasonably programming practice to ensure than the length of the data to be transferred is equal to or less than 255 bytes. -Even if ***AGWPE\*** handles AX.25 frames larger than 255 bytes not so many other programs could over the air, so it’s a reasonably programming practice to ensure than the length of the data to be transferred is equal to or less than 255 bytes. - - - -However, nothing prevents the SUM of the VIA information and the data information to be sent to be larger than 255 bytes (the VIA information is internally decoded and used by ***AGWPE\*** to build the AX.25 header but only the data information is included on the AX.25 information part). - - +However, nothing prevents the SUM of the VIA information and the data information to be sent to be larger than 255 bytes (the VIA information is internally decoded and used by **\*AGWPE\*** to build the AX.25 header but only the data information is included on the AX.25 information part). ### Non-Standard Connections, Connection with PID (‘c’ frame) - - On special situations the application might need to interchange information with a destination thru frames using a non-standard PID (standard AX.25 PID for Information Frames is 0xF0), examples of such a need are NETROM connections and frames related to a connected TCP/IP over AX.25 circuit. - - -On such ocassions ***AGWPE\*** must be signaled of this singularity starting the connection with this frame instead of a “normal” ‘C’ frame as documented before; the application is also responsible to fill the PID field of the header of all data frames sent during the connection with the appropriate value (even if the PID is informed during the connection it has to be “repeated” on every data frame). - - +On such ocassions **\*AGWPE\*** must be signaled of this singularity starting the connection with this frame instead of a “normal” ‘C’ frame as documented before; the application is also responsible to fill the PID field of the header of all data frames sent during the connection with the appropriate value (even if the PID is informed during the connection it has to be “repeated” on every data frame). The format of the frame would be - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port to send the connection request frame thru {0=Port1,1=Port2,…} | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘c’ (ASCII 0x63) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | Non Standard PID to use | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. **\*LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | +| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port to send the connection request frame thru {0=Port1,1=Port2,…} | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘c’ (ASCII 0x63) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | Non Standard PID to use | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Our CallSign-SSIDi.e. ***LU7DID\***-11 ended withnull (0x00) used. must had been previously registered | -| CallTo | 10 Bytes | Destination callsign+SSID of the connection. | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - - - - -***AGWPE\*** would start inmediately to connect the destination callsign-SSID (it could be monitored, if monitoring has been enabled) thru the ‘S’ frames. - - +**\*AGWPE\*** would start inmediately to connect the destination callsign-SSID (it could be monitored, if monitoring has been enabled) thru the ‘S’ frames. Upon connection or failure the application would receive a ‘C’ frame or a “RETRYOUT” message. - - An application could sustain one connection per distinctive callsigns+SSID for both origin and destination pairs (only one connection by a given callsign+SSID on origin and destination is allowed by the AX.25 protocol). - - No practical limit do exists on the number of connections an application could sustain with different destinations, even from the same originating callsign+SSID. This concept, of course, is extended when many callsigns+SSID are registered by the same application. - - -It is an application duty, as we’ll see on the relevant frames sent by ***AGWPE\***, to discriminate among data coming from diferent connections. - - +It is an application duty, as we’ll see on the relevant frames sent by **\*AGWPE\***, to discriminate among data coming from diferent connections. Please note that the destination application must know exactly how to handle data frames with non-standard PID in order for a data exchange to take place, the connection would succeed even with destinations not truly aware of the non-standard PID (the AX.25 protocol doesn’t include PID information on a connection frame). - - - - - - ### Send Data in “raw” AX.25 format (‘K’ frame) - - On special situations when the application needs to control the exact content of a given frame (as when applications needs to deal with a hardware TNC in KISS mode) the complete frame could be built and sent using this frame. - - This facility should be used on very special applications only. - - The format of the frame follows: - - -| Field | Length | Meaning | -| ----------------- | -------- | ---------------------------------------------------- | -| ***AGWPE\*** Port | 1 Bytes | Port to send the data frame thru {0=Port1,1=Port2,…} | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘K’ (ASCII 0x4B) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00Actual origin is stated in theraw frame | -| CallTo | 10 Bytes | 10 0x00Actual destination is stated inthe raw frame | -| DataLen | 4 Bytes | Number of Data Bytes to be transferred. | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ---------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port to send the data frame thru {0=Port1,1=Port2,…} | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘K’ (ASCII 0x4B) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00Actual origin is stated in theraw frame | +| CallTo | 10 Bytes | 10 0x00Actual destination is stated inthe raw frame | +| DataLen | 4 Bytes | Number of Data Bytes to be transferred. | +| User (Reserved) | 4 Bytes | 0 | The complete frame (AX.25 header followed by data if applicable) in raw format must follow as data, the exact length of it must be reflected on the DataLen field. - - Full knowledge of the intricancies of the AX.25 must be mastered by the brave programmer trying to use this frame, for what is worth the heartfull recommendation is to try to identify other frames or combination of frames most suitable for a given purpose, so use this frame format as an absolute last resort. - - For those brave souls in need to still use it the following recommendations should be used (refer to the AX.25 Protocol documentation for the naming conventions). - - -| Field | Length | Description | -| ------- | ------------ | ------------------------------------------------------------ | +| Field | Length | Description | +| ------- | ------------ | ------------------------------------------------------------------------------- | | Flag | 1 byte | Will not be the standard 0b01111110 flag butthe “TNC” to use00=Port 116=Port 2… | -| Address | 112/360 bits | AX.25 coded Origin, Destination and (optionally) digipeaters. | -| Control | 1 byte | AX.25 Control Field | -| PID | 1 byte | AX.25 PID | -| Info | N bytes | AX.25 Information Area | +| Address | 112/360 bits | AX.25 coded Origin, Destination and (optionally) digipeaters. | +| Control | 1 byte | AX.25 Control Field | +| PID | 1 byte | AX.25 PID | +| Info | N bytes | AX.25 Information Area | - +Please note than the AX.25 FCS and the ending Flag are NOT included. No KISS escape codes nor bit stuffing is required to be performed (**\*AGWPE\*** would add them as needed). -Please note than the AX.25 FCS and the ending Flag are NOT included. No KISS escape codes nor bit stuffing is required to be performed (***AGWPE\*** would add them as needed). - - - -As per ***AGWPE\*** Version 2000.20 this frame should be used to send **only unproto information**. This is a general recommendation, still it could be used to send both connected +As per **\*AGWPE\*** Version 2000.20 this frame should be used to send **only unproto information**. This is a general recommendation, still it could be used to send both connected and unconnected information. When connected information is sent using this frame the application will not receive monitor frames (T frames) with the frames sent. Connected frames will be both received as “K” frames and the appropriate monitoring frame. - - -Even if ***AGWPE\*** handles AX.25 frames larger than 255 bytes not so many other programs could over the air, so it’s a reasonably programming practice to ensure than the length of the data to be transferred is equal to or less than 255 bytes. - - - - +Even if **\*AGWPE\*** handles AX.25 frames larger than 255 bytes not so many other programs could over the air, so it’s a reasonably programming practice to ensure than the length of the data to be transferred is equal to or less than 255 bytes. ### Activate reception of Frames in “raw” format (‘k’ Frame) - - -***AGWPE\*** send to the application all data using several frame formats (D or U for actual connected or unconnected data, I or S for monitored information, T for information the application sent, etc). - - +**\*AGWPE\*** send to the application all data using several frame formats (D or U for actual connected or unconnected data, I or S for monitored information, T for information the application sent, etc). In particular, the I and S frames (as we would see) provides some “decoding” of the information as part of the data area of the frame; things such as the AX.25 header components, NETROM circuit control and TCP/IP connection control data are parsed and included in plain ASCII before the actual data. - - The application program could, for light usages, process and decode the contents of either the ‘I’ (information) or ‘S’ (supervisory) frames. - - For more serious usages it’s likely the application would need the complete AX.25 frame and process it by it’s own means. - - -This is accomplished with this frame, the application signals ***AGWPE\*** that from this moment on all relevant information should be sent also in raw format; ***AGWPE\*** will still continue to provide information with the regular frames (D/U/I/S) and it would also send the raw version of them using ‘K’ frames. - - +This is accomplished with this frame, the application signals **\*AGWPE\*** that from this moment on all relevant information should be sent also in raw format; **\*AGWPE\*** will still continue to provide information with the regular frames (D/U/I/S) and it would also send the raw version of them using ‘K’ frames. The format of the frame would be: - +| Field | Length | Meaning | +| ------------------ | -------- | ---------------- | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘k’ (ASCII 0x6B) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 0 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ---------------- | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘k’ (ASCII 0x6B) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 0 | -| User (Reserved) | 4 Bytes | 0 | - - - -***AGWPE\*** doesn’t recognize this frame in any particular way, however, ‘K’ frames should start to flow into the application reflecting any activity at the ports. - - +**\*AGWPE\*** doesn’t recognize this frame in any particular way, however, ‘K’ frames should start to flow into the application reflecting any activity at the ports. This frame acts like a switch, the first time issued it enables the reception of raw frames while the second disables it and so on; in general on odd times it would enable and on even times it would disable. - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - |00 00 00 00 6B 00 00 00 00 00 00 00 00 00 00 00 |....k........... |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ -|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... - - - - - - - - - - +|00 00 00 00 -- -- -- -- -- -- -- -- -- -- -- -- |.... ## Frames Sent by AGWPE to the Application - - AGWPE might send information to the application basically for two main reasons: - - - In response of a query from the application. - To inform the application about some event (data arrived, monitoring frames, etc). - - The frame format is exactly the same than the previously seen used by the application side, in fact, many frames shares the same datakind, so the meaning might differ depending on the direction of the information flow. - - -A cross reference among frames sent by the application and by AGWPE could be seen in a later section of this document (See ***Frame Cross-Reference\*** on page 42) +A cross reference among frames sent by the application and by AGWPE could be seen in a later section of this document (See **\*Frame Cross-Reference\*** on page 42) ### Version Number (‘R’ frame) - - -This frame is sent by ***AGWPE\*** to the application in response of an ‘R’ frame sent to ***AGWPE\*** carrying the information about the current ***AGWPE\*** version. - - +This frame is sent by **\*AGWPE\*** to the application in response of an ‘R’ frame sent to **\*AGWPE\*** carrying the information about the current **\*AGWPE\*** version. The format of the frame would be: - +| Field | Length | Meaning | +| ------------------ | -------- | ---------------- | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘R’ (ASCII 0x52) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 8 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ---------------- | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘R’ (ASCII 0x52) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 8 | -| User (Reserved) | 4 Bytes | 0 | - - - - - -8 bytes of data would follow (as indicated by the DataLen field) containing the ***AGWPE\*** version with the following contents: - - - - +8 bytes of data would follow (as indicated by the DataLen field) containing the **\*AGWPE\*** version with the following contents: | Offset (Byte or Characters) into the Data Area | Meaning | | ---------------------------------------------- | -------------------- | @@ -1830,151 +1008,83 @@ The format of the frame would be: | +06 | not used | | +07 | not used | - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - - - - - |00 00 00 00 52 00 00 00 00 00 00 00 00 00 00 00 |....R........... |00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 |................ -|00 00 00 00 D0 07 00 00 14 00 00 00 -- -- -- -- |............ - - +|00 00 00 00 D0 07 00 00 14 00 00 00 -- -- -- -- |............ ### Callsign Registration (‘X’ Frame) - - -This frame would be sent by ***AGWPE\*** in response for a callsign registration (‘X’ frame) sent by the application. - - - - +This frame would be sent by **\*AGWPE\*** in response for a callsign registration (‘X’ frame) sent by the application. The format of the frame would be: - - -| Field | Length | Meaning | -| ----------------- | -------- | ----------------------------------------------- | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘X’ (ASCII 0x58) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Registered CallSign-SSID ended with null (0x00) | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 1 | -| User (Reserved) | 4 Bytes | 0 | - - - - +| Field | Length | Meaning | +| ------------------ | -------- | ----------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘X’ (ASCII 0x58) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Registered CallSign-SSID ended with null (0x00) | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 1 | +| User (Reserved) | 4 Bytes | 0 | 1 byte of data would follow (as indicated by the DataLen field) containing the result of the registration: - - - - | Offset (Byte or Characters) into the Data Area | Meaning | | ---------------------------------------------- | ---------------------------------------------------- | | +00 | 0x00 Registration Failed0x01 Registration Successful | - - -The application must refrain any further use of the callsign if the registration failed because it means that callsign is already in use (already registered) with ***AGWPE\***. - - +The application must refrain any further use of the callsign if the registration failed because it means that callsign is already in use (already registered) with **\*AGWPE\***. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - -|00 00 00 00 58 00 00 00 4C 55 37 44 49 44 2D 34 |....X...***LU7DID\***-4 +|00 00 00 00 58 00 00 00 4C 55 37 44 49 44 2D 34 |....X...**\*LU7DID\***-4 |00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 |................ -|00 00 00 00 01 -- -- -- -- -- -- -- -- -- -- -- |..... - - - - +|00 00 00 00 01 -- -- -- -- -- -- -- -- -- -- -- |..... ### Port Information (‘G’ Frame) - - -This frame would be sent by ***AGWPE\*** in response of a query for Port information (‘G’ frame) sent by the application. - - - - +This frame would be sent by **\*AGWPE\*** in response of a query for Port information (‘G’ frame) sent by the application. The format of the frame would be: - - - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------- | -| ***AGWPE\*** Port | 1 Bytes | 0x00 | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘G’ (ASCII 0x47) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | Length of port info | -| User (Reserved) | 4 Bytes | 0 | - - - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------- | +| **\*AGWPE\*** Port | 1 Bytes | 0x00 | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘G’ (ASCII 0x47) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | Length of port info | +| User (Reserved) | 4 Bytes | 0 | A stream of bytes would follow (as indicated by the DataLen field) containing the port data using the following format: - Total number of ports in ASCII (i.e. “1” ASCII 0x31) followed by “;”. -- A data stream for each port using the general format “Portn xxxxxxx” followed by “;” with “n” being the port number (i.e. “Port1”, “Port2”…) and “xxxxxxx” being the description of the port as seen in the Properties dialog of ***AGWPE\***. - - +- A data stream for each port using the general format “Portn xxxxxxx” followed by “;” with “n” being the port number (i.e. “Port1”, “Port2”…) and “xxxxxxx” being the description of the port as seen in the Properties dialog of **\*AGWPE\***. An example of a typical data area showing this information for two ports is - - 2;Port1 with KPC3 on COM1: 145.03 Mhz;Port2 with Loopback Port; - +The first port information belongs to the Port1, the second to Port2 and so on. The application could rely on the “;” character to “parse” the successive components; **\*AGWPE\*** guarantees that the text information won’t contain ‘;’ characters other than the ones to separate succesive information pieces. -The first port information belongs to the Port1, the second to Port2 and so on. The application could rely on the “;” character to “parse” the successive components; ***AGWPE\*** guarantees that the text information won’t contain ‘;’ characters other than the ones to separate succesive information pieces. - - - -The total length of the stream would depend on the number of ports defined with ***AGWPE\*** - - +The total length of the stream would depend on the number of ports defined with **\*AGWPE\*** Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - |00 00 00 00 47 00 00 00 00 00 00 00 00 00 00 00 |....G........... |00 00 00 00 00 00 00 00 00 00 00 00 5C 00 00 00 |............\... @@ -1991,284 +1101,164 @@ Follows a sample frame using a dump format of this frame (16 hexadecimal formatt |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................ - - - - - - - - ### Capabilities of a Port (‘g’ Frame) - - -This frame is generated by ***AGWPE\*** in response of a ‘g’ frame sent by the application and contain static configuration information as well as dynamically updated values for the particular port being queried. - - +This frame is generated by **\*AGWPE\*** in response of a ‘g’ frame sent by the application and contain static configuration information as well as dynamically updated values for the particular port being queried. The format of the frame would be: - +| Field | Length | Meaning | +| ------------------ | -------- | ----------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port being queried0x00 Port10x01 Port2 …. | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘g’ (ASCII 0x67) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 12 | +| User (Reserved) | 4 Bytes | 0 | -| Field | Length | Meaning | -| ----------------- | -------- | ----------------------------------------- | -| ***AGWPE\*** Port | 1 Bytes | Port being queried0x00 Port10x01 Port2 …. | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘g’ (ASCII 0x67) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 12 | -| User (Reserved) | 4 Bytes | 0 | +12 bytes of data would follow (as indicated by the DataLen field) containing the following information about the particular port referenced by the header’s **\*AGWPE\***Port field : - - - - -12 bytes of data would follow (as indicated by the DataLen field) containing the following information about the particular port referenced by the header’s ***AGWPE\***Port field : - - - - - -| Offset (Byte or Characters) into the Data Area | Meaning | -| ------------------------------------------------------------ | ------------------------------------------------------------ | -| +00 | On air baud rate (0=1200/1=2400/2=4800/3=9600…) | -| +01 | Traffic level (if 0xFF the port is not in autoupdate mode) | -| +02 | TX Delay | -| +03 | TX Tail | -| +04 | Persist | -| +05 | SlotTime | -| +06 | MaxFrame | -| +07 | How Many connections are active on this port | +| Offset (Byte or Characters) into the Data Area | Meaning | +| ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | +| +00 | On air baud rate (0=1200/1=2400/2=4800/3=9600…) | +| +01 | Traffic level (if 0xFF the port is not in autoupdate mode) | +| +02 | TX Delay | +| +03 | TX Tail | +| +04 | Persist | +| +05 | SlotTime | +| +06 | MaxFrame | +| +07 | How Many connections are active on this port | | +08 LSB Low Word+09 MSB Low Word+10 LSB High Word+11 MSB High Word | HowManyBytes (received in the last 2 minutes) as a 32 bits (4 bytes) integer. Updated every two minutes. | - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - -|01 00 00 00 67 00 00 00 4C 55 37 44 49 44 2D 34 |....g...***LU7DID\***-4 +|01 00 00 00 67 00 00 00 4C 55 37 44 49 44 2D 34 |....g...**\*LU7DID\***-4 |00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00 00 |................ |00 00 00 00 00 01 19 04 C8 04 07 00 01 00 00 00 |................ - - - - ### Frames Outstanding on a Port (‘y’ Frame) - +This frame is generated by **\*AGWPE\*** in response of a ‘y’ frame sent by the application and contains how many frames are waiting to be transmitted by **\*AGWPE\*** thru the indicated port (from all sources, not only from the application that makes the queries). -This frame is generated by ***AGWPE\*** in response of a ‘y’ frame sent by the application and contains how many frames are waiting to be transmitted by ***AGWPE\*** thru the indicated port (from all sources, not only from the application that makes the queries). - - - -It could (should) be used by the application to introduce a “reality check” into the amount of data being sent to ***AGWPE\*** for transmission in order to accommodate the real bandwidth of the port. - - +It could (should) be used by the application to introduce a “reality check” into the amount of data being sent to **\*AGWPE\*** for transmission in order to accommodate the real bandwidth of the port. The format of the frame would be: - - -| Field | Length | Meaning | -| ----------------- | -------- | ----------------------------------------- | -| ***AGWPE\*** Port | 1 Bytes | Port being queried0x00 Port10x01 Port2 …. | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘y’ (ASCII 0x79) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | 4 | -| User (Reserved) | 4 Bytes | 0 | - - - - +| Field | Length | Meaning | +| ------------------ | -------- | ----------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port being queried0x00 Port10x01 Port2 …. | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘y’ (ASCII 0x79) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | 4 | +| User (Reserved) | 4 Bytes | 0 | 4 bytes of data would follow (as indicated by the DataLen field) containing a 32 bits integer with the total number of frames waiting to be transmitted (outstanding frames) : - - - - -| Offset (Byte or Characters) into the Data Area | Meaning | -| ------------------------------------------------------------ | ------------------------------------------------------------ | +| Offset (Byte or Characters) into the Data Area | Meaning | +| ------------------------------------------------------------------ | --------------------------------------------------------------- | | +00 LSB Low Word+01 MSB Low Word+02 LSB High Word+03 MSB High Word | Number of Frames waiting to be transmitted on the queried port. | - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - |00 00 00 00 79 00 00 00 9C 09 58 00 A0 BE 9D 01 |....y.....X..... |98 BE 9D 01 00 00 00 00 24 00 00 00 04 00 00 00 |........$....... -|98 02 BE 00 01 00 00 00 -- -- -- -- -- -- -- -- |........ - - - - +|98 02 BE 00 01 00 00 00 -- -- -- -- -- -- -- -- |........ ### Frames Outstanding on a Connection (‘Y’ Frame) - - -This frame is conceptually similar to the previous one but referring to a particular AX.25 L2 connection (CallFrom/CallTo pair) on a given port; it’s returned by ***AGWPE\*** when queried thru a ‘Y’ frame over an existing connection. - - +This frame is conceptually similar to the previous one but referring to a particular AX.25 L2 connection (CallFrom/CallTo pair) on a given port; it’s returned by **\*AGWPE\*** when queried thru a ‘Y’ frame over an existing connection. As in the ‘y’ frame this information could (should) be used by the application to control the pace of information delivery on a given connection in order to adjust it realistically to the port bandwidth. - - The format of the frame would be: - - -| Field | Length | Meaning | -| ----------------- | -------- | ----------------------------------------- | -| ***AGWPE\*** Port | 1 Bytes | Port being queried0x00 Port10x01 Port2 …. | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘Y’ (ASCII 0x59) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Callsign-SSID ended with null (0x00) | -| CallTo | 10 Bytes | CallSign-SSID ended with null (0x00) | -| DataLen | 4 Bytes | 4 | -| User (Reserved) | 4 Bytes | 0 | - - - - +| Field | Length | Meaning | +| ------------------ | -------- | ----------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port being queried0x00 Port10x01 Port2 …. | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘Y’ (ASCII 0x59) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Callsign-SSID ended with null (0x00) | +| CallTo | 10 Bytes | CallSign-SSID ended with null (0x00) | +| DataLen | 4 Bytes | 4 | +| User (Reserved) | 4 Bytes | 0 | 4 bytes of data would follow (as indicated by the DataLen field) containing a 32 bits integer with the total number of frames waiting to be transmitted (outstanding frames) : - - - - -| Offset (Byte or Characters) into the Data Area | Meaning | -| ------------------------------------------------------------ | ------------------------------------------------------------ | +| Offset (Byte or Characters) into the Data Area | Meaning | +| ------------------------------------------------------------------ | ------------------------------------------------------------------------ | | +00 LSB Low Word+01 MSB Low Word+02 LSB High Word+03 MSB High Word | Number of Frames waiting to be transmitted on the given AX.25 connection | - - - - - - - - ### Heard Stations on a Port (‘H’ Frame) - +This frame is produced by **\*AGWPE\*** in response of an ‘H’ frame sent by the application and contains information about the stations heard by **\*AGWPE\*** on a given port. -This frame is produced by ***AGWPE\*** in response of an ‘H’ frame sent by the application and contains information about the stations heard by ***AGWPE\*** on a given port. +Upon a single ‘H’ frame sent by the application **\*AGWPE\*** would produce 20 sucessive ‘H’ frames, one for each station heard. - - -Upon a single ‘H’ frame sent by the application ***AGWPE\*** would produce 20 sucessive ‘H’ frames, one for each station heard. - - - -If on a given port more than 20 stations were heard only the 20 most recently heard would be sent, if less than 20 stations were heard ***AGWPE\*** would send as many “empty” ‘H’ frames as required to make the total number sent as 20. - - +If on a given port more than 20 stations were heard only the 20 most recently heard would be sent, if less than 20 stations were heard **\*AGWPE\*** would send as many “empty” ‘H’ frames as required to make the total number sent as 20. The frame format would be - - -| Field | Length | Meaning | -| ----------------- | -------- | ----------------------------------- | -| ***AGWPE\*** Port | 1 Bytes | Queried Port0x00 Port10x01 Port2 …. | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘H’ (ASCII 0x48) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | 10 0x00 | -| CallTo | 10 Bytes | 10 0x00 | -| DataLen | 4 Bytes | Length of heard info | -| User (Reserved) | 4 Bytes | 0 | - - - - +| Field | Length | Meaning | +| ------------------ | -------- | ----------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Queried Port0x00 Port10x01 Port2 …. | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘H’ (ASCII 0x48) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | 10 0x00 | +| CallTo | 10 Bytes | 10 0x00 | +| DataLen | 4 Bytes | Length of heard info | +| User (Reserved) | 4 Bytes | 0 | A stream of bytes would follow (as indicated by the DataLen field) containing the heard data using the following format: - - - Callsign and SSID in ASCII ended with a blank. - Timestamp of first hearing ended with a blank. - Timestamp of last hearing ended with a blank. - A null (0x00) at the end of the stream. - - An example of a typical data area showing this information would be - - -***LU7DID\***-4 Mon,21Feb2000 11:14:30 Mon,21Feb2000 12:18:22 - - +**\*LU7DID\***-4 Mon,21Feb2000 11:14:30 Mon,21Feb2000 12:18:22 After the null (0x00) signaling the end of the “plain ASCII” heard information follows two SYSTEMTIME structures containing the timestamp of the first hearing and the last hearing (see the Windows SDK help for information about this standard structure). - - The application could “parse” the timestamps and get the individual components such as day, month, year, hour, minute and seconds of both the first hearing and last hearing information or to process the information using the SYSTEMTIME structures as it best suit the programmer’s preferences. - - -Take into consideration this information is stored by ***AGWPE\*** from the moment it had been started the last time and it’s not preserved by ***AGWPE\*** across succesive starts (meaning, the heard information would be empty just after ***AGWPE\*** starts). - - +Take into consideration this information is stored by **\*AGWPE\*** from the moment it had been started the last time and it’s not preserved by **\*AGWPE\*** across succesive starts (meaning, the heard information would be empty just after **\*AGWPE\*** starts). The empty entries (used to complete up to 20 entries) would have the callsign and timestamp information not filled, so it would look like - - - - -​ 00:00:00 00:00:00 - - +​ 00:00:00 00:00:00 Unexpected data might be expected by the application on an empty frame, it’s on the application responsibility to define when an entry contain valid information or it’s just empty and should be discarded. - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|-- -- -- -- -- -- -- -- 01 00 00 00 48 00 00 00 | ....H... -|-- -- -- -- -- -- -- -- 01 00 00 00 48 00 00 00 | ....H... +|4C 55 37 44 49 44 00 00 74 BD 9D 01 00 00 00 00 |**\*LU7DID\***..t....... -|4C 55 37 44 49 44 00 00 74 BD 9D 01 00 00 00 00 |***LU7DID\***..t....... - -|F0 BE 9D 01 5A 00 00 00 68 A0 F7 BF 20 20 20 4C |....Z...h... L +|F0 BE 9D 01 5A 00 00 00 68 A0 F7 BF 20 20 20 4C |....Z...h... L |55 37 44 49 44 20 54 75 65 2C 32 32 46 65 62 32 |U7DID Tue,22Feb2 @@ -2282,282 +1272,166 @@ Follows a sample frame using a dump format of this frame (16 hexadecimal formatt |00 38 00 08 00 3E -- -- -- -- -- -- -- -- -- -- |.8...> - +### AX.25 Connection Received (‘C’ Frame) -### AX.25 Connection Received (‘C’ Frame) - - - -This frame is sent by ***AGWPE\*** to the application when an AX.25 connection has been made, either started from the application from a registered callsign+SSID or initiated by a remote node with a registered callsign+SSID. - - +This frame is sent by **\*AGWPE\*** to the application when an AX.25 connection has been made, either started from the application from a registered callsign+SSID or initiated by a remote node with a registered callsign+SSID. The frame format would be - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port where the connection had been made0x00 Port10x01 Port2 …. | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘C’ (ASCII 0x43) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Callsign+SSID who the connection has been made to(usually the remote end) ended by null (0x00) | -| CallTo | 10 Bytes | CallSign+SSID receiving the connection (usually one of our registered callsigns) ended by null (0x00) | -| DataLen | 4 Bytes | Length of connect info | -| User (Reserved) | 4 Bytes | 0 | - - - - +| Field | Length | Meaning | +| ------------------ | -------- | ----------------------------------------------------------------------------------------------------- | +| **\*AGWPE\*** Port | 1 Bytes | Port where the connection had been made0x00 Port10x01 Port2 …. | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘C’ (ASCII 0x43) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Callsign+SSID who the connection has been made to(usually the remote end) ended by null (0x00) | +| CallTo | 10 Bytes | CallSign+SSID receiving the connection (usually one of our registered callsigns) ended by null (0x00) | +| DataLen | 4 Bytes | Length of connect info | +| User (Reserved) | 4 Bytes | 0 | A stream of bytes would follow (as indicated by the DataLen field) containing the connection message. - - Depending on who started the connection the connection message could be: - - - Connection started by our application, the message would be -*** CONNECTED With {Callsign-SSID} - - +\*\*\* CONNECTED With {Callsign-SSID} - Connection started by the other station, the message would be -*** CONNECTED To Station {Callsign-SSID} - - +\*\*\* CONNECTED To Station {Callsign-SSID} The application might “parse” the message to detect whether a given connection is the result of our connection request (thru a ‘C’ frame) or initiated independently the the other end; this verification has to always be made since we could not rule out the other station independently started a connection even simultaneously with our connection request (at the very least, it should be a good programming practice to perform that verification whenever a ‘C’ frame is received). - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|01 00 00 00 43 00 00 00 4C 55 37 44 49 44 2D 33 |....C...**\*LU7DID\***-3 - +|00 2F 4C 55 37 44 49 44 2D 34 00 00 23 00 00 00 |./**\*LU7DID\***-4..#... -|01 00 00 00 43 00 00 00 4C 55 37 44 49 44 2D 33 |....C...***LU7DID\***-3 - -|00 2F 4C 55 37 44 49 44 2D 34 00 00 23 00 00 00 |./***LU7DID\***-4..#... - -|D3 73 F7 BF 2A 2A 2A 20 43 4F 4E 4E 45 43 54 45 |.s..*** CONNECTE +|D3 73 F7 BF 2A 2A 2A 20 43 4F 4E 4E 45 43 54 45 |.s..\*\*\* CONNECTE |44 20 54 6F 20 53 74 61 74 69 6F 6E 20 4C 55 37 |D To Station LU7 |44 49 44 2D 33 0D 00 -- -- -- -- -- -- -- -- -- |DID-3.. - - - - ### Connected AX.25 Data (‘D’ Frame) - - -This is a frame sent by ***AGWPE\*** to the application when an information frame part of an established AX.25 connection directed to a registered station is detected. - - +This is a frame sent by **\*AGWPE\*** to the application when an information frame part of an established AX.25 connection directed to a registered station is detected. The frame format would be - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port where the connection had been made0x00 Port10x01 Port2 …. | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘D’ (ASCII 0x44) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | AX.25 PID | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Callsign+SSID who sends the information(usually the remote end) ended by null (0x00) | -| CallTo | 10 Bytes | CallSign+SSID receiving the information (usually one of our registered callsigns) ended by null (0x00) | -| DataLen | 4 Bytes | Length of data info | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------ | +| **\*AGWPE\*** Port | 1 Bytes | Port where the connection had been made0x00 Port10x01 Port2 …. | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘D’ (ASCII 0x44) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | AX.25 PID | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Callsign+SSID who sends the information(usually the remote end) ended by null (0x00) | +| CallTo | 10 Bytes | CallSign+SSID receiving the information (usually one of our registered callsigns) ended by null (0x00) | +| DataLen | 4 Bytes | Length of data info | +| User (Reserved) | 4 Bytes | 0 | A stream of bytes would follow (as indicated by the DataLen field) containing the connected data in a fully transparent way (binary information, no delimiters, bit stuffing or escape codes), the data is as sent by the other end and could be inmediately used by the application without further processing. - - Note that the PID reflected on the frame would be 0xF0 if the connection has been established by us using the ‘C’ command, could be any non-standard PID if the connection had been established by us using the ‘c’ command and could be anything if the connection has been established by the other end. - +**\*AGWPE\*** guarantees the information is sent just once to the application in the right sequence (all the retries of information and resending of it due to link conditions is hidden from the application perspective), the frame doesn’t provide any information about the frame sequence as received on the AX.25 link, in case the application needs that information pairing of the ‘D’ frame with other monitoring information should be made by the application by it’s own means (albeit, this need should be extremely infrequent on normal uses). -***AGWPE\*** guarantees the information is sent just once to the application in the right sequence (all the retries of information and resending of it due to link conditions is hidden from the application perspective), the frame doesn’t provide any information about the frame sequence as received on the AX.25 link, in case the application needs that information pairing of the ‘D’ frame with other monitoring information should be made by the application by it’s own means (albeit, this need should be extremely infrequent on normal uses). +Note there is no limit on the amount of data sent by **\*AGWPE\*** to the application with this frame since it’s not necessarily related to a concrete AX.25 frame; so the application should not expect any given length to be used (i.e. several AX.25 frames could be bound together on a single ‘D’ frame sent by **\*AGWPE\***). - - -Note there is no limit on the amount of data sent by ***AGWPE\*** to the application with this frame since it’s not necessarily related to a concrete AX.25 frame; so the application should not expect any given length to be used (i.e. several AX.25 frames could be bound together on a single ‘D’ frame sent by ***AGWPE\***). - - - -Since ***AGWPE\*** supports the latest AX.25 specification no guarantee the frame is limited to 256 bytes do actually exist and the application should be able to process data of any arbitrary length. - - - - +Since **\*AGWPE\*** supports the latest AX.25 specification no guarantee the frame is limited to 256 bytes do actually exist and the application should be able to process data of any arbitrary length. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|01 00 00 00 44 00 F0 00 4C 55 37 44 49 44 2D 33 |....D...**\*LU7DID\***-3 - - -|01 00 00 00 44 00 F0 00 4C 55 37 44 49 44 2D 33 |....D...***LU7DID\***-3 - -|00 47 4C 55 37 44 49 44 2D 34 00 00 02 00 00 00 |.G***LU7DID\***-4...... +|00 47 4C 55 37 44 49 44 2D 34 00 00 02 00 00 00 |.G**\*LU7DID\***-4...... |A8 6D 45 00 62 0D -- -- -- -- -- -- -- -- -- -- |.mE.b. - - - - ### Monitored Connected Information (‘I’ Frame) - - -This frame is sent by ***AGWPE\*** to the application whenever any exchange of connected information is detected among any pair of stations on any port, for ***AGWPE\*** to send this information the monitoring must be previously activated by the application thru the sending of a ‘m’ frame to ***AGWPE\***. - - - - - - +This frame is sent by **\*AGWPE\*** to the application whenever any exchange of connected information is detected among any pair of stations on any port, for **\*AGWPE\*** to send this information the monitoring must be previously activated by the application thru the sending of a ‘m’ frame to **\*AGWPE\***. The frame format would be - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port where the frame has been heard0x00 Port10x01 Port2 …. | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘I’ (ASCII 0x49) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Callsign+SSID who sends the information(usually the remote end) ended by null (0x00) | -| CallTo | 10 Bytes | CallSign+SSID receiving the information (usually one of our registered callsigns) ended by null (0x00) | -| DataLen | 4 Bytes | Length of monitored info | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------ | +| **\*AGWPE\*** Port | 1 Bytes | Port where the frame has been heard0x00 Port10x01 Port2 …. | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘I’ (ASCII 0x49) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Callsign+SSID who sends the information(usually the remote end) ended by null (0x00) | +| CallTo | 10 Bytes | CallSign+SSID receiving the information (usually one of our registered callsigns) ended by null (0x00) | +| DataLen | 4 Bytes | Length of monitored info | +| User (Reserved) | 4 Bytes | 0 | A stream of bytes would follow (as indicated by the DataLen field) containing the decoded headers of the AX.25 Frames and the connected data as sent by the transmitting end and could be inmediately used by the application without further processing. - - -***AGWPE\*** also includes a decode NETROM header or a decoded TCP/IP header when the respective frame types are detected. - - +**\*AGWPE\*** also includes a decode NETROM header or a decoded TCP/IP header when the respective frame types are detected. The application might parse the information to extract both information relevant to the connected link and the actual data being interchanged. - - The AX.25 headers included in the data area of the frame usually follows the format (example) - - - 1:Fm ***LU7DID\***-4 To ***SV2AGW\***-2 [12:23:49] - - +1:Fm **\*LU7DID\***-4 To **\*SV2AGW\***-2 [12:23:49] Followed by the actual data being exchanged (binary information). - - The application might choose to process the information and extract the relevant components, if so, the following things must be considered. - - -- The AX.25 header is sent by ***AGWPE\*** in plain ASCII, no binary information, while the data itself is sent and should be handled as binary. -- The first number is the port where the information has been heard, please note it follows the convention used by ***AGWPE\*** on it’s Property Dialog and NOT the convention used on the frame headers (so “1’ means “Port1”, “2” means “Port2” and so on). -- The decoded header is presented by ***AGWPE\*** in a consistent way, first the “From” (origin) station followed by the “To” (destination) station in callsign-SSID format. +- The AX.25 header is sent by **\*AGWPE\*** in plain ASCII, no binary information, while the data itself is sent and should be handled as binary. +- The first number is the port where the information has been heard, please note it follows the convention used by **\*AGWPE\*** on it’s Property Dialog and NOT the convention used on the frame headers (so “1’ means “Port1”, “2” means “Port2” and so on). +- The decoded header is presented by **\*AGWPE\*** in a consistent way, first the “From” (origin) station followed by the “To” (destination) station in callsign-SSID format. - Then follows the AX.25 frame header data, a constant “I” meaning an information frame, followed by the Received and Sent AX.25 counters (N( R ) and N(S) on the AX.25 protocol definition) as seen by the sending application. - Follows the PID of the frame. - Follows the length of the binary information on the frame. -- Then a timestamp of the frame reception at ***AGWPE\***. - - +- Then a timestamp of the frame reception at **\*AGWPE\***. After the frame AX.25 header a CR (0x0D) follows and then the actual data in binary form. - - - - - - -Please note the application should handle TWO different lengths when handling this frame, the one stated on the header (DataLen) refers to the total amount of data transferred after the ***AGWPE\*** header (which includes BOTH the decoded AX.25 header and the binary data). - - +Please note the application should handle TWO different lengths when handling this frame, the one stated on the header (DataLen) refers to the total amount of data transferred after the **\*AGWPE\*** header (which includes BOTH the decoded AX.25 header and the binary data). A second length is the one stated on the decoded AX.25 header (Len=…) which referes to the actual amount of data transferred AFTER the header. - - The application, in order to process this frame, should - - -- First get the whole data block as stated on the ***AGWPE\*** header (DataLen). - - +- First get the whole data block as stated on the **\*AGWPE\*** header (DataLen). - Then it should parse the data block till the first CR (0x0D) character and decode it on their components (Port/From/To/DataKind/N(R) /N(S)/Pid/Len). - +- Then get as many bytes after the CR as stated in the “Len=” part of the AX.25 header decoded by **\*AGWPE\*** as plain text, those bytes (which are a binary block without an escape code, KISS masking or bit stuffing) are the actual data exchanged between both stations. -- Then get as many bytes after the CR as stated in the “Len=” part of the AX.25 header decoded by ***AGWPE\*** as plain text, those bytes (which are a binary block without an escape code, KISS masking or bit stuffing) are the actual data exchanged between both stations. +- Beware that **\*AGWPE\*** might include some few extra bytes of information after the binary block actually exchanged by the two connected stations being monitored which should be ignored by the application processing an ‘I’ frame. The application should read them in order to complete the processing of the **\*AGWPE\*** frame but later should ignore them. - - -- Beware that ***AGWPE\*** might include some few extra bytes of information after the binary block actually exchanged by the two connected stations being monitored which should be ignored by the application processing an ‘I’ frame. The application should read them in order to complete the processing of the ***AGWPE\*** frame but later should ignore them. - - - -The application should be aware on the fact that the data transmitted (or received) by it would be communicated by ***AGWPE\*** using the appropriate frame AND also thru an ‘I’ frame, so if the ‘I’ frames sent by ***AGWPE\*** are used with any functional purpose the redundancy has to be considered and solved by the application. - - +The application should be aware on the fact that the data transmitted (or received) by it would be communicated by **\*AGWPE\*** using the appropriate frame AND also thru an ‘I’ frame, so if the ‘I’ frames sent by **\*AGWPE\*** are used with any functional purpose the redundancy has to be considered and solved by the application. The conceptual thinking behind an ‘I’ frame is to provide the application with a way to provide it with “presentation” ready monitored information rather than to rely on them for any functional purpose (altrough, this could be done provided appropriate caution is taken as show above). - - -Take note that the correct PID of the monitored frame is correctly reflected on the “decoded” header provided by ***AGWPE\*** rather than on the relevant field on the ***AGWPE\*** header. - - +Take note that the correct PID of the monitored frame is correctly reflected on the “decoded” header provided by **\*AGWPE\*** rather than on the relevant field on the **\*AGWPE\*** header. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|01 00 00 00 49 00 00 00 4C 55 37 44 49 44 2D 34 |....I...**\*LU7DID\***-4 - +|00 E7 4C 55 37 44 49 44 00 FA 6A 00 6F 00 00 00 |..**\*LU7DID\***..j.o... -|01 00 00 00 49 00 00 00 4C 55 37 44 49 44 2D 34 |....I...***LU7DID\***-4 +|2C 0E 45 00 20 32 3A 46 6D 20 4C 55 37 44 49 44 |,.E. 2:Fm **\*LU7DID\*** -|00 E7 4C 55 37 44 49 44 00 FA 6A 00 6F 00 00 00 |..***LU7DID\***..j.o... - -|2C 0E 45 00 20 32 3A 46 6D 20 4C 55 37 44 49 44 |,.E. 2:Fm ***LU7DID\*** - -|2D 34 20 54 6F 20 4C 55 37 44 49 44 20 3C 49 20 |-4 To ***LU7DID\*** [10:55:55 -|5D 0D 0D 5B 4C 55 37 44 49 44 40 4C 55 37 44 49 |]..[***LU7DID\***@LU7DI +|5D 0D 0D 5B 4C 55 37 44 49 44 40 4C 55 37 44 49 |]..[**\*LU7DID\***@LU7DI |44 2D 34 5D 20 42 2C 43 2C 44 2C 45 2C 58 2C 49 |D-4] B,C,D,E,X,I @@ -2565,20 +1439,12 @@ Follows a sample frame using a dump format of this frame (16 hexadecimal formatt |0D 0D 00 -- -- -- -- -- -- -- -- -- -- -- -- -- |... - - ### Monitored Supervisory Information (‘S’ Frames) - - -Conceptually similar to the ‘I’ frames discussed before ***AGWPE\*** sends the application information regarding supervisory frames interchanged among any two stations as a part of the AX.25 connected session as stated on the AX.25 protocol in order to administer a given link. - - +Conceptually similar to the ‘I’ frames discussed before **\*AGWPE\*** sends the application information regarding supervisory frames interchanged among any two stations as a part of the AX.25 connected session as stated on the AX.25 protocol in order to administer a given link. Those frames are usually - - - SABM (Connection Request). - UA (Connection Acknowledge/Accepted). - DISC (Disconnection Request). @@ -2587,195 +1453,115 @@ Those frames are usually - RNR (Receiver not Ready) - REJ (Frame Rejected) - - Those frames doesn’t transport information other than their own meaning in the context of a given connection. - - - - The frame format would be - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port where the frame has been heard0x00 Port10x01 Port2 …. | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘S’ (ASCII 0x53) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Callsign+SSID who sends the information(usually the remote end) ended by null (0x00) | -| CallTo | 10 Bytes | CallSign+SSID receiving the information (usually one of our registered callsigns) ended by null (0x00) | -| DataLen | 4 Bytes | Length of supervisory info | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------ | +| **\*AGWPE\*** Port | 1 Bytes | Port where the frame has been heard0x00 Port10x01 Port2 …. | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘S’ (ASCII 0x53) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Callsign+SSID who sends the information(usually the remote end) ended by null (0x00) | +| CallTo | 10 Bytes | CallSign+SSID receiving the information (usually one of our registered callsigns) ended by null (0x00) | +| DataLen | 4 Bytes | Length of supervisory info | +| User (Reserved) | 4 Bytes | 0 | A stream of bytes would follow (as indicated by the DataLen field) containing the decoded headers of the AX.25 Supervisory Frames sent by the transmitting end and could be inmediately used by the application without further processing. - - The usual format of the information is as follows - +1:Fm **\*LU7DID\***-2 To **\*SV2AGW\***-11 [12:11:19] - 1:Fm ***LU7DID\***-2 To ***SV2AGW\***-11 [12:11:19] - - - -In the above example a “RR” frame is shown; all information provided by ***AGWPE\*** is formatted as plain ASCII text (no binary elements) and is “presentation ready” for the application; the application could choose to “parse” that information and use it functionally if needed. - - +In the above example a “RR” frame is shown; all information provided by **\*AGWPE\*** is formatted as plain ASCII text (no binary elements) and is “presentation ready” for the application; the application could choose to “parse” that information and use it functionally if needed. Most of the programming recommendations provided for the ‘I’ frames still does apply with the exception of no data to be associated with the frame after the header. - - Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - +|01 00 00 00 53 00 00 00 4C 55 37 44 49 44 2D 33 |....S...**\*LU7DID\***-3 - +|00 E7 4C 55 37 44 49 44 2D 34 00 00 2F 00 00 00 |..**\*LU7DID\***-4../... -|01 00 00 00 53 00 00 00 4C 55 37 44 49 44 2D 33 |....S...***LU7DID\***-3 +|2C 0E 45 00 20 32 3A 46 6D 20 4C 55 37 44 49 44 |,.E. 2:Fm **\*LU7DID\*** -|00 E7 4C 55 37 44 49 44 2D 34 00 00 2F 00 00 00 |..***LU7DID\***-4../... - -|2C 0E 45 00 20 32 3A 46 6D 20 4C 55 37 44 49 44 |,.E. 2:Fm ***LU7DID\*** - -|2D 33 20 54 6F 20 4C 55 37 44 49 44 2D 34 20 3C |-3 To ***LU7DID\***-4 < +|2D 33 20 54 6F 20 4C 55 37 44 49 44 2D 34 20 3C |-3 To **\*LU7DID\***-4 < |53 41 42 4D 20 50 3E 5B 31 30 3A 35 37 3A 35 32 |SABM P>[10:57:52 -|5D 0D 00 -- -- -- -- -- -- -- -- -- -- -- -- -- |].. - - - - +|5D 0D 00 -- -- -- -- -- -- -- -- -- -- -- -- -- |].. ### Monitored Unproto Information (‘U’ Frames) - - -Conceptually similar to the ‘I’ frames discussed before ***AGWPE\*** sends the application information regarding unnumbered (unproto) frames frames interchanged among any two stations as a part of the AX.25 connected session as stated on the AX.25 protocol in order to administer a given link. - - +Conceptually similar to the ‘I’ frames discussed before **\*AGWPE\*** sends the application information regarding unnumbered (unproto) frames frames interchanged among any two stations as a part of the AX.25 connected session as stated on the AX.25 protocol in order to administer a given link. Those frames are usually related to beacons or broadcasted data of some sort or in more advanced uses convey NETROM or TCP/IP links related information. - - - - The frame format would be - - -| Field | Length | Meaning | -| ----------------- | -------- | ------------------------------------------------------------ | -| ***AGWPE\*** Port | 1 Bytes | Port where the frame has been heard0x00 Port10x01 Port2 …. | -| Reserved | 3 Bytes | 0x00 0x00 0x00 | -| DataKind | 1 Byte | ‘U’ (ASCII 0x55) | -| Reserved | 1 Byte | 0x00 | -| PID | 1 Byte | 0x00 | -| Reserved | 1 Byte | 0x00 | -| CallFrom | 10 Bytes | Callsign+SSID who sends the information(usually the remote end) ended by null (0x00) | -| CallTo | 10 Bytes | CallSign+SSID receiving the information (usually one of our registered callsigns) ended by null (0x00) | -| DataLen | 4 Bytes | Length of unproto info | -| User (Reserved) | 4 Bytes | 0 | - - +| Field | Length | Meaning | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------------ | +| **\*AGWPE\*** Port | 1 Bytes | Port where the frame has been heard0x00 Port10x01 Port2 …. | +| Reserved | 3 Bytes | 0x00 0x00 0x00 | +| DataKind | 1 Byte | ‘U’ (ASCII 0x55) | +| Reserved | 1 Byte | 0x00 | +| PID | 1 Byte | 0x00 | +| Reserved | 1 Byte | 0x00 | +| CallFrom | 10 Bytes | Callsign+SSID who sends the information(usually the remote end) ended by null (0x00) | +| CallTo | 10 Bytes | CallSign+SSID receiving the information (usually one of our registered callsigns) ended by null (0x00) | +| DataLen | 4 Bytes | Length of unproto info | +| User (Reserved) | 4 Bytes | 0 | A stream of bytes would follow (as indicated by the DataLen field) containing the decoded headers of the AX.25 Unproto Frames sent by the transmitting end and could be inmediately used by the application without further processing. - - The usual format of the information is as follows - - - 1:Fm ***LU7DID\***-2 To ***SV2AGW\***-11 [12:11:19] - - +1:Fm **\*LU7DID\***-2 To **\*SV2AGW\***-11 [12:11:19] The application might choose to process the information and extract the relevant components, if so, the following things must be considered. - - -- The AX.25 header is sent by ***AGWPE\*** in plain ASCII, no binary information, while the data itself is sent and should be handled as binary. -- The first number is the port where the information has been heard, please note it follows the convention used by ***AGWPE\*** on it’s Property Dialog and NOT the convention used on the frame headers (so “1’ means “Port1”, “2” means “Port2” and so on). -- The decoded header is presented by ***AGWPE\*** in a consistent way, first the “From” (origin) station followed by the “To” (destination) station in callsign-SSID format. +- The AX.25 header is sent by **\*AGWPE\*** in plain ASCII, no binary information, while the data itself is sent and should be handled as binary. +- The first number is the port where the information has been heard, please note it follows the convention used by **\*AGWPE\*** on it’s Property Dialog and NOT the convention used on the frame headers (so “1’ means “Port1”, “2” means “Port2” and so on). +- The decoded header is presented by **\*AGWPE\*** in a consistent way, first the “From” (origin) station followed by the “To” (destination) station in callsign-SSID format. - Then follows the AX.25 frame header data, a constant “UI” meaning an unproto frame, as seen by the sending application. - Follows the PID of the frame. - Follows the length of the binary information on the frame. -- Then a timestamp of the frame reception at ***AGWPE\***. - - +- Then a timestamp of the frame reception at **\*AGWPE\***. After the frame AX.25 header a CR (0x0D) follows and then the actual data in binary form. - - -Please note the application should handle TWO different lengths (as if the ‘I’ frame) when handling this frame, the one stated on the header (DataLen) refers to the total amount of data transferred after the ***AGWPE\*** header (which includes BOTH the decoded AX.25 header and the binary data). - - +Please note the application should handle TWO different lengths (as if the ‘I’ frame) when handling this frame, the one stated on the header (DataLen) refers to the total amount of data transferred after the **\*AGWPE\*** header (which includes BOTH the decoded AX.25 header and the binary data). A second length is the one stated on the decoded AX.25 header (Len=…) which referes to the actual amount of data transferred AFTER the header. - - The application, in order to process this frame, should - - -- First get the whole data block as stated on the ***AGWPE\*** header (DataLen). - - +- First get the whole data block as stated on the **\*AGWPE\*** header (DataLen). - Then it should parse the data block till the first CR (0x0D) character and decode it on their components (Port/From/To/DataKind/Pid/Len). - +- Then get as many bytes after the CR as stated in the “Len=” part of the AX.25 header decoded by **\*AGWPE\*** as plain text, those bytes (which are a binary block without an escape code, KISS masking or bit stuffing) are the actual data exchanged between both stations. -- Then get as many bytes after the CR as stated in the “Len=” part of the AX.25 header decoded by ***AGWPE\*** as plain text, those bytes (which are a binary block without an escape code, KISS masking or bit stuffing) are the actual data exchanged between both stations. +- Beware that **\*AGWPE\*** might include some few extra bytes of information after the binary block actually exchanged by the two connected stations being monitored which should be ignored by the application processing an ‘I’ frame. The application should read them in order to complete the processing of the **\*AGWPE\*** frame but later should ignore them. - - - - -- Beware that ***AGWPE\*** might include some few extra bytes of information after the binary block actually exchanged by the two connected stations being monitored which should be ignored by the application processing an ‘I’ frame. The application should read them in order to complete the processing of the ***AGWPE\*** frame but later should ignore them. - - - -The application should be aware on the fact that the data transmitted (or received) by it would be communicated by ***AGWPE\*** using the appropriate frame AND also thru an ‘U’ frame, so if the ‘U’ frames sent by ***AGWPE\*** are used with any functional purpose the redundancy has to be considered and solved by the application. - - +The application should be aware on the fact that the data transmitted (or received) by it would be communicated by **\*AGWPE\*** using the appropriate frame AND also thru an ‘U’ frame, so if the ‘U’ frames sent by **\*AGWPE\*** are used with any functional purpose the redundancy has to be considered and solved by the application. The conceptual thinking behind an ‘U’ frame is to provide the application with a way to provide it with “presentation” ready monitored information rather than to rely on them for any functional purpose (altrough, this could be done provided appropriate caution is taken as show above). - +Take note that the correct PID of the monitored frame is correctly reflected on the “decoded” header provided by **\*AGWPE\*** rather than on the relevant field on the **\*AGWPE\*** header. -Take note that the correct PID of the monitored frame is correctly reflected on the “decoded” header provided by ***AGWPE\*** rather than on the relevant field on the ***AGWPE\*** header. - - - -If the unproto frame transport additional information on known formats used by other protocols such as NETROM or TCPIP ***AGWPE\*** would attempt to “decode’ them also and provide a “plain text” version of them. - - +If the unproto frame transport additional information on known formats used by other protocols such as NETROM or TCPIP **\*AGWPE\*** would attempt to “decode’ them also and provide a “plain text” version of them. Follows a sample frame using a dump format of this frame (16 hexadecimal formatted bytes at the left and the ASCII, interpretation when feasible at the right), this sample could be used for study and comparation purposes. - - - - -|01 00 00 00 55 00 00 00 4C 55 37 44 49 44 2D 34 |....U...***LU7DID\***-4 +|01 00 00 00 55 00 00 00 4C 55 37 44 49 44 2D 34 |....U...**\*LU7DID\***-4 |00 E7 4E 45 54 4D 45 00 C8 FA 6A 00 6F 00 00 00 |..NETME...j.o... -|2C 0E 45 00 20 32 3A 46 6D 20 4C 55 37 44 49 44 |,.E. 2:Fm ***LU7DID\*** +|2C 0E 45 00 20 32 3A 46 6D 20 4C 55 37 44 49 44 |,.E. 2:Fm **\*LU7DID\*** |2D 34 20 54 6F 20 4E 45 54 4D 45 20 3C 55 49 20 |-4 To NETME >> Write <<<----------------------------------------------_) -(*--->>> Write <<<----------------------------------------------*) +{_Write information to the packet engine _} -{*Write information to the packet engine *} - -{*----------------------------------------------------------------------*} +{_----------------------------------------------------------------------_} Function TLink.Write(cPort : Char; cPID : Char; cDataKind : Char; szFrom : String; szTo : String; iDataLen : DWORD; szData : String) : Boolean; - - begin { TLink.Write} - +​ {_-----------------------_} -​ {*-----------------------*} +​ {_Only write to valid _} -​ {*Only write to valid *} +​ {_sockets _} -​ {*sockets *} +​ {\* \*} -​ {* *} +{_----------------------------------------------------------------------_} -{*----------------------------------------------------------------------*} +If AGWState <> 2 then begin - +​ PutAGW(1,'**\*AGWPE\*** Not connected, ignoring Write request'); - If AGWState <> 2 then begin +​ Result := FALSE; -​ PutAGW(1,'***AGWPE\*** Not connected, ignoring Write request'); - -​ Result := FALSE; - -​ Exit; - - end; - - - - Send(AGWSocket,cPort,cPID,cDataKind,szFrom,szTo,iDataLen,szData); - - Result := TRUE; - - - -end; { TLink.Write} - - - -(*--->>> Send <<<----------------------------------------------*) - -{* Function to send a frame to ***AGWPE\*** (Low Level Routine) *} - -{*----------------------------------------------------------------------*} - -Function TLink.Send (Socket : TCustomWinSocket ; - -​ cPort : Char; - -​ cPID : Char; - -​ cDataKind : Char; - -​ szFrom : String; - -​ szTo : String; - -​ iLen : DWORD; - -​ szBuffer : String) : Boolean; - - Var - - Index : Integer; - - MSB : Byte; - - LSB : Byte; - - szFrame : String; - - szFromAux : String; - - szToAux : String; - - iBigLen : DWORD; - - szBigBuffer : String; - - dwStatus : DWORD; - - - -begin { Send } - - - -​ {*-----------------------*} - -​ {*Re-entrancy protection *} - -{*----------------------------------------------------------------------*} - - - - dwStatus := WaitForSingleObject(hAGWSend,INFINITE); - - If dwSTATUS <> WAIT_OBJECT_0 then begin - - PutAGW(1,'dwStatus <> WAIT_OBJECT_0 returned by WaitForSingleObject'); - - end; {endif} - - - - - - If ((cDataKind = 'g') or (cDataKind = 'H') or (cDataKind = 'G')) then begin - - PutAGW(1,'SEND to ***AGWPE\***:Port {'+inttostr(ord(cPort))+'} DataKind ('+cDataKind+') Pid=('+inttostr(ord(cPid))+') From <'+szFrom+'> To <'+szTo+'> Len ('+inttostr(iLen)+')'); - - end else begin - - PutAGW(1,'SEND to ***AGWPE\***:Port {'+inttostr(ord(cPort))+'} DataKind ('+cDataKind+') Pid=('+inttostr(ord(cPid))+') From <'+szFrom+'> To <'+szTo+'> Len ('+inttostr(iLen)+')'); - - end; {endif} - - - - - - - - - - DumpHex(4,szBuffer); - - - -​ {*-----------------------*} - -​ {*does we have a live *} - -​ {*connection already? *} - -​ {*If NOT -> Error *} - -{*----------------------------------------------------------------------*} - - If Socket = Nil then begin - - PutAGW(1,'SEND: Socket = Nil, frame discarded'); - - ReleaseSemaphore(hAGWSend,+1,Nil); - - Result := FALSE; - - Exit; - - End; - - - -​ {*-----------------------*} - -​ {*Init buffer and temp *} - -​ {*areas *} - -​ {* *} - -{*----------------------------------------------------------------------*} - - szFrame := ''; - - szFromAux := szFrom; - - szToAux := szTo; - - - -​ {*-----------------------*} - -​ {*Ensure the whole header*} - -​ {*is filled with nulls *} - -​ {*as well as the callsign*} - -{*----------------------------------------------------------------------*} - - szFrame := PadStr(szFrame,AGW_HEADER,NUL); - - szFromAux := PadStr(szFromAux,10,NUL); - - szToAux := PadStr(szToAux,10,NUL); - - - -​ {*-----------------------*} - -​ {*Format the frame *} - -​ {* *} - -​ {* *} - -{*----------------------------------------------------------------------*} - - - - szFrame[01] := Chr(ord(cPort)-1); {* Port *} - - If szFrame[01] = Chr($FF) then begin - - szFrame[01] := Chr($00); - - end; {endif} - - - - szFrame[02] := NUL; - - szFrame[03] := NUL; - - szFrame[04] := NUL; - - - - szFrame[05] := cDataKind; {* LOWord(DataKind) *} - - szFrame[06] := NUL; - - szFrame[07] := cPID; {* HiWord(bPID) *} - - szFrame[08] := NUL; - - - - For Index := 1 to 10 do begin {* From Call *} - - szFrame[08+Index] := szFromAux[Index]; - - end; {endfor} - - - - For Index := 1 to 10 do begin {* To Call *} - - szFrame[18+Index] := szToAux[Index]; - - end; {endfor} - - - - If iLen <= (MAXFRAME-1) then begin - - MSB := Trunc(iLen/MAXFRAME); - - LSB := Trunc(iLen - (MSB*MAXFRAME)); - - end else begin - - MSB := $00; - - LSB := $FF; - - end; {endif} - - - - szFrame[29] := chr(LSB); {* Size *} - - szFrame[30] := chr(MSB); - - szFrame[31] := NUL; - - szFrame[32] := NUL; - - - - szFrame[33] := NUL; {* User - Reserved *} - - szFrame[34] := NUL; - - szFrame[35] := NUL; - - szFrame[36] := NUL; - - - - PutAGW(1,'Frame to send to ***AGWPE\*** is'); - - DumpHex(1,szFrame+szBuffer); - - - - - -​ {*-----------------------*} - -​ {*Efficiency trick *} - -​ {*If there is data send *} - -​ {*with the frame,othewise*} - -​ {*send just the frame *} - -​ {*This will reduce the *} - -​ {*chances for TCP to frag*} - -{*----------------------------------------------------------------------*} - - If (iLen = 0) then begin - - PutAGW(3,'Send Header'); - - DumpHex(3,szFrame); - - SendAGW(szFrame); - - - - - - end else begin - - If (iLen <= (MAXFRAME-1)) then begin - -​ PutAGW(3,'Send Header+Data'); - -​ DumpHex(3,szFrame+szBuffer); - -​ SendAGW(szFrame+szBuffer); - - end else begin - - - -​ {*-----------------------*} - -​ {*Handles data areas *} - -​ {*longer than 256 bytes *} - -​ {*in sucessive frames *} - -​ {*of up to 256 bytes *} - -{*----------------------------------------------------------------------*} - -​ SendAGW(szFrame+Copy(szBuffer,1,(MAXFRAME-1))); - - - -​ szBigBuffer := Copy(szBuffer,MAXFRAME,Length(szBuffer)-(MAXFRAME-1)); - -​ iBigLen := Length(szBigBuffer); - - - -​ ReleaseSemaphore(hAGWSend,+1,Nil); - - - -​ Self.Send(Socket,cPort,cPid,cDataKind,szFrom,szTo,iBigLen,szBigBuffer); - -​ If cDataKind <> 'Y' then begin - -​ Self.Send(Socket,cPort,NUL,'Y',szFrom,szTo,0,''); - -​ end; {endif} - - - -​ Result := TRUE; - -​ Exit; - - end; {endif} - - end; {endif} - - - - ReleaseSemaphore(hAGWSend,+1,Nil); - - - - - -​ {*-----------------------*} - -​ {*Piggyback a request *} - -​ {*for AGW Status on every*} - -​ {*Data Frame Sent *} - -​ {* *} - -{*----------------------------------------------------------------------*} - - - - If cDataKind = 'D' then begin - - Self.Send(Socket,cPort,NUL,'Y',szFrom,szTo,0,''); - - end; {endif} - - Result := TRUE; - - - -end; { Send } - - - -(*--->>> SendAGW <<<----------------------------------------------*) - -{* Function to send at low level (TCPIP) the actual frame *} - -{*----------------------------------------------------------------------*} - -Procedure TLink.SendAGW( szBuffer : String); - - - -begin { TLink } - - PutAGW(1,'Send to ***AGWPE\*** (TCP/IP)'); - - DumpHex(1,szBuffer); - - If AGWSocket <> Nil then begin - -​ AGWSocket.SendText(szBuffer); - - end else begin - -​ PutAGW(1,'AGW Frame IGNORED because ***AGWPE\*** is not connected'); - - end; {endif} +​ Exit; end; - +Send(AGWSocket,cPort,cPID,cDataKind,szFrom,szTo,iDataLen,szData); + +Result := TRUE; + +end; { TLink.Write} + +(_--->>> Send <<<----------------------------------------------_) + +{\* Function to send a frame to **\*AGWPE\*** (Low Level Routine) \*} + +{_----------------------------------------------------------------------_} + +Function TLink.Send (Socket : TCustomWinSocket ; + +​ cPort : Char; + +​ cPID : Char; + +​ cDataKind : Char; + +​ szFrom : String; + +​ szTo : String; + +​ iLen : DWORD; + +​ szBuffer : String) : Boolean; + +Var + +Index : Integer; + +MSB : Byte; + +LSB : Byte; + +szFrame : String; + +szFromAux : String; + +szToAux : String; + +iBigLen : DWORD; + +szBigBuffer : String; + +dwStatus : DWORD; + +begin { Send } + +​ {_-----------------------_} + +​ {_Re-entrancy protection _} + +{_----------------------------------------------------------------------_} + +dwStatus := WaitForSingleObject(hAGWSend,INFINITE); + +If dwSTATUS <> WAIT_OBJECT_0 then begin + +PutAGW(1,'dwStatus <> WAIT_OBJECT_0 returned by WaitForSingleObject'); + +end; {endif} + +If ((cDataKind = 'g') or (cDataKind = 'H') or (cDataKind = 'G')) then begin + +PutAGW(1,'SEND to **\*AGWPE\***:Port {'+inttostr(ord(cPort))+'} DataKind ('+cDataKind+') Pid=('+inttostr(ord(cPid))+') From <'+szFrom+'> To <'+szTo+'> Len ('+inttostr(iLen)+')'); + +end else begin + +PutAGW(1,'SEND to **\*AGWPE\***:Port {'+inttostr(ord(cPort))+'} DataKind ('+cDataKind+') Pid=('+inttostr(ord(cPid))+') From <'+szFrom+'> To <'+szTo+'> Len ('+inttostr(iLen)+')'); + +end; {endif} + +DumpHex(4,szBuffer); + +​ {_-----------------------_} + +​ {_does we have a live _} + +​ {_connection already? _} + +​ {_If NOT -> Error _} + +{_----------------------------------------------------------------------_} + +If Socket = Nil then begin + +PutAGW(1,'SEND: Socket = Nil, frame discarded'); + +ReleaseSemaphore(hAGWSend,+1,Nil); + +Result := FALSE; + +Exit; + +End; + +​ {_-----------------------_} + +​ {_Init buffer and temp _} + +​ {_areas _} + +​ {\* \*} + +{_----------------------------------------------------------------------_} + +szFrame := ''; + +szFromAux := szFrom; + +szToAux := szTo; + +​ {_-----------------------_} + +​ {_Ensure the whole header_} + +​ {_is filled with nulls _} + +​ {_as well as the callsign_} + +{_----------------------------------------------------------------------_} + +szFrame := PadStr(szFrame,AGW_HEADER,NUL); + +szFromAux := PadStr(szFromAux,10,NUL); + +szToAux := PadStr(szToAux,10,NUL); + +​ {_-----------------------_} + +​ {_Format the frame _} + +​ {\* \*} + +​ {\* \*} + +{_----------------------------------------------------------------------_} + +szFrame[01] := Chr(ord(cPort)-1); {_ Port _} + +If szFrame[01] = Chr($FF) then begin + +szFrame[01] := Chr($00); + +end; {endif} + +szFrame[02] := NUL; + +szFrame[03] := NUL; + +szFrame[04] := NUL; + +szFrame[05] := cDataKind; {_ LOWord(DataKind) _} + +szFrame[06] := NUL; + +szFrame[07] := cPID; {_ HiWord(bPID) _} + +szFrame[08] := NUL; + +For Index := 1 to 10 do begin {_ From Call _} + +szFrame[08+Index] := szFromAux[Index]; + +end; {endfor} + +For Index := 1 to 10 do begin {_ To Call _} + +szFrame[18+Index] := szToAux[Index]; + +end; {endfor} + +If iLen <= (MAXFRAME-1) then begin + +MSB := Trunc(iLen/MAXFRAME); + +LSB := Trunc(iLen - (MSB\*MAXFRAME)); + +end else begin + +MSB := $00; + +LSB := $FF; + +end; {endif} + +szFrame[29] := chr(LSB); {_ Size _} + +szFrame[30] := chr(MSB); + +szFrame[31] := NUL; + +szFrame[32] := NUL; + +szFrame[33] := NUL; {_ User - Reserved _} + +szFrame[34] := NUL; + +szFrame[35] := NUL; + +szFrame[36] := NUL; + +PutAGW(1,'Frame to send to **\*AGWPE\*** is'); + +DumpHex(1,szFrame+szBuffer); + +​ {_-----------------------_} + +​ {_Efficiency trick _} + +​ {_If there is data send _} + +​ {_with the frame,othewise_} + +​ {_send just the frame _} + +​ {_This will reduce the _} + +​ {_chances for TCP to frag_} + +{_----------------------------------------------------------------------_} + +If (iLen = 0) then begin + +PutAGW(3,'Send Header'); + +DumpHex(3,szFrame); + +SendAGW(szFrame); + +end else begin + +If (iLen <= (MAXFRAME-1)) then begin + +​ PutAGW(3,'Send Header+Data'); + +​ DumpHex(3,szFrame+szBuffer); + +​ SendAGW(szFrame+szBuffer); + +end else begin + +​ {_-----------------------_} + +​ {_Handles data areas _} + +​ {_longer than 256 bytes _} + +​ {_in sucessive frames _} + +​ {_of up to 256 bytes _} + +{_----------------------------------------------------------------------_} + +​ SendAGW(szFrame+Copy(szBuffer,1,(MAXFRAME-1))); + +​ szBigBuffer := Copy(szBuffer,MAXFRAME,Length(szBuffer)-(MAXFRAME-1)); + +​ iBigLen := Length(szBigBuffer); + +​ ReleaseSemaphore(hAGWSend,+1,Nil); + +​ Self.Send(Socket,cPort,cPid,cDataKind,szFrom,szTo,iBigLen,szBigBuffer); + +​ If cDataKind <> 'Y' then begin + +​ Self.Send(Socket,cPort,NUL,'Y',szFrom,szTo,0,''); + +​ end; {endif} + +​ Result := TRUE; + +​ Exit; + +end; {endif} + +end; {endif} + +ReleaseSemaphore(hAGWSend,+1,Nil); + +​ {_-----------------------_} + +​ {_Piggyback a request _} + +​ {_for AGW Status on every_} + +​ {_Data Frame Sent _} + +​ {\* \*} + +{_----------------------------------------------------------------------_} + +If cDataKind = 'D' then begin + +Self.Send(Socket,cPort,NUL,'Y',szFrom,szTo,0,''); + +end; {endif} + +Result := TRUE; + +end; { Send } + +(_--->>> SendAGW <<<----------------------------------------------_) + +{_ Function to send at low level (TCPIP) the actual frame _} + +{_----------------------------------------------------------------------_} + +Procedure TLink.SendAGW( szBuffer : String); + +begin { TLink } + +PutAGW(1,'Send to **\*AGWPE\*** (TCP/IP)'); + +DumpHex(1,szBuffer); + +If AGWSocket <> Nil then begin + +​ AGWSocket.SendText(szBuffer); + +end else begin + +​ PutAGW(1,'AGW Frame IGNORED because **\*AGWPE\*** is not connected'); + +end; {endif} + +end; Complex?…. A little, however once invested here look what means to send an unproto beacon to all available ports…. - +….. - ….. +sMessage := ‘Hello World!’+Chr($0D); - sMessage := ‘Hello World!’+Chr($0D); +For iPort = 0 to iMaxPorts do begin - For iPort = 0 to iMaxPorts do begin +​ Self.Write(Chr(iPort),Chr($F0),’M’, -​ Self.Write(Chr(iPort),Chr($F0),’M’, +​ sMyCall,’BEACON’,Length(sMessage),sMessage); -​ sMyCall,’BEACON’,Length(sMessage),sMessage); +end; - end; - - ….. - - - - +….. There could be another couple of zillion ways to do this work (even far more efficiently) and everybody is encouraged to find it’s own way. - - - - - - ### Receive Frames - +Receive and processing **\*AGWPE\*** frames isn’t quantum physics nor rocket science, it’s deceptively simple once a couple of issues are properly addressed. -Receive and processing ***AGWPE\*** frames isn’t quantum physics nor rocket science, it’s deceptively simple once a couple of issues are properly addressed. +In order to understand the proper way to process an **\*AGWPE\*** frame a golden rule must be understood. - - - - -In order to understand the proper way to process an ***AGWPE\*** frame a golden rule must be understood. - - - -TCP/IP doesn’t guarantees the data would arrive at the destination blocked in the same way than was blocked on the transmision end. In other words, ***AGWPE\*** could send in one end a perfectly formatted frame complete with header and data at once on a single TCP send call. - - +TCP/IP doesn’t guarantees the data would arrive at the destination blocked in the same way than was blocked on the transmision end. In other words, **\*AGWPE\*** could send in one end a perfectly formatted frame complete with header and data at once on a single TCP send call. At the other end, however, and due to TCP and (specially) IP fragmentation factors, the data could be made available to the application as it’s received and not necessarily as the same block that has been sent. - - So the application must deal with the following situations. - - - The block of data received isn’t a complete frame. - A fragment of the header. - A complete header but incomplete data. -- The block of data received is a complete ***AGWPE\*** frame. -- The block of data received contains more than one completed ***AGWPE\*** frame. -- The block of data received contains several completed ***AGWPE\*** frames and the fragment of one. +- The block of data received is a complete **\*AGWPE\*** frame. +- The block of data received contains more than one completed **\*AGWPE\*** frame. +- The block of data received contains several completed **\*AGWPE\*** frames and the fragment of one. - +So, you could decide to follow this advice and save yourself many hours of frustration and debugging or find it by yourself the hard way…. **\*“never assume anything about how the data arrives to the application”\*** -So, you could decide to follow this advice and save yourself many hours of frustration and debugging or find it by yourself the hard way…. ***“never assume anything about how the data arrives to the application”\*** +The recommended way to process **\*AGWPE\*** frames is to tackle that activity as three differenciated stages: - - -The recommended way to process ***AGWPE\*** frames is to tackle that activity as three differenciated stages: - - - -- Receive whatever arrives thru the TCP/IP connection and store it somewhere as a bulk of data without any attempt to extract any meaning of it (this “somewhere” should be some buffer, big enough to held several BIG ***AGWPE\*** frames and persistent across different invocations to the receiving method). +- Receive whatever arrives thru the TCP/IP connection and store it somewhere as a bulk of data without any attempt to extract any meaning of it (this “somewhere” should be some buffer, big enough to held several BIG **\*AGWPE\*** frames and persistent across different invocations to the receiving method). - Every time data arrives to the application and is stored on the buffer examine this buffer with the following high level logic: - See if the buffer contains at least 36 bytes already, if not, just go do something else. - If at least 36 bytes exists a complete frame header had arrived, the frame might or might not have data. @@ -3859,18 +2313,10 @@ The recommended way to process ***AGWPE\*** frames is to tackle that activity as - If after the removal of the frame just processed there are 36 bytes or more still on the buffer there is a good chance that another frame is ready for processing, so call recursively this routine to process it. - A decoding routine should cascade thru a switch or case structure where every relevant DataKind is handled, frame types not relevant to the application are then ignored. - - - - -This is the method recommended by George (***SV2AGW\***) - - +This is the method recommended by George (**\*SV2AGW\***) Don't assume that you will receive a complete frame,TCPIP may send to your program part of a frame or more than a frame so the procedure for reading data is like reading from a file.Read only what you need. Like - - A complete frame is HEADER+DATA or just HEADER with no data 1.check to see if in the stream socket there are at least HEADER bytes. If not then return @@ -3883,980 +2329,750 @@ A complete frame is HEADER+DATA or just HEADER with no data 5.go to step 1 again till all the frames read. - - Follow these steps carefully. If your application is running in the same machine with agw packet engine then the usal is that you will receive more than a frame ,if the monitor traffic is large. - - -Follow some of the routines used by Pedro (***LU7DID\***) written in Delphi4 with the same purpose. - - +Follow some of the routines used by Pedro (**\*LU7DID\***) written in Delphi4 with the same purpose. This routine is the OnRead event (some TCP/IP implementation calls it OnDataAvailable) handler, it’s activated anytime data is ready to be processed from TCP/IP, this is the first stage recommended previously. - +(_--->>> AGWSocketRead <<<---------------------------------------_) -(*--->>> AGWSocketRead <<<---------------------------------------*) +{_ Receives the OK from the connection request _} -{* Receives the OK from the connection request *} - -{*----------------------------------------------------------------------*} +{_----------------------------------------------------------------------_} procedure TLink.AGWSocketRead(Sender: TObject; -​ Socket: TCustomWinSocket); +​ Socket: TCustomWinSocket); - Var +Var - szData : String; - - +szData : String; begin - PutAGW(3,'Data Available from ***AGWPE\*** '); +PutAGW(3,'Data Available from **\*AGWPE\*** '); - +szData := Socket.ReceiveText; - szData := Socket.ReceiveText; +DumpHex(3,szData); - DumpHex(3,szData); +If Length(szData) <> 0 then begin - +​ Store(szData); - If Length(szData) <> 0 then begin - -​ Store(szData); - - end; {endif} - - +end; {endif} end; - - The following method decides whether or not completed frames are ready for processing, the Decode routine is the one actually handling the different frames, see how the routine is called recursively. - +(_--->>> Store <<<----------------------------------------------_) -(*--->>> Store <<<----------------------------------------------*) +{\*Store the information from **\*AGWPE\*** and handles fragmentation issues \*} -{*Store the information from ***AGWPE\*** and handles fragmentation issues *} - -{*----------------------------------------------------------------------*} +{_----------------------------------------------------------------------_} Function TLink.Store (szReceived : String) : Boolean; - Var +Var - szHeader : String; +szHeader : String; - MSB : Integer; +MSB : Integer; - LSB : Integer; +LSB : Integer; - Index : Integer; - - +Index : Integer; begin - +PutAGW(5,'Received from TCPIP'); - PutAGW(5,'Received from TCPIP'); +DumpHex(5,szReceived); - DumpHex(5,szReceived); +AGW.Buffer := AGW.Buffer + szReceived; - +if AGW.Pending = FALSE then begin - AGW.Buffer := AGW.Buffer + szReceived; +{_----------------------------------_} - +{_This is where it comes for a fresh_} - if AGW.Pending = FALSE then begin +{\*packet from **\*AGWPE\*** \*} - +{_----------------------------------_} - {*----------------------------------*} +if Length(AGW.Buffer) >= AGW_HEADER then begin - {*This is where it comes for a fresh*} +​ szHeader := Copy(AGW.Buffer,1,AGW_HEADER); - {*packet from ***AGWPE\*** *} +​ PutAGW(5,'Translated into Header Buffer'); - {*----------------------------------*} +​ DumpHex(5,szHeader); - +​ If Length(AGW.Buffer) > 0 then begin - if Length(AGW.Buffer) >= AGW_HEADER then begin +​ AGW.Buffer := Copy(AGW.Buffer,AGW_HEADER+1,Length(AGW.Buffer)-AGW_HEADER); - +​ end; {endif} -​ szHeader := Copy(AGW.Buffer,1,AGW_HEADER); +​ AGW.Data := ''; -​ PutAGW(5,'Translated into Header Buffer'); +​ If szHeader[1] = Chr($31) then begin -​ DumpHex(5,szHeader); +​ AGW.Buffer := Copy(AGW.Buffer,2,Length(AGW.Buffer)-1); - +​ Self.Store(''); - +​ Result := TRUE; -​ If Length(AGW.Buffer) > 0 then begin +​ Exit; -​ AGW.Buffer := Copy(AGW.Buffer,AGW_HEADER+1,Length(AGW.Buffer)-AGW_HEADER); +​ end; {endif} -​ end; {endif} +​ AGW.cPort := szHeader[1]; - +​ AGW.cPort := Chr(ord(AGW.cPort)+1); -​ AGW.Data := ''; +​ AGW.DataKind := szHeader[5]; -​ If szHeader[1] = Chr($31) then begin +​ AGW.cPID := szHeader[7]; -​ AGW.Buffer := Copy(AGW.Buffer,2,Length(AGW.Buffer)-1); +​ AGW.CallFrom := ''; -​ Self.Store(''); +​ AGW.CallTo := ''; -​ Result := TRUE; +​ For Index := 9 to 18 do begin -​ Exit; +​ If szHeader[Index] <> NUL then begin -​ end; {endif} +​ AGW.CallFrom := AGW.CallFrom + szHeader[Index]; - +​ end else begin -​ AGW.cPort := szHeader[1]; +​ Break; -​ AGW.cPort := Chr(ord(AGW.cPort)+1); +​ end; {endif} - +​ end; {endfor} -​ AGW.DataKind := szHeader[5]; +​ For Index := 19 to 28 do begin -​ AGW.cPID := szHeader[7]; +​ If szHeader[Index] <> NUL then begin - +​ AGW.CallTo := AGW.CallTo + szHeader[Index]; -​ AGW.CallFrom := ''; +​ end else begin -​ AGW.CallTo := ''; +​ Break; - +​ end; {endif} -​ For Index := 9 to 18 do begin +​ end; {endfor} -​ If szHeader[Index] <> NUL then begin +​ LSB := ord(szHeader[29]); -​ AGW.CallFrom := AGW.CallFrom + szHeader[Index]; +​ MSB := ord(szHeader[30]); -​ end else begin +​ AGW.DataLen := MSB\*MAXFRAME + LSB; -​ Break; +​ PutAGW(3,'Just Decoded as Port('+inttostr(ord(AGW.cPort))+') Kind['+AGW.DataKind+'] {'+HexByte(Ord(AGW.cPID))+'} <'+AGW.CallFrom+ -​ end; {endif} +​ '> <'+AGW.CallTo+'> Len('+inttostr(AGW.DataLen)+') + <<--Store'); -​ end; {endfor} +​ {_----------------------------------_} - +​ {_If DataLen is zero there is no _} -​ For Index := 19 to 28 do begin +​ {_data, HOWEVER other frames could _} -​ If szHeader[Index] <> NUL then begin +​ {_be pending as well _} -​ AGW.CallTo := AGW.CallTo + szHeader[Index]; +​ {_----------------------------------_} -​ end else begin +​ If (AGW.DataLen = 0) then begin -​ Break; +​ {_----------------------------------_} -​ end; {endif} +​ {_A frame were received and has no _} -​ end; {endfor} +​ {_data, we might call it a complete _} - +​ {_frame so store it on the port _} -​ LSB := ord(szHeader[29]); +​ {_object. _} -​ MSB := ord(szHeader[30]); +​ {_----------------------------------_} - +​ AGW.Pending := FALSE; -​ AGW.DataLen := MSB*MAXFRAME + LSB; +​ {_----------------------------------_} - +​ {_Store the frame on that port obj _} -​ PutAGW(3,'Just Decoded as Port('+inttostr(ord(AGW.cPort))+') Kind['+AGW.DataKind+'] {'+HexByte(Ord(AGW.cPID))+'} <'+AGW.CallFrom+ +​ {_----------------------------------_} -​ '> <'+AGW.CallTo+'> Len('+inttostr(AGW.DataLen)+') + <<--Store'); +​ PutAGW(3,'Decoded Port{'+inttostr(ord(AGW.cPort))+'} DataKind['+AGW.DataKind+'] <'+AGW.CallFrom+'> <'+AGW.CallTo+'> {NO DATA}'); -​ {*----------------------------------*} +​ Decode(AGW.cPort,AGW.cPID,AGW.DataKind,AGW.CallFrom,AGW.CallTo,0,''); -​ {*If DataLen is zero there is no *} +​ Result := TRUE; -​ {*data, HOWEVER other frames could *} +​ {_----------------------------------_} -​ {*be pending as well *} +​ {_Wonder if something else came with_} -​ {*----------------------------------*} +​ {_that frame and still in the buffer_} -​ If (AGW.DataLen = 0) then begin +​ {_----------------------------------_} - +​ If Length(AGW.Buffer) = 0 then begin -​ {*----------------------------------*} +​ {_----------------------------------_} -​ {*A frame were received and has no *} +​ {_Buffer is empty, see ya next time _} -​ {*data, we might call it a complete *} +​ {\* \*} -​ {*frame so store it on the port *} +​ {_----------------------------------_} -​ {*object. *} +​ end else begin -​ {*----------------------------------*} +​ {_----------------------------------_} - +​ {_Ooops, something else there _} -​ AGW.Pending := FALSE; +​ {_recurse on myself to process _} -​ {*----------------------------------*} +​ {_----------------------------------_} -​ {*Store the frame on that port obj *} +​ Result := Self.Store(''); -​ {*----------------------------------*} +​ end; {endif} - +​ Exit; -​ PutAGW(3,'Decoded Port{'+inttostr(ord(AGW.cPort))+'} DataKind['+AGW.DataKind+'] <'+AGW.CallFrom+'> <'+AGW.CallTo+'> {NO DATA}'); +​ end; {endif} -​ Decode(AGW.cPort,AGW.cPID,AGW.DataKind,AGW.CallFrom,AGW.CallTo,0,''); +​ {_----------------------------------_} - +​ {_If DataLen is NOT zero then _} -​ Result := TRUE; +​ {_continue processing the buffer to _} - +​ {_see if we could extract the data _} -​ {*----------------------------------*} +​ {_----------------------------------_} -​ {*Wonder if something else came with*} +​ Result := Self.FragFrame; -​ {*that frame and still in the buffer*} +​ Exit; -​ {*----------------------------------*} +end; {endif} - +end else begin -​ If Length(AGW.Buffer) = 0 then begin +Result := Self.FragFrame; - +Exit; -​ {*----------------------------------*} +end; {endif} -​ {*Buffer is empty, see ya next time *} - -​ {* *} - -​ {*----------------------------------*} - -​ end else begin - -​ {*----------------------------------*} - -​ {*Ooops, something else there *} - -​ {*recurse on myself to process *} - -​ {*----------------------------------*} - -​ Result := Self.Store(''); - -​ end; {endif} - - - - - -​ Exit; - - - -​ end; {endif} - - - -​ {*----------------------------------*} - -​ {*If DataLen is NOT zero then *} - -​ {*continue processing the buffer to *} - -​ {*see if we could extract the data *} - -​ {*----------------------------------*} - -​ Result := Self.FragFrame; - -​ Exit; - - - - end; {endif} - - - - end else begin - - - - Result := Self.FragFrame; - - Exit; - - - - end; {endif} - - Result := TRUE; - - +Result := TRUE; end; -(*--->>> FragFrame <<<----------------------------------------------*) +(_--->>> FragFrame <<<----------------------------------------------_) -{*Method to handle the likely fragmentation of frames over a TCPIP link *} +{_Method to handle the likely fragmentation of frames over a TCPIP link _} -{*----------------------------------------------------------------------*} +{_----------------------------------------------------------------------_} Function TLink.FragFrame : Boolean; - - begin { TLink } - +​ {_----------------------------------_} -​ {*----------------------------------*} +​ {_If DataLen is NOT zero then _} -​ {*If DataLen is NOT zero then *} +​ {_continue processing the buffer to _} -​ {*continue processing the buffer to *} +​ {_see if we could extract the data _} -​ {*see if we could extract the data *} +​ {_----------------------------------_} -​ {*----------------------------------*} +If Length(AGW.Buffer) >= AGW.DataLen then begin - If Length(AGW.Buffer) >= AGW.DataLen then begin +AGW.Data := Copy(AGW.Buffer,1,AGW.DataLen); - +If Length(AGW.Data) < Length(AGW.Buffer) then begin - AGW.Data := Copy(AGW.Buffer,1,AGW.DataLen); +​ AGW.Buffer:= Copy(AGW.Buffer,Length(AGW.Data)+1,Length(AGW.Buffer)-Length(AGW.Data)); - +end else begin - If Length(AGW.Data) < Length(AGW.Buffer) then begin +​ AGW.Buffer := ''; -​ AGW.Buffer:= Copy(AGW.Buffer,Length(AGW.Data)+1,Length(AGW.Buffer)-Length(AGW.Data)); +end; {endif} - end else begin +AGW.Pending := FALSE; -​ AGW.Buffer := ''; +​ {_----------------------------------_} - end; {endif} +​ {_Store the frame on that port obj _} - +​ {_instance _} - AGW.Pending := FALSE; +​ {_Same solution than previous _} -​ {*----------------------------------*} +​ {_----------------------------------_} -​ {*Store the frame on that port obj *} +PutAGW(3,'Decoded (Frag) Port{'+inttostr(ord(AGW.cPort))+'} DataKind['+AGW.DataKind+'] <'+AGW.CallFrom+'> <'+AGW.CallTo+'> Len=('+inttostr(AGW.DataLen)+') Data: '+AGW.Data); -​ {*instance *} +Decode(AGW.cPort,AGW.cPID,AGW.DataKind,AGW.CallFrom,AGW.CallTo,AGW.DataLen,AGW.Data); -​ {*Same solution than previous *} +Result := TRUE; -​ {*----------------------------------*} +​ {_----------------------------------_} - +​ {_Wonder if something else came with_} - PutAGW(3,'Decoded (Frag) Port{'+inttostr(ord(AGW.cPort))+'} DataKind['+AGW.DataKind+'] <'+AGW.CallFrom+'> <'+AGW.CallTo+'> Len=('+inttostr(AGW.DataLen)+') Data: '+AGW.Data); +​ {_that frame and still in the buffer_} - Decode(AGW.cPort,AGW.cPID,AGW.DataKind,AGW.CallFrom,AGW.CallTo,AGW.DataLen,AGW.Data); +​ {_----------------------------------_} - +If Length(AGW.Buffer) = 0 then begin - Result := TRUE; +​ {_----------------------------------_} - +​ {_Buffer is empty, see ya next time _} -​ {*----------------------------------*} +​ {\* \*} -​ {*Wonder if something else came with*} +​ {_----------------------------------_} -​ {*that frame and still in the buffer*} +end else begin -​ {*----------------------------------*} +​ {_----------------------------------_} - +​ {_Ooops, something else there _} - If Length(AGW.Buffer) = 0 then begin +​ {_recurse on myself to process _} - +​ {_----------------------------------_} -​ {*----------------------------------*} +​ Result := Self.Store(''); -​ {*Buffer is empty, see ya next time *} +end; {endif} -​ {* *} +Exit; -​ {*----------------------------------*} +end else begin - end else begin +AGW.Pending := TRUE; -​ {*----------------------------------*} +Result := FALSE; -​ {*Ooops, something else there *} +Exit; -​ {*recurse on myself to process *} +end; {endif} -​ {*----------------------------------*} - -​ Result := Self.Store(''); - - end; {endif} - - - - - - Exit; - - - - end else begin - - - - AGW.Pending := TRUE; - - Result := FALSE; - - Exit; - - - - end; {endif} - - Result := TRUE; - - +Result := TRUE; end; { TLink } - - - - Last, but not least, the actual actions for each frame received, this is a method very application specific so only the skeleton is provided as a sample (despite its length this is a conceptually simple skeleton). - +(_--->>> Decode <<<----------------------------------------------_) -(*--->>> Decode <<<----------------------------------------------*) +{_Procedure to decode, validate and route a received frame _} -{*Procedure to decode, validate and route a received frame *} +{_----------------------------------------------------------------------_} -{*----------------------------------------------------------------------*} +Procedure TLink.Decode (cPort : Char; -Procedure TLink.Decode (cPort : Char; +​ cPID : Char; -​ cPID : Char; +​ cDataKind : Char; -​ cDataKind : Char; +​ szFrom : String; -​ szFrom : String; +​ szTo : String; -​ szTo : String; +​ iDataLen : DWORD; -​ iDataLen : DWORD; +​ szData : String) ; -​ szData : String) ; +Var - Var +szYourCall : String; - szYourCall : String; +szAuxStr : String; - szAuxStr : String; +szInfo : String; - szInfo : String; +szVIA : String; - szVIA : String; +IsNew : Boolean; - +lpAux : PtrLink; - IsNew : Boolean; +MSB : Byte; - lpAux : PtrLink; +LSB : Byte; - - - MSB : Byte; - - LSB : Byte; - - SysDateTime : TDatetime; - - +SysDateTime : TDatetime; begin { TLink.Decode } - +szTo := UpCaseStr(szTo); - szTo := UpCaseStr(szTo); +szFrom := UpCaseStr(szFrom); - szFrom := UpCaseStr(szFrom); +​ {_-----------------------_} - +​ {_Return of call registr._} -​ {*-----------------------*} +{_---------------------------------------------------------------------_} -​ {*Return of call registr.*} +If cDataKind = ‘X’ then begin -{*---------------------------------------------------------------------*} +​ {_ Validate our registrations _} - +​ Exit; - If cDataKind = ‘X’ then begin +end; {_ endif _} -​ {* Validate our registrations *} +​ {_-----------------------_} -​ Exit; +​ {_Outstanding Frames Call_} - end; {* endif *} +{_---------------------------------------------------------------------_} - +If cDataKind = 'Y' then begin -​ {*-----------------------*} +​ {_ Your code here… _} -​ {*Outstanding Frames Call*} +​ Exit; -{*---------------------------------------------------------------------*} +end; {endif} - If cDataKind = 'Y' then begin +​ {_-----------------------_} -​ {* Your code here… *} +​ {_Outstanding Frames Port_} -​ Exit; +{_---------------------------------------------------------------------_} - end; {endif} +If cDataKind = 'y' then begin - +​ {_ Your code here … _} -​ {*-----------------------*} +​ Exit; -​ {*Outstanding Frames Port*} +end; {endif} -{*---------------------------------------------------------------------*} +​ {_-----------------------_} - If cDataKind = 'y' then begin +​ {_MHEARD List _} -​ {* Your code here … *} +{_---------------------------------------------------------------------_} -​ Exit; +If cDataKind = 'H' then begin - end; {endif} +​ PutAGW(1,'AGW Message '); - +​ DumpHex(1,szData); - +​ szAuxStr := Parse(szFrom); -​ {*-----------------------*} +​ PutAGW(1,'AGW Message Parsed From is ('+szAuxStr+') Remaining('+szFrom+')'); -​ {*MHEARD List *} +​ If szAuxStr <> '' then begin -{*---------------------------------------------------------------------*} +​ ParseHeard(cPort,szData); - If cDataKind = 'H' then begin +​ end; {endif} - +​ PutAGW(1,'AGW Message End of Message'); -​ PutAGW(1,'AGW Message '); +​ Exit; -​ DumpHex(1,szData); +end; {endif} - +​ {_-----------------------_} -​ szAuxStr := Parse(szFrom); +​ {_PARAMS List _} - +{_---------------------------------------------------------------------_} -​ PutAGW(1,'AGW Message Parsed From is ('+szAuxStr+') Remaining('+szFrom+')'); +If cDataKind = 'g' then begin -​ If szAuxStr <> '' then begin +​ PutAGW(5,'AGW Message '); -​ ParseHeard(cPort,szData); +​ ParseParam(cPort,szData); -​ end; {endif} +​ PutAGW(3,'End of processing Message '); - +​ Exit; -​ PutAGW(1,'AGW Message End of Message'); +end; {endif} - +​ {_-----------------------_} -​ Exit; +​ {\***\*AGWPE\*** KISS Raw Frame \*} - end; {endif} +{_---------------------------------------------------------------------_} - +If cDataKind = 'K' then begin -​ {*-----------------------*} +​ PutAGW(5,'AGW Message '); -​ {*PARAMS List *} +​ DumpHex(5,szData); -{*---------------------------------------------------------------------*} +​ {_------- Here Decode the Raw Frame ------_} - If cDataKind = 'g' then begin +​ RawDecode(szData,szFrom,szTo,szVIA,cDataKind,cPID,iDataLen,szInfo); -​ PutAGW(5,'AGW Message '); +​ szData := szInfo; -​ ParseParam(cPort,szData); +​ Exit; -​ PutAGW(3,'End of processing Message '); +end; {endif} -​ Exit; +​ {_-----------------------_} - end; {endif} +​ {\***\*AGWPE\*** UNPROTO \*} - +{_---------------------------------------------------------------------_} -​ {*-----------------------*} +If cDataKind = 'U' then begin -​ {****AGWPE\*** KISS Raw Frame *} +​ PutAGW(5,'AGW Message '); -{*---------------------------------------------------------------------*} +​ {_ Your code here…._} - If cDataKind = 'K' then begin +​ Exit; -​ PutAGW(5,'AGW Message '); +end; {endif} -​ DumpHex(5,szData); +​ {_-----------------------_} -​ {*------- Here Decode the Raw Frame ------*} +​ {\***\*AGWPE\*** Radio Ports \*} -​ RawDecode(szData,szFrom,szTo,szVIA,cDataKind,cPID,iDataLen,szInfo); +{_---------------------------------------------------------------------_} -​ szData := szInfo; +If cDataKind = 'G' then begin -​ Exit; +​ PutAGW(5,'AGW Message '); - end; {endif} +​ ParsePort(szData); -​ {*-----------------------*} +​ Exit; -​ {****AGWPE\*** UNPROTO *} +end; {endif} -{*---------------------------------------------------------------------*} +​ {_-----------------------_} - If cDataKind = 'U' then begin +​ {\***\*AGWPE\*** Version \*} -​ PutAGW(5,'AGW Message '); +{_---------------------------------------------------------------------_} -​ {* Your code here….*} +If cDataKind = 'R' then begin -​ Exit; +​ PutAGW(5,'AGW Message '); - end; {endif} +​ If VersionFlag = FALSE then begin - +​ VersionFlag := TRUE; -​ {*-----------------------*} +​ If Length(szData) >= 8 then begin -​ {****AGWPE\*** Radio Ports *} +​ LSB := ord(szData[1]); -{*---------------------------------------------------------------------*} +​ MSB := ord(szData[2]); - If cDataKind = 'G' then begin +​ AGWVerHigh := MAXFRAME \* MSB + LSB; -​ PutAGW(5,'AGW Message '); +​ LSB := ord(szData[5]); -​ ParsePort(szData); +​ MSB := ord(szData[6]); -​ Exit; +​ AGWVerLow := MAXFRAME \* MSB + LSB; - end; {endif} +​ PutAGW(1,'**\*AGWPE\*** Version '+inttostr(AGWVerHigh)+'-'+inttostr(AGWVerLow)); - +​ end; {endif} -​ {*-----------------------*} +​ end; {endif} -​ {****AGWPE\*** Version *} +​ Exit; -{*---------------------------------------------------------------------*} +end; {endif} - If cDataKind = 'R' then begin +​ {_-----------------------_} -​ PutAGW(5,'AGW Message '); +​ {_CONNECT Event Handler _} - +{_---------------------------------------------------------------------_} -​ If VersionFlag = FALSE then begin +If cDataKind = 'C' then begin -​ VersionFlag := TRUE; +​ PutAGW(5,'AGW Message '); - +​ IsNew := FALSE; -​ If Length(szData) >= 8 then begin +​ szYourCall := ''; -​ LSB := ord(szData[1]); +​ If Pos('CONNECTED To',szData) <> 0 then begin -​ MSB := ord(szData[2]); +​ szAuxStr := Parse(szData); -​ AGWVerHigh := MAXFRAME * MSB + LSB; +​ szAuxStr := Parse(szData); - +​ szAuxStr := Parse(szData); -​ LSB := ord(szData[5]); +​ szAuxStr := Parse(szData); -​ MSB := ord(szData[6]); +​ szYourCall:= Parse(szData); -​ AGWVerLow := MAXFRAME * MSB + LSB; +​ IsNew := TRUE; - +​ PutAGW(1,'Connection initiated by station '+szYourCall); -​ PutAGW(1,'***AGWPE\*** Version '+inttostr(AGWVerHigh)+'-'+inttostr(AGWVerLow)); +​ end; {endif} - +​ If Pos('CONNECTED With',szData) <> 0 then begin -​ end; {endif} +​ szAuxStr := Parse(szData); -​ end; {endif} +​ szAuxStr := Parse(szData); - +​ szAuxStr := Parse(szData); -​ Exit; +​ szAuxStr := Parse(szData); - end; {endif} +​ szYourCall:= Parse(szData); - +​ IsNew := FALSE; -​ {*-----------------------*} +​ PutAGW(1,'Connection initiated by us with station '+szYourCall); -​ {*CONNECT Event Handler *} +​ end; {endif} -{*---------------------------------------------------------------------*} +​ {_-----------------------_} - If cDataKind = 'C' then begin +​ {_We are looking for a _} -​ PutAGW(5,'AGW Message '); +​ {_connection we started _} -​ IsNew := FALSE; +{_---------------------------------------------------------------------_} -​ szYourCall := ''; +​ If IsNew = FALSE then begin - +​ {_ Your code here to handle a connection started by us _} -​ If Pos('CONNECTED To',szData) <> 0 then begin +​ end; {endif} -​ szAuxStr := Parse(szData); +​ {_-----------------------_} -​ szAuxStr := Parse(szData); +​ {_We are looking to serve_} -​ szAuxStr := Parse(szData); +​ {_an unsolicited connect _} -​ szAuxStr := Parse(szData); +{_---------------------------------------------------------------------_} -​ szYourCall:= Parse(szData); +​ If IsNew = TRUE then begin -​ IsNew := TRUE; +​ {_ Somebody connected us, so handle it…._} -​ PutAGW(1,'Connection initiated by station '+szYourCall); +​ end; -​ end; {endif} +end; {endif} {_-- This is the Footer of the whole event handler --_} - +​ {_-----------------------_} -​ If Pos('CONNECTED With',szData) <> 0 then begin +​ {_DISC Event Handler _} -​ szAuxStr := Parse(szData); +{_---------------------------------------------------------------------_} -​ szAuxStr := Parse(szData); +If cDataKind = 'd' then begin -​ szAuxStr := Parse(szData); +​ {_First look at IC link _} -​ szAuxStr := Parse(szData); +​ PutAGW(1,'Disconnect Frame: '+szData); -​ szYourCall:= Parse(szData); +​ If ((Pos('DISCONNECTED',szData) <> 0) and -​ IsNew := FALSE; +​ (Pos('RETRYOUT',szData) <> 0)) then begin -​ PutAGW(1,'Connection initiated by us with station '+szYourCall); +​ PutAGW(2,'Disconnection by Retryout detected'); -​ end; {endif} +​ end else begin - +​ If ((Pos('DISCONNECTED',szData) <> 0) and -​ {*-----------------------*} +​ (Pos('From',szData) <> 0)) then begin -​ {*We are looking for a *} +​ PutAGW(2,'Normal Disconnection detected'); -​ {*connection we started *} +​ end else begin -{*---------------------------------------------------------------------*} +​ If ((Pos('DISCONNECTED',szData) <> 0) and -​ If IsNew = FALSE then begin +​ (Pos('With',szData) <> 0)) then begin - +​ PutAGW(2,'AbNormal Disconnection detected, swap From<->To'); -​ {* Your code here to handle a connection started by us *} +​ szAuxStr := szFrom; - +​ szFrom := szTo; -​ end; {endif} +​ szTo := szAuxStr; - +​ end else begin -​ {*-----------------------*} +​ PutAGW(2,'Bogus Disconnection form detected, ignored'); -​ {*We are looking to serve*} +​ Exit; -​ {*an unsolicited connect *} +​ end; {endif} -{*---------------------------------------------------------------------*} +​ end; {endif} -​ If IsNew = TRUE then begin +​ end; {endif} - +​ {_ Process the remaining of the disconnection _} -​ {* Somebody connected us, so handle it….*} +​ Exit; -​ end; +end; {endif} - +​ {_-----------------------_} - end; {endif} {*-- This is the Footer of the whole event handler --*} +​ {_DATA Event Handler _} - +{_---------------------------------------------------------------------_} - +If cDataKind = 'D' then begin -​ {*-----------------------*} +​ {_ DO whatever it fits with the Data from a connected partner _} -​ {*DISC Event Handler *} +​ Exit; -{*---------------------------------------------------------------------*} +end; {endif} - If cDataKind = 'd' then begin - -​ {*First look at IC link *} - -​ PutAGW(1,'Disconnect Frame: '+szData); - - - -​ If ((Pos('DISCONNECTED',szData) <> 0) and - -​ (Pos('RETRYOUT',szData) <> 0)) then begin - -​ PutAGW(2,'Disconnection by Retryout detected'); - - - -​ end else begin - -​ If ((Pos('DISCONNECTED',szData) <> 0) and - -​ (Pos('From',szData) <> 0)) then begin - -​ PutAGW(2,'Normal Disconnection detected'); - -​ end else begin - -​ If ((Pos('DISCONNECTED',szData) <> 0) and - -​ (Pos('With',szData) <> 0)) then begin - -​ PutAGW(2,'AbNormal Disconnection detected, swap From<->To'); - -​ szAuxStr := szFrom; - -​ szFrom := szTo; - -​ szTo := szAuxStr; - -​ end else begin - -​ PutAGW(2,'Bogus Disconnection form detected, ignored'); - -​ Exit; - -​ end; {endif} - -​ end; {endif} - -​ end; {endif} - - - -​ {* Process the remaining of the disconnection *} - -​ Exit; - - end; {endif} - - - -​ {*-----------------------*} - -​ {*DATA Event Handler *} - -{*---------------------------------------------------------------------*} - - If cDataKind = 'D' then begin - - - -​ {* DO whatever it fits with the Data from a connected partner *} - -​ Exit; - - end; {endif} - - - - PutAGW(3,'AGW Message not processed <'+cDataKind+'>'); - - +PutAGW(3,'AGW Message not processed <'+cDataKind+'>'); end; { TLink.Decode } - - - - - - - - - - - - ### Format VIA Areas - - -The way a digipeater string is informed to ***AGWPE\*** seems intrincated and terrible on first look, but it’s rather simple actually, see on how to create the data area in C++ (code excerpt from George, ***SV2AGW\***). - - +The way a digipeater string is informed to **\*AGWPE\*** seems intrincated and terrible on first look, but it’s rather simple actually, see on how to create the data area in C++ (code excerpt from George, **\*SV2AGW\***). char str[100]; - - str[0]=HowManyDigis; str+1=1digi;//null terminated @@ -4865,21 +3081,17 @@ str+1+10=2digi;//null terminated str+1+20=3digi//null terminated - - -A more comprehensive routine to prepare a VIA list in C++ (also from George, ***SV2AGW\***) follows - - +A more comprehensive routine to prepare a VIA list in C++ (also from George, **\*SV2AGW\***) follows int PrepareViaList(char *InVia,char *OutVia) { -//InVia string contains the via list like ***SV2AGW\***,SV2BBO,SV2DFK +//InVia string contains the via list like **\*SV2AGW\***,SV2BBO,SV2DFK -//OutVia is the same list suitable prepared for ***AGWPE\*** +//OutVia is the same list suitable prepared for **\*AGWPE\*** -char *token; +char \*token; char temp[15]; @@ -4889,279 +3101,229 @@ token=strtok(InVia,", "); if (token) - { +{ - HowVia++; +HowVia++; - strcpy(temp,token); +strcpy(temp,token); - memmove(OutVia+1,temp,10); - - } - -for (;;) - -​ { - -​ token=strtok(NULL,", "); - -​ if (token) - -​ { - -​ strcpy(temp,token); - -​ memmove(OutVia+1+(HowVia*10),temp,10); - -​ HowVia++; - -​ } else break; - -​ }//end for - -OutVia[0]=HowVia; - -return((HowVia*10)+1); +memmove(OutVia+1,temp,10); } - +for (;;) -The following function does about the same, only in Delphi4 and written by Pedro (***LU7DID\***); the routine accepts a string with the list of callsigns+SSID to be used as digipeaters and returns a data area directly in the format ***AGWPE\*** likes it. +​ { - +​ token=strtok(NULL,", "); -(*--->>> FormatVIA <<<----------------------------------------------*) +​ if (token) -{*Routine to format the VIA path in the particular way ***AGWPE\*** likes it *} +​ { -{*----------------------------------------------------------------------*} +​ strcpy(temp,token); + +​ memmove(OutVia+1+(HowVia\*10),temp,10); + +​ HowVia++; + +​ } else break; + +​ }//end for + +OutVia[0]=HowVia; + +return((HowVia\*10)+1); + +} + +The following function does about the same, only in Delphi4 and written by Pedro (**\*LU7DID\***); the routine accepts a string with the list of callsigns+SSID to be used as digipeaters and returns a data area directly in the format **\*AGWPE\*** likes it. + +(_--->>> FormatVIA <<<----------------------------------------------_) + +{\*Routine to format the VIA path in the particular way **\*AGWPE\*** likes it \*} + +{_----------------------------------------------------------------------_} Function FormatVIA (InStr : String) : String; - Var +Var - AuxStr : String; +AuxStr : String; - CountVIA : Byte; +CountVIA : Byte; - ArrayVIA : Array[0..256] of Char; +ArrayVIA : Array[0..256] of Char; - Index : Integer; +Index : Integer; - Token : String; +Token : String; - PtrVIA : Byte; +PtrVIA : Byte; - Jndex : Integer; - - +Jndex : Integer; begin { FormatVIA } - +For Index := 0 to 256 do begin - For Index := 0 to 256 do begin +​ ArrayVIA[Index] := NUL; -​ ArrayVIA[Index] := NUL; +end; {endfor} - end; {endfor} +AuxStr := InStr; - +PtrVIA := 1; - AuxStr := InStr; +CountVIA := 0; - PtrVIA := 1; +While AuxStr <> '' do begin - CountVIA := 0; +Token := Parse(AuxStr); - +If Token <> '' then begin - While AuxStr <> '' do begin +​ For Jndex := 1 to Length(Token) do begin - Token := Parse(AuxStr); +​ ArrayVIA[Jndex-1+PtrVIA] := Token[Jndex]; - If Token <> '' then begin +​ end; {endfor} -​ For Jndex := 1 to Length(Token) do begin +​ ArrayVia[Length(Token)+1+PtrVIA] := NUL; -​ ArrayVIA[Jndex-1+PtrVIA] := Token[Jndex]; +​ PtrVIA := PtrVIA + 10; -​ end; {endfor} +​ inc(CountVIA); -​ ArrayVia[Length(Token)+1+PtrVIA] := NUL; +end; {endif} -​ PtrVIA := PtrVIA + 10; +end; {endwhile} -​ inc(CountVIA); +If PtrVIA <> 1 then begin - end; {endif} +​ AuxStr := ''; - end; {endwhile} +​ ArrayVia[0] := chr(CountVIA); - +​ For Index := 0 to PtrVIA-1 do begin - If PtrVIA <> 1 then begin +​ AuxStr := AuxStr + ArrayVia[Index]; -​ AuxStr := ''; +​ end; {endfor} -​ ArrayVia[0] := chr(CountVIA); +​ Result := AuxStr; - +​ Exit; -​ For Index := 0 to PtrVIA-1 do begin +end else begin -​ AuxStr := AuxStr + ArrayVia[Index]; +​ Result := ''; -​ end; {endfor} +​ Exit; -​ Result := AuxStr; - -​ Exit; - - end else begin - -​ Result := ''; - -​ Exit; - - end; {endif} - - +end; {endif} end; { FormatVIA } - - - - ### Parsing Port Information - +This code excerpt written in Delphi4 shows how to “chain” port information sent by **\*AGWPE\*** with request for further information to **\*AGWPE\***, this routine/method should be originally called from the main dispatcher switch when a frame with DataKind=’G’ is received. -This code excerpt written in Delphi4 shows how to “chain” port information sent by ***AGWPE\*** with request for further information to ***AGWPE\***, this routine/method should be originally called from the main dispatcher switch when a frame with DataKind=’G’ is received. +(_--->>> ParsePort <<<----------------------------------------------_) - +{_Procedure to decode, validate and store information about ports _} -(*--->>> ParsePort <<<----------------------------------------------*) - -{*Procedure to decode, validate and store information about ports *} - -{*----------------------------------------------------------------------*} +{_----------------------------------------------------------------------_} Procedure TLink.ParsePort(szPort : String); - Var +Var - PortNum : Integer; +PortNum : Integer; - AuxStr : String; +AuxStr : String; - RadioPort : Integer; +RadioPort : Integer; - cPort : Char; +cPort : Char; - bPort : Byte; +bPort : Byte; - Index : Integer; - - +Index : Integer; begin { TLink } - +AGWPortInit; - AGWPortInit; +PutAGW(3,'Port String is '+szPort); - +PortNum := strtoint(PopBang(szPort,';')); - PutAGW(3,'Port String is '+szPort); +PutAGW(3,'Parsed Number of Ports is '+inttostr(PortNum)); - PortNum := strtoint(PopBang(szPort,';')); +RadioPort := 1; - PutAGW(3,'Parsed Number of Ports is '+inttostr(PortNum)); +While PortNum > 0 do begin - RadioPort := 1; +​ {_----------------------------------_} - +​ {_Store the port description _} - While PortNum > 0 do begin +​ {_----------------------------------_} -​ {*----------------------------------*} +AuxStr := PopBang(szPort,';'); -​ {*Store the port description *} +Ports[RadioPort].PortStr := GetStrZ(AuxStr); -​ {*----------------------------------*} +Ports[RadioPort].Enabled := TRUE; - AuxStr := PopBang(szPort,';'); +​ {_----------------------------------_} - Ports[RadioPort].PortStr := GetStrZ(AuxStr); +​ {_Initialize the MHEARD structure _} - Ports[RadioPort].Enabled := TRUE; +​ {_for the port and pull a refresh _} - +​ {_----------------------------------_} -​ {*----------------------------------*} +bPort := Trunc(RadioPort); -​ {*Initialize the MHEARD structure *} +cPort := chr(bPort); -​ {*for the port and pull a refresh *} +For Index := 1 to MAXHEARD do begin -​ {*----------------------------------*} +​ Ports[RadioPort].HeardStr[Index] := ''; - bPort := Trunc(RadioPort); +end; {endfor} - cPort := chr(bPort); +​ {_----------------------------------_} - +​ {_Pull outstanding info, heard and _} - For Index := 1 to MAXHEARD do begin +​ {_capabilities info _} -​ Ports[RadioPort].HeardStr[Index] := ''; +​ {_----------------------------------_} - end; {endfor} +Send(AGWSocket,cPort,NUL,'y','','',0,''); -​ {*----------------------------------*} +Send(AGWSocket,cPort,NUL,'H','','',0,''); -​ {*Pull outstanding info, heard and *} +Send(AGWSocket,cPort,NUL,'g','','',0,''); -​ {*capabilities info *} +PutAGW(3,' Stored RadioPort # '+inttostr(RadioPort)+' as +Ports[RadioPort].PortStr); -​ {*----------------------------------*} +inc(RadioPort); - +dec(PortNum); - Send(AGWSocket,cPort,NUL,'y','','',0,''); - - Send(AGWSocket,cPort,NUL,'H','','',0,''); - - Send(AGWSocket,cPort,NUL,'g','','',0,''); - - - - PutAGW(3,' Stored RadioPort # '+inttostr(RadioPort)+' as +Ports[RadioPort].PortStr); - - inc(RadioPort); - - dec(PortNum); - - end; {endwhile} - - - - +end; {endwhile} ### Port Capabilities - - -This is the C++ structure recommended by George (***SV2AGW\***) to held and decode the data area with the port capabilities as provided in the ‘g’ Frame sent by ***AGWPE\***. - - +This is the C++ structure recommended by George (**\*SV2AGW\***) to held and decode the data area with the port capabilities as provided in the ‘g’ Frame sent by **\*AGWPE\***. unsigned char OnairBaud; -unsigned char TrafficLevel;// if this is 255 then the port is not in autoupdate mode +unsigned char TrafficLevel;// if this is 255 then the port is not in autoupdate mode unsigned char TxDelay; @@ -5177,592 +3339,396 @@ unsigned char AX25Channels; // How many connections we have unsigned int HowManyBytes;// how many bytes are received the last 2 minutes - +An alternate way, this time in Delphi4 from a code excerpt from Pedro (**\*LU7DID\***) obtain this information right out of the data area as received in the ‘G’ frame from **\*AGWPE\***. -An alternate way, this time in Delphi4 from a code excerpt from Pedro (***LU7DID\***) obtain this information right out of the data area as received in the ‘G’ frame from ***AGWPE\***. +(_--->>> ParseParam <<<----------------------------------------------_) - +{_Procedure to decode, validate and store information about ports params_} -(*--->>> ParseParam <<<----------------------------------------------*) - -{*Procedure to decode, validate and store information about ports params*} - -{*----------------------------------------------------------------------*} +{_----------------------------------------------------------------------_} Procedure TLink.ParseParam(cPort : Char; szData : String); - +Var - Var +bPort : Byte; - bPort : Byte; - - szAuxStr : String; - - +szAuxStr : String; begin { TLink } - +bPort := Ord(cPort); - bPort := Ord(cPort); +If (bPort > 0) and (bPort <= MAXPORT) then begin - If (bPort > 0) and (bPort <= MAXPORT) then begin +end else begin - end else begin +PutAGW(1,'ParseParam exit with cPort('+inttostr(bPort)+') too high'); - PutAGW(1,'ParseParam exit with cPort('+inttostr(bPort)+') too high'); +Exit; - Exit; +end; {endif} - end; {endif} +PutAGW(3,'Storing Params for Port ('+inttostr(bPort)+')'); - +Ports[bPort].bOnAirBaud := ord(szData[1]); - PutAGW(3,'Storing Params for Port ('+inttostr(bPort)+')'); +Ports[bPort].bTrafficLevel := ord(szData[2]); - Ports[bPort].bOnAirBaud := ord(szData[1]); +Ports[bPort].bTxDelay := ord(szData[3]); - Ports[bPort].bTrafficLevel := ord(szData[2]); +Ports[bPort].bTxTail := ord(szData[4]); - Ports[bPort].bTxDelay := ord(szData[3]); +Ports[bPort].bPersist := ord(szData[5]); - Ports[bPort].bTxTail := ord(szData[4]); +Ports[bPort].bSlotTime := ord(szData[6]); - Ports[bPort].bPersist := ord(szData[5]); +Ports[bPort].bMaxFrame := ord(szData[7]); - Ports[bPort].bSlotTime := ord(szData[6]); +Ports[bPort].bAX25Channel := ord(szData[8]); - Ports[bPort].bMaxFrame := ord(szData[7]); - - Ports[bPort].bAX25Channel := ord(szData[8]); - - Ports[bPort].iHowManyBytes := ord(szData[9])+MAXFRAME*ord(szData[10])+($10000*ord(szData[11])); - - - - +Ports[bPort].iHowManyBytes := ord(szData[9])+MAXFRAME*ord(szData[10])+($10000*ord(szData[11])); end; { TLink } - - - - ### Heard Information for a Port - +The following Delphi4 code excerpt from Pedro (**\*LU7DID\***) shows a possible way to decode the heard information provided on the data area of an ‘H’ frame (note that the data associated with the binary format is just ignored). -The following Delphi4 code excerpt from Pedro (***LU7DID\***) shows a possible way to decode the heard information provided on the data area of an ‘H’ frame (note that the data associated with the binary format is just ignored). +(_--->>> ParseHeard <<<----------------------------------------------_) - +{_Procedure to decode, validate and store information about ports _} -(*--->>> ParseHeard <<<----------------------------------------------*) - -{*Procedure to decode, validate and store information about ports *} - -{*----------------------------------------------------------------------*} +{_----------------------------------------------------------------------_} Procedure TLink.ParseHeard(cPort : Char; szData : String); - Var +Var - bPort : Byte; +bPort : Byte; - iPort : Integer; +iPort : Integer; - Index : Integer; +Index : Integer; - szAuxStr : String; +szAuxStr : String; - szHeardStr : String; - - +szHeardStr : String; begin { TLink } - +bPort := Ord(cPort); - bPort := Ord(cPort); +If (bPort > 0) and (bPort <= MAXPORT) then begin - If (bPort > 0) and (bPort <= MAXPORT) then begin +end else begin - end else begin +PutAGW(1,'ParseHeard exit with cPort('+inttostr(bPort)+') too high'); - PutAGW(1,'ParseHeard exit with cPort('+inttostr(bPort)+') too high'); +Exit; - Exit; +end; {endif} - end; {endif} +iPort := bPort; - iPort := bPort; +PutAGW(1,'ParseHeard:'); - +DumpHex(1,szData); - PutAGW(1,'ParseHeard:'); +szAuxStr := szData; - DumpHex(1,szData); +szHeardStr := PopBang(szAuxStr,Chr($00)); - +For Index := 1 to MAXHEARD do begin - szAuxStr := szData; +If Ports[iPort].HeardStr[Index] = '' then begin - szHeardStr := PopBang(szAuxStr,Chr($00)); +​ Ports[iPort].HeardStr[Index] := szHeardStr; - +​ PutAGW(1,'Stored '+szHeardStr+' at Offset ('+IntToStr(Index)+')'); - For Index := 1 to MAXHEARD do begin +​ Exit; - If Ports[iPort].HeardStr[Index] = '' then begin +end; {endif} -​ Ports[iPort].HeardStr[Index] := szHeardStr; +end; {endfor} -​ PutAGW(1,'Stored '+szHeardStr+' at Offset ('+IntToStr(Index)+')'); - -​ Exit; - - end; {endif} - - end; {endfor} - - PutAGW(1,'Table Full. Not Stored '+szHeardStr); - - +PutAGW(1,'Table Full. Not Stored '+szHeardStr); end; { TLink } - - - - - - - - - - - - - - - - - - - - ### Raw Frames - +In case raw frames want to be handled the following Delphi4 routine written by Pedro (**\*LU7DID\***) could give you a starting point. -In case raw frames want to be handled the following Delphi4 routine written by Pedro (***LU7DID\***) could give you a starting point. +You must enter the routine (method, actually) with the data frame as received over the air on the ‘K’ frame from **\*AGWPE\***, the routine would parse and decode the components of that frame. - +(_--->>> RawDecode <<<----------------------------------------------_) -You must enter the routine (method, actually) with the data frame as received over the air on the ‘K’ frame from ***AGWPE\***, the routine would parse and decode the components of that frame. +{_Procedure to decode a Raw KISS frame _} - +{_----------------------------------------------------------------------_} -(*--->>> RawDecode <<<----------------------------------------------*) +Procedure TLink.RawDecode( szData : String; -{*Procedure to decode a Raw KISS frame *} +​ Var szFrom : String; -{*----------------------------------------------------------------------*} +​ Var szTo : String; -Procedure TLink.RawDecode( szData : String; +​ Var szVIA : String; -​ Var szFrom : String; +​ Var cDataKind : Char; -​ Var szTo : String; +​ Var cPID : Char; -​ Var szVIA : String; +​ Var iDataLen : DWORD; -​ Var cDataKind : Char; +​ Var szInfo : String); -​ Var cPID : Char; +Var -​ Var iDataLen : DWORD; +Index : Integer; -​ Var szInfo : String); +AuxChar : Char; - Var +AuxByte : Byte; - Index : Integer; +szCall : String; - AuxChar : Char; +Jndex : Integer; - AuxByte : Byte; +iCount : Integer; - szCall : String; - - Jndex : Integer; - - iCount : Integer; - - iFlag : Integer; - - +iFlag : Integer; begin { TLink } - +Index := 2; - Index := 2; +szCall := ''; - szCall := ''; +iCount := 1; - iCount := 1; +iFlag := 1; - iFlag := 1; +szVIA := ''; - szVIA := ''; +For Jndex := Index to Length(szData) do begin - For Jndex := Index to Length(szData) do begin +​ AuxChar := szData[Index]; -​ AuxChar := szData[Index]; +​ AuxByte := Ord(AuxChar); -​ AuxByte := Ord(AuxChar); +​ szCall := szCall + Chr(((AuxByte and $FE) shr 1)); -​ szCall := szCall + Chr(((AuxByte and $FE) shr 1)); +​ inc(iCount); -​ inc(iCount); +​ If iCount > 7 then begin -​ If iCount > 7 then begin +​ iCount := 1; -​ iCount := 1; +​ If iFlag = 1 then begin -​ If iFlag = 1 then begin +​ szTo := szCall; -​ szTo := szCall; +​ szCall := ''; -​ szCall := ''; +​ inc(iFlag); -​ inc(iFlag); +​ end else begin -​ end else begin +​ If iFlag = 2 then begin -​ If iFlag = 2 then begin +​ szFrom := szFrom; -​ szFrom := szFrom; +​ szCall := ''; -​ szCall := ''; +​ inc(iFlag); -​ inc(iFlag); +​ end else begin -​ end else begin +​ szVIA := szVIA + szCall; -​ szVIA := szVIA + szCall; +​ szCall := ''; -​ szCall := ''; +​ end; {endif} -​ end; {endif} +​ end; {endif} -​ end; {endif} +​ end; {endif} -​ end; {endif} +​ inc(Index); -​ inc(Index); +​ If (AuxByte and $01) = $01 then begin -​ If (AuxByte and $01) = $01 then begin +​ Break; -​ Break; +​ end; {endif} -​ end; {endif} +end; {endfor} - end; {endfor} +szCall := szFrom; - +szFrom := Parse(szCall); - szCall := szFrom; +szCall := szTo; - szFrom := Parse(szCall); +szTo := Parse(szCall); - szCall := szTo; +AuxChar := szData[Index]; - szTo := Parse(szCall); +AuxByte := Ord(AuxChar); - +If (AuxByte and $FE) = $00 then begin - AuxChar := szData[Index]; +​ cDataKind := 'I'; - AuxByte := Ord(AuxChar); +end else begin - If (AuxByte and $FE) = $00 then begin +​ If (AuxByte and $FC) = $01 then begin -​ cDataKind := 'I'; +​ cDataKind := 'S'; - end else begin +​ end else begin -​ If (AuxByte and $FC) = $01 then begin +​ cDataKind := 'U'; -​ cDataKind := 'S'; +​ end; {endif} -​ end else begin +end; {endif} -​ cDataKind := 'U'; +inc(Index); -​ end; {endif} +cPid := szData[Index]; - end; {endif} +inc(Index); - +szInfo := ''; - inc(Index); +For Jndex := Index to Length(szData) do begin - cPid := szData[Index]; +​ szInfo := szInfo + szData[Jndex]; - inc(Index); +end; {endfor} - +PutAGW(2,'Decoded KISS Frame as From=('+szFrom+') To=('+szTo+') VIA('+szVIA+') DataKind('+cDataKind+') Pid('+HexByte(Ord(cPid))+')'); - szInfo := ''; - - For Jndex := Index to Length(szData) do begin - -​ szInfo := szInfo + szData[Jndex]; - - end; {endfor} - - - - PutAGW(2,'Decoded KISS Frame as From=('+szFrom+') To=('+szTo+') VIA('+szVIA+') DataKind('+cDataKind+') Pid('+HexByte(Ord(cPid))+')'); - - DumpHex(2,szInfo); - - +DumpHex(2,szInfo); end; { TLink } - - - - - - ### Tracking Frames - - Some of the frames used for the application to communicate with AGWPE acts like a switch, the first time sent activates a function, the second de-activates it and so on (i.e. the ‘m’ and ‘k’ frames). - - Since AGWPE doesn’t return a “confirming” frame to the requirement the application has to keep track of the current status if for functional reasons the underlying functions must be alternated as on or off. - - A good technique of doing so is to use a “counter” to track how many frames of a given type has been sent, at any time the value of that counter could be inspected and being odd it would signal the function is activated while being even it’s inactive. - - The general algorithm would be: - - - Everytime the connection with AGWPE is established (at the beginning of the execution or because of a re-connection) the counter bFrame must be set to zero (0x00); - Everytime a frame under traking is sent the counter must be increased by one and “AND”ed with 7 (0x07 or 0b00000111). - At any time the value of the counter being even (i.e. multiple of 2) would signal the function is inactive (0,2,4,….) while being odd (i.e. not multiple of 2) would signal the function is active (1,3,5,…). - - - - - - - - - - - - - - - - ## Managing Connections - - -Once the basic frame processing is mastered just one additional issue has to be understood for the would be ***AGWPE\*** programmer in order to be ready to write applications of any arbitrary complexity, and that is how to manage AX.25 connections. - - +Once the basic frame processing is mastered just one additional issue has to be understood for the would be **\*AGWPE\*** programmer in order to be ready to write applications of any arbitrary complexity, and that is how to manage AX.25 connections. Simple applications that involves the processing of some sort of monitoring only doesn’t need to be bothered by the managing of connections at all, those applications doesn’t even need to register a call to work properly. - - Simple terminal programs could assume that a single user could sustain a single connection using a single registered callsign, so no complex issues occurs in that scenario. - - However, most real world applications would face the need to be able to manage multiple simultaneous connections possibly using several registered callsigns at once. - +The basic issue to solve is assuming a single TCP/IP connection is held between the application and **\*AGWPE\*** different frames might arrive thru that connection which logically belongs to different connections and the application is responsible to identify to which particular connection the frame belongs and to route the relevant information to that connection. -The basic issue to solve is assuming a single TCP/IP connection is held between the application and ***AGWPE\*** different frames might arrive thru that connection which logically belongs to different connections and the application is responsible to identify to which particular connection the frame belongs and to route the relevant information to that connection. - - - -Unfortunately ***AGWPE\*** doesn’t provide any handle or id that uniquely identify a given connection among others; this is not needed actually since a close look of the AX.25 protocol provides such unique identifier as we would see. - - +Unfortunately **\*AGWPE\*** doesn’t provide any handle or id that uniquely identify a given connection among others; this is not needed actually since a close look of the AX.25 protocol provides such unique identifier as we would see. Some suggested tactics would be discussed on the following sections. - - ### One Callsign, Many Connections - - This is the simplest case, so it’s a good starting point. - - The application needs to sustain several AX.25 connections at the same time (i.e. a multiwindow terminal program) using a single registered callsign. - +At first look, the initial attempt of many programmers should be to create different TCP/IP sockets one for each connection, so frames flowing from **\*AGWPE\*** to the application would be automatically bucketed into their destination by means of the socket where the data arrived. -At first look, the initial attempt of many programmers should be to create different TCP/IP sockets one for each connection, so frames flowing from ***AGWPE\*** to the application would be automatically bucketed into their destination by means of the socket where the data arrived. +Given the relative simplicity to establish TCP/IP sockets from the application standpoint and the fact that **\*AGWPE\*** could handle a limitless number of simultaneous connections (from any meaningful number required in the real world) this seems to be the right approach. - - -Given the relative simplicity to establish TCP/IP sockets from the application standpoint and the fact that ***AGWPE\*** could handle a limitless number of simultaneous connections (from any meaningful number required in the real world) this seems to be the right approach. - - - -But it is not, the main drawback is in the fact that ***AGWPE\*** only allows a given callsign+SSID to be registered once across all applications running on a given moment, ***AGWPE\*** doesn’t really knows nor care if the multiple sockets were opened from a single application or from many applications. - - +But it is not, the main drawback is in the fact that **\*AGWPE\*** only allows a given callsign+SSID to be registered once across all applications running on a given moment, **\*AGWPE\*** doesn’t really knows nor care if the multiple sockets were opened from a single application or from many applications. So the first socket to register a callsign+SSID would take it all, the others would either fail trying to register the same callsign+SSID or be forced to use different callsign+SSID. - - To register a different callsign+SSID for each connection could be both extremely impractical and a very limited approach, after all AX.25 tolerates just 16 different SSID to be used by callsign (0 to 15), and with a fair number of applications running on a typical environment this would quickly become a limiting factor. - +So, the best solution would be for the application to open just a single socket with **\*AGWPE\***, register a single callsign with it and manage many connections with the same callsign+SSID. -So, the best solution would be for the application to open just a single socket with ***AGWPE\***, register a single callsign with it and manage many connections with the same callsign+SSID. - - - -A limitation of the AX.25 protocol L2 connections come to provide a sort of help, the protocol doesn’t allow more than one connected session among a pair of callsign+SSID ends, so the combination From/To (in any order) of any two callsign+SSID has to be unique. Since ***AGWPE\*** could handle multiple ports at the same time the uniqueness could be obtained adding the Port to the identification key. - - +A limitation of the AX.25 protocol L2 connections come to provide a sort of help, the protocol doesn’t allow more than one connected session among a pair of callsign+SSID ends, so the combination From/To (in any order) of any two callsign+SSID has to be unique. Since **\*AGWPE\*** could handle multiple ports at the same time the uniqueness could be obtained adding the Port to the identification key. The overall logic the application should follow is despicted as follows: - - - The application should register a callsign+SSID as a part of the initialization cycle. - A memory structure (a table, a linked list, a double linked list, whatever) should be created and maintaned by the application with Port,From,To and status. This table would be initially empty. Additional information closely tied to the application functionality should also be included on each entry. -- Everytime a ‘C’ frame arrives from ***AGWPE\*** as an unsolicited connection an entry is created, in the case the connection had been requested by us the entry might be created at the moment the connection was requested and the status updated when the connection is actually acomplished. The application should check at this point if another connection is already active with the same callsign+SSID pairs and if so refuse to start another connection (that would fail in the AX.25 realm anyway). -- Everytime a ‘D’ frame arrives from ***AGWPE\*** the application scans the memory structure looking for a match with the Port/From/To and Port/To/From of the arriving data frame, if an entry is found the application could use the additional (functionality dependent) information to properly route the data block (object pointers, window handler, whatever). If an entry is not found the frame is just discarded or the error is flagged in some meaningful way for the application context. -- Everytime a ‘d’ frame arrives from ***AGWPE\*** the application scans for the frame looking to match the Port/From/To and Port/To/From of it, once an entry is found all the actions associated with the disconnection are made and the entry is either destroyed or flagged as inactive (so no additional data frames could be handled by it). - - +- Everytime a ‘C’ frame arrives from **\*AGWPE\*** as an unsolicited connection an entry is created, in the case the connection had been requested by us the entry might be created at the moment the connection was requested and the status updated when the connection is actually acomplished. The application should check at this point if another connection is already active with the same callsign+SSID pairs and if so refuse to start another connection (that would fail in the AX.25 realm anyway). +- Everytime a ‘D’ frame arrives from **\*AGWPE\*** the application scans the memory structure looking for a match with the Port/From/To and Port/To/From of the arriving data frame, if an entry is found the application could use the additional (functionality dependent) information to properly route the data block (object pointers, window handler, whatever). If an entry is not found the frame is just discarded or the error is flagged in some meaningful way for the application context. +- Everytime a ‘d’ frame arrives from **\*AGWPE\*** the application scans for the frame looking to match the Port/From/To and Port/To/From of it, once an entry is found all the actions associated with the disconnection are made and the entry is either destroyed or flagged as inactive (so no additional data frames could be handled by it). Since this logic would be exercised fairly often the programmer should pay premium attention to the efficiency of the creation, search and disposal of entries on the memory structure making them as efficient and fast as possible (or buy an umpteen Mhz Pentium IX iron to run it). - - - - - - ### Many CallSigns, Many Connections - - In this case the added complexity is the need for the application to register and use any arbitrary number of callsign+SSID (i.e. on a BBS program some callsigns to accept connections and some others to start forward sessions). - - Again, multiple sockets could be opened, in this case one for each registered callsign, so the case trivialized itself into many instances of the “One CallSign, Many Connection” just seen in the previous section. - - However, the very logic stated in that case would still be valid for this one, as long as we add a validation on every connection started that the our involved callsign belongs to a given (and limited) authorized set or pool of callsigns. - - This control won’t hurt, actually is highly desirable, even on the case a single callsign is used. - - - - ## Down the Tubes, Climb the Ladder - - In fantastic Wonderland bug free programs do exist; however, on Earth this is not true. Programs does have bugs, plenty of them. Some inocuous enough to survive the entire lifespan of a program and still be undetected (only triggered for a combination of factors so unlikely that it actually never happens). - - -***AGWPE\*** itself is not an exception, and certainly no application program would be out of that rule. - - +**\*AGWPE\*** itself is not an exception, and certainly no application program would be out of that rule. So the ideal profile of a programmer is a person that it’s moderately paranoid and expect things that might go wrong from time to time; good programs often differentiate from bad programs that provide exactly the same functionality just by the extend of how hardened it has been made by it’s author. - - Some general guidelines: - - -- ***AGWPE\*** is in general terms an stable platform, it could run days or even weeks under heavy use without any major trap or problem. However, from time to time, it might fail. Prepare your application to handle unexpected disconnections from ***AGWPE\*** and recover graciously from them. -- Whenever a disconnection do occur assume something wrong happened to ***AGWPE\***, so don’t assume anything about the state of execution, just re-init everything as if it would be a fresh start. ***AGWPE\*** might fail not because of a resident bug of it, Windows 95/98/NT aren’t themselves the most stable OS on Earth, sometimes a ill behaved application might push it down the tubes for no particular good reason (NEVER rule out that is YOUR application the guilty one!!!). +- **\*AGWPE\*** is in general terms an stable platform, it could run days or even weeks under heavy use without any major trap or problem. However, from time to time, it might fail. Prepare your application to handle unexpected disconnections from **\*AGWPE\*** and recover graciously from them. +- Whenever a disconnection do occur assume something wrong happened to **\*AGWPE\***, so don’t assume anything about the state of execution, just re-init everything as if it would be a fresh start. **\*AGWPE\*** might fail not because of a resident bug of it, Windows 95/98/NT aren’t themselves the most stable OS on Earth, sometimes a ill behaved application might push it down the tubes for no particular good reason (NEVER rule out that is YOUR application the guilty one!!!). - Don’t trust data you didn’t generated, always extensively check data contents, data ranges, meaningful values of data that came into your application from the outside; plan for actions when something non-compliant does arrives, because eventually does arrives. -- The landmark of a novel programmer is to suspect something is wrong with the compiler when a program doesn’t work; even if it could be true it’s extremely unlikely on most cases. ***AGWPE\*** is not a compiler grade bug-free but still is a platform in use by thousands of nodes across the globe. So if something doesn’t seems to work correctly with your application double check, and then check again. ***AGWPE\*** might react in obscure ways when feed with improperly formated frames or data. -- Keep your feets on the ground at all times, the ***AGWPE\*** API might lead you think you have a T3 bandwidth at your disposal because everything is transferred so fast; however, if the phisical port still is 1200 bps over Packet Radio is little what ***AGWPE\*** could do about, you are just overwhelming the internal buffers of ***AGWPE\*** for no good reason and this won’t make your data move faster. Feed data at volumes that could be handled within reason with the available port bandwidth, check reasonably often how big your queue is on ***AGWPE\*** and act accordingly. +- The landmark of a novel programmer is to suspect something is wrong with the compiler when a program doesn’t work; even if it could be true it’s extremely unlikely on most cases. **\*AGWPE\*** is not a compiler grade bug-free but still is a platform in use by thousands of nodes across the globe. So if something doesn’t seems to work correctly with your application double check, and then check again. **\*AGWPE\*** might react in obscure ways when feed with improperly formated frames or data. +- Keep your feets on the ground at all times, the **\*AGWPE\*** API might lead you think you have a T3 bandwidth at your disposal because everything is transferred so fast; however, if the phisical port still is 1200 bps over Packet Radio is little what **\*AGWPE\*** could do about, you are just overwhelming the internal buffers of **\*AGWPE\*** for no good reason and this won’t make your data move faster. Feed data at volumes that could be handled within reason with the available port bandwidth, check reasonably often how big your queue is on **\*AGWPE\*** and act accordingly. - Plan carefully the whole AX.25 cycle your application would use, provide for unexpected events to happen and still the application provide meaningful results on them. - Plan for your application to fail miserably from time to time, even for reasons you don’t have any reasonable clue about at the writing time; use all exception resources your language of choice provide to handle the “unthinkable” and still end gracefully and if possible leaving a trace of what happened. -- ***AGWPE\*** could sustain substantial abuse in terms of the resources and information required by each application, but still request from ***AGWPE\*** what you could actually handle. There is no point on requiring information (i.e. activate monitoring in both conventional and raw formats) you are not going to actually process. Assume your application would be part on a typical station of a multiapplication scenario (using application mixes you could not imagine probably), so everytime you drag unneded resources you might be impacting other’s application ability to run smoothly. +- **\*AGWPE\*** could sustain substantial abuse in terms of the resources and information required by each application, but still request from **\*AGWPE\*** what you could actually handle. There is no point on requiring information (i.e. activate monitoring in both conventional and raw formats) you are not going to actually process. Assume your application would be part on a typical station of a multiapplication scenario (using application mixes you could not imagine probably), so everytime you drag unneded resources you might be impacting other’s application ability to run smoothly. - Don’t fall on the typical programmer attitude to consider the world divided into the persons who write applications and the idiots who uses them; applications are black boxes for end users and many things you take for granted because you know your program might be obscure and arcane to a third person, no matter how literate with computers this person might be, just because he lacks your “common knowledge”. Be forgiving with your user interface and if possible think on the unthinkable, it might well happen. - - - - - - # Credits and other stuff - - -This document is the intellectual property of Pedro E. Colla (***LU7DID\***) and George Rossopoulos (***SV2AGW\***) and as such is a copyrighted piece subject to international laws covering intellectual property. - - +This document is the intellectual property of Pedro E. Colla (**\*LU7DID\***) and George Rossopoulos (**\*SV2AGW\***) and as such is a copyrighted piece subject to international laws covering intellectual property. However, it’s usage is free for radioamateur uses as long as the reader understand is using the material contained on it at his or her own risk, authors doesn’t bear any responsibility on any damage direct or indirect been made thru the usage of this material. - - Excerpts had been taken from other sources and the relevant copyright information provided when this has been done, the copyright over those parts remains on it’s beholder. - +This documentation could be understood as an annotated version of the original “AGW TCPIP Socket Interface” document originally written by George Rossopoulos (**\*SV2AGW\***) and included as a documentation with thw **\*AGWPE\*** package. -This documentation could be understood as an annotated version of the original “AGW TCPIP Socket Interface” document originally written by George Rossopoulos (***SV2AGW\***) and included as a documentation with thw ***AGWPE\*** package. +**\*AGWPE\*** is copyright© of G.Rossopoulos (**\*SV2AGW\***) who held it’s property and the right to change any aspect of the functionality without prior notice. - - -***AGWPE\*** is copyright© of G.Rossopoulos (***SV2AGW\***) who held it’s property and the right to change any aspect of the functionality without prior notice. - ------- +--- [[1\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftnref1) As a reference on a 233 Mhz Pentium it could take as little as 4% of the total processor time and less than 4 MBytes of memory (allocated) under a moderate to heavy port activity. Under idle port conditions the amount of CPU taken might be 0.5% or less. - - -[[2\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftnref2) If (as an example) two 9k6 bps packet ports are serviced the minimum bandwidth between ***AGWPE\*** and each application should be between 3 X 2 X 9K6 = 57K6 and 4 X 2 X 9k6 = 76K8, so a modern 56K dialup connection would be in the lower end to service such arrangement with reasonable performance, assuming the effective speed is about 56K bps and not something lower. +[[2\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftnref2) If (as an example) two 9k6 bps packet ports are serviced the minimum bandwidth between **\*AGWPE\*** and each application should be between 3 X 2 X 9K6 = 57K6 and 4 X 2 X 9k6 = 76K8, so a modern 56K dialup connection would be in the lower end to service such arrangement with reasonable performance, assuming the effective speed is about 56K bps and not something lower. [[3\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftnref3) TCP/IP addressing is not particularly difficult once understood, however, the author of any program that forces the user to deal with them should be prepared to expend a great deal of effort to make the configuration of it as user friendly and “foolproof” as possible. -[[4\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftnref4) Some oddity of the API, while ***AGWPE\*** number the ports in the order of creation starting with Port 1 the API reflects the ports in the same order but starting with 0 (zero). So, the port reflected as Port 1 in the ***AGWPE\*** Properties dialog would be reflected as 0x00 on the API, Port 2 as 0x01, and so on. +[[4\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftnref4) Some oddity of the API, while **\*AGWPE\*** number the ports in the order of creation starting with Port 1 the API reflects the ports in the same order but starting with 0 (zero). So, the port reflected as Port 1 in the **\*AGWPE\*** Properties dialog would be reflected as 0x00 on the API, Port 2 as 0x01, and so on. [[5\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftnref5) When the callsign plus ssid plus the ending null (0x00) requires less than 10 bytes the remaining bytes of the field are not guaranteed to be cleared, data after the null (0x00) must be handled as “garbage” and cleared out by the application program. C programmers would handle it nicely (ASCIIZ variables), Pascal programmers should handle it more carefully. -[[6\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftnref6) An exception to this is when the application terminates a link with a ‘d’ frame and inmediately unregisteres the callsign with a ‘x’ frame, in this situation no further information regarding the fate of the disconnection is sent to the application. In fact, if the unregistration closely follows the ‘d’ frame in such a way that the frame doesn’t have enough time to be sent the other end will be left “connected”, the connection would be terminated then either by the remote end inactivity timeout or when a data exchange attempt is made. \ No newline at end of file +[[6\]](https://www.on7lds.net/42/sites/default/files/AGWPEAPI.HTM#_ftnref6) An exception to this is when the application terminates a link with a ‘d’ frame and inmediately unregisteres the callsign with a ‘x’ frame, in this situation no further information regarding the fate of the disconnection is sent to the application. In fact, if the unregistration closely follows the ‘d’ frame in such a way that the frame doesn’t have enough time to be sent the other end will be left “connected”, the connection would be terminated then either by the remote end inactivity timeout or when a data exchange attempt is made.