AGW TCPIP Socket Interface New ver (2000) AGW Packet Engine can serve as the L2 for your Packet Application. That Way you can take advantage of the many unique features of AGW Packet Engine. So far the only way to communicate with AGW Packet Engine was the DDEML. In this document will i will describe the new way using tcpip sockets. How to Enable tne new interface New Versions have an appropriate menu entry. How to Start your application and register with AGW PAcket Engine First of all create a stream socket and connect with AGW Packet Engine ip address at port 8000. If your application is running at the same machine with agwpe then as ip address use localhost (127.0.0.1). After connecting you need to register your application's callsign if your application need to establish ax25 connections. If your application just do monitoring and sends Unproto frames ,no need for callsign registration. You can register as many as 100 d ifferent callsigns. If you register a callsign then agw packet engine accepts AX25 connections for this call. You then ask agwpe to send you the radioport information. How many radioports are with their describtion. After that you can create your windows or anything else. Now you are ready. If you wish to do monitoring then you must enable monitoring. How AGWPE communicates with your application This is done with frames. Each frame has a header that describes the frame and after the header are the data. The header format is as follow int Port; (4 bytse long )(LOWORD contins the port info,HIWORD is reserved)0 is the first port , 1 is the second port,2 is the third and so on.. int DataKind; the datakind 4 bytes long(THe LOWORD conatins the kind of this frame) The HIWORD is used as stated below unsigned char CallFrom[10]; NULL terminated 10 bytes long including the NULL char. unsigned char CallTo[10]; NULL terminated 10 bytes long including the NULL char. int DataLen; The length of the data that follow. This field is 4 bytes long(32bit) int USER (4 bytes long) reserved,undefined. The two callsign fields may be empty. And are in plain text,like SV2AGW-12. The callsign may be less than 10 characters and the NULL terminating character is always at the end of the call not at the 10th character. **** CAUTION******** 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 2.Examine the header and the DataLen field 3.If the DataLen field is greater than 0 check to see if there are in the stream socket DataLen bytes. 4.If there are DataLen bytes then read exactly DataLen bytes no more, otherwise wait until DataLen bytes are available. 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. What Kind Of Frames AGW Packet Engine sends to Your Program MONITOR FRAMES 1.UNPROTO monitor frame The LOWORD Port field is the port which heard the frame The LOWORD DataKind field ='U'; The ASCII value of letter U CallFrom= is the call from the station we heard the Packet CallTo =is the destination call (CQ,BEACON etc) DataLen= is the length of the data that follow the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes 2.DATA That We transmit The LOWORD Port field is the port which heard the frame The LOWORD DataKind field ='T'; The ASCII value of letter T CallFrom =The call from which we heard the frame CallTo=is the call to whom we send the frame DataLen is the length of the data that follow USER is undefined. the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes 3.SUpervisory Frames (only Header) (RR,REJ etc) The LOWORD Port field is the port which heard the frame The LOWORD DataKind field ='S'; The ASCII value of letter S CallFrom is empty (NULL) CallTo is empty NULL DataLen is the length of the data that follow USER is undefined. the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes 4.Connected data from other stations The LOWORD Port field is the port which heard the frame The LOWORD DataKind field ='I'; The ASCII value of letter I CallFrom is empty (NULL) CallTo is empty NULL DataLen is the length of the data that follow USER is undefined. the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes STATUS FRAMES(Connect, disconnect,Mheard list,and radioport info ................................................................ 1.Connect( if we connect with another station) The LOWORD Port field is the port which heard the frame The LOWORD DataKind field ='C'; The ASCII value of letter C CallFrom the callsign of the station with whom we connect CallTo is empty (NULL) DataLen is the length of the status message that follow USER is undefined. the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER][status message ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes The status messages are two a)"*** CONNECTED To Station [CALLSIGN]" When the other station starts the connection b)"*** CONNECTED With [CALLSIGN]" When we started the connection 2.Disconnect The LOWORD Port field is the port which heard the frame The LOWORD DataKind field ='d'; The ASCII value of letter d (lower case value) CallFrom the callsign of the station from whom we disconnect CallTo is empty (NULL) DataLen is the length of the status message that follow USER is Undefined the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER][status message ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes The status messages are two a)"*** DISCONNECTED From Station [CALLSIGN]" when we disconnect b)"*** DISCONNECTED RETRYOUT With [CALLSIGN]" When no answer from other station 3.How Many Outstanding frames wait for tx for a particular station The LOWORD Port field is the port The LOWORD DataKind field ='Y'; The ASCII value of letter Y CallFrom our callsign or empty CallTo is the callsign of the station for whome is the value DataLen is the number of outstanding frames USER is undefined There are no data the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes 4.RadioPort information The LOWORD Port field is always 0 The LOWORD DataKind field ='G'; The ASCII value of letter G CallFrom empty(NULL) CallTo empty(NULL) DataLen is the length of the data that follow USER is undefined the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes the data field format is as follow in plain text howmany ports ;1st radioport description;2nd radioport;....;last radioport describtion like 2;TNC2 on serialport 1;OE5DXL on serialport2; We have here 2 radioports. The separator is the ';' 5.MHEARD LIST The LOWORD Port field is the port for which the list is The LOWORD DataKind field ='H'; the ASCII value of letter H CallFrom empty the call of the station in the mheard list CallTo empty(NULL) DataLen is the length of the data that follow USER is undefined [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes the data field format is as follow. First there is a string (Null Terminated) with all the info like SV2AGW Fri,22JAN1999 08:10:32 Fri,22JAN1999 22:08:03 Then follows two SYSTEMTIME structers (check windows help) The first is the time when the station first heard and the second when last heard. You will receive 20 separate frames for the radioport you asked the MHEARD list. Many of them may be empty so check first the CallFrom Field to see if it is empty. 6.RadioPort Capabilities We receive a frame like this The LOWORD Port field is the RadioPort The LOWORD DataKind field ='g'; The ASCII value of lower case letter g CallFrom empty(NULL) CallTo empty(NULL) DataLen is the length of the data that follow USER is undefined the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes the data field format is as follow and it is a structure unsigned char OnairBaud; unsigned char TrafficLevel;// if this is 255 then the port is not in autoupdate mode unsigned char TxDelay; unsigned char TxTail; unsigned char Persist; unsigned char Slottime; unsigned char maxframe; unsigned char AX25Channels; // How many connections we have unsigned int HowManyBytes;// how many bytes are received the last 2 minutes 6.Version Number The LOWORD Port field= is undefined The LOWORD DataKind field ='R'; the ASCII value of letter R CallFrom ==Undefined CallTo = Undefined DataLen is the length of the data that follow USER is undefined [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes the data field Conatains two 32bit integers. The first is the Major Version and the Second is the Minor Version. The first version that has this feauture is 98.90 (Major ver=98,minor ver=90). DATA FROM Connected Stations The LOWORD Port field is the port which heard the frame The LOWORD DataKind field ='D'; The ASCII value of letter D The HIWORD contains the PID info for this frame CallFrom is the call of the other station CallTo is our call. We may have more than a callsign DataLen is the length of the data that follow USER is undefined the whole frame with the header is [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes How your application can communicate with AGWPE The format is the same as with the received frames a header and then the data if there are any int Port; (4 bytse long )(LOWORD contins the port info,HIWORD is reserved)0 is the first port , 1 is the second port,2 is the third and so on.. int DataKind; the datakind 4 bytes long(THe LOWORD conatins the kind of this frame) The HIWORD is used as stated below unsigned char CallFrom[10]; NULL terminated 10 bytes long including the NULL char. unsigned char CallTo[10]; NULL terminated 10 bytes long including the NULL char. int DataLen; The length of the data that follow. This field is 4 bytes long(32bit) int USER (4 bytes long) reserved,undefined. EXAMPLE This is a function that we use to send data over our stream socket to agwpe.We use it for certain frame kinds. The port integer varible is connstructed s follow MAKELONG(0,0);//to tx from port 0 The sme with the DataKid MKELONG('D',0); void SendPacket(char *ToCall,char *str,int count,int DataKind,int port) { if (count==0) count=lstrlen(str); char szTemp[3000]; MoveMemory(szTemp.&port,sizeof(int));//which port to tx MoveMemory(szTemp+sizeof(int),&DataKind,sizeof(int));datakind here LOWORD should be 'D' datakind here should be 'D' MoveMemory(szTemp+(sizeof(int)*2),MyCall,strlen(MyCall)+1);//mycall MoveMemory(szTemp+(sizeof(int)*2)+10,ToCall,strlen(ToCall)+1);//other station call MoveMemory(szTemp+(sizeof(int)*2)+10+10,&count,4);//length of the data we send to other station MoveMemory(szTemp+(sizeof(int)*4)+10+10,str,count+1);//now add the actual data after leving 4 additional bytes for USER which are reserved for the moment; TXDATA(szTemp,count+26);//send them over our socket connection } Transmit DATA To Connected Stations ........................... Port field is the port where we want the data to tx DataKind field =MAKELONG('D',0); The ASCII value of letter D CallFrom is our call CallTo is the call of the other station DataLen is the length of the data that follow USER is undefined the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes EXAMPLE Assume that we wish to send "Hello" to SV2BBO with whom we are already connected at radioport 1. SendPacket("SV2BBO","Hello\r",6,MAKELONG('D',0),MAKELONG(0,0)) Transmit DATA UNPROTO ..................... Port field is the port where we want the data to tx DataKind field =MAKELONG('M',0); The ASCII value of letter M CallFrom is our call CallTo is the call of the other station DataLen is the length of the data that follow USER is udefined the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes EXAMPLE We send a beacon text. String test contains the Beacon text and we tx the beacon over all our radioports for (int x=0;xWrite((char *)&Header,sizeof(Header));//send it to AGWPE using our stream socket Register our CallSign ...................... We need to register a call if we wish to accept connections for this callsign. That way when agwpe listend a packet for that call will notify us Port field must be 0 DataKind field =MKELONNG('X',0); The ASCII value of letter X CallFrom is our callsign CallTo is empty(NULL) DataLen must be 0 USER is undefined No data field must exists [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4byte 10bytes 10bytes 4bytes 4bytes int Count=0; char szTemp[50]; MoveMemory(szTemp.&port,sizeof(int));//which port to tx MoveMemory(szTemp+sizeof(int),&DataKind,sizeof(int));datakind here LOWORD should be 'X' datakind here should be 'D' MoveMemory(szTemp+(sizeof(int)*2),MyCall,strlen(MyCall)+1);//mycall the call we wish to register MoveMemory(szTemp+(sizeof(int)*2)+10,ToCall,strlen(MyCall)+1); MoveMemory(szTemp+(sizeof(int)*2)+10+10,&count,4);//length of the data we send to other station MoveMemory(szTemp+(sizeof(int)*3)+10+10,&count,4);//User is undefined TXDATA(szTemp,36);//send the header over our stream socket to agwpe Unregister previously registered callsign ......................................... Doing so AGWPE will stop responding to incoming packets for that callsign Port field must be 0 DataKind field =MAKELONG('x',0); The ASCII value of letter x lower case CallFrom is the callsign we wish to unregister CallTo is empty(NULL) DataLen must be 0 USER is undefined No data field must exists [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes int Count=0; char szTemp[50]; MoveMemory(szTemp.&port,sizeof(int));//which port to tx MoveMemory(szTemp+sizeof(int),&DataKind,sizeof(int));datakind here LOWORD should be 'x' datakind here should be 'D' MoveMemory(szTemp+(sizeof(int)*2),MyCall,strlen(MyCall)+1);//mycall the call we wish to unregister MoveMemory(szTemp+(sizeof(int)*2)+10,ToCall,strlen(MyCall)+1); MoveMemory(szTemp+(sizeof(int)*2)+10+10,&count,4);//length of the data we send to other station MoveMemory(szTemp+(sizeof(int)*3)+10+10,&count,4);//User is undefined TXDATA(szTemp,36);//send the header over our stream socket to agwpe Connect using a special PID ............................ We can use it eg for netrom connections Port field is the port where we want the connection to be done DataKind field =MAKELONG('c',0); The ASCII value of letter c(Lower case) CallFrom is our call CallTo is the call of the other station DataLen must be 1 USER is undefined the data field is 1 byte long and contains the PID value the whole frame with the header is [ HEADER ] [port] [DataKind][CallFrom][CallTo ][DataLen][USER] [Data ] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes DataLen Bytes Connect ....... Port field is the port where we want the connection to be done DataKind field =MAKELONG('C',0); The ASCII value of letter C CallFrom is the call of the other station CallTo is our call DataLen must be 0 USER is undefined No data field must be present the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4byte 10bytes 10bytes 4bytes 4bytes Connect VIA ............ Port field is the port where we want the connection to be done DataKind field =MAKELONG('v',0); The ASCII value of letter v(Lower case v) CallFrom is our call CallTo is the call of the other station USER is undefined DataLen the length of the data frame where the via calls are the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER][Data ] 4bytes 4bytes 10bytes 10bytes 4bytes . 4bytes DataLen Bytes The data field is in special format and contains the via callsigns like [ DATA field ] [How many digis] [1stdigicall][2digicall]....... byte 10bytes 10bytes Be carefull each digi call must be 10 char long Null terminated.If sorter then next digi must exactly after 10 bytes as follow e.g char str[100]; str[0]=HowManyDigis; str+1=1digi;//null terminated str+1+10=2digi;//null terminated str+1+20=3digi//null terminated .............. .............. int count; count=PrepareViaList(Via,ViaList);//prepare the via list in special format if (!count) return;//no via list,something wrong return memmove(str,ViaList,count); count++; MoveMemory(szTemp.&port,sizeof(int));//which port to tx MoveMemory(szTemp+sizeof(int),&DataKind,sizeof(int));datakind here LOWORD should be 'x' datakind here should be 'D' MoveMemory(szTemp+(sizeof(int)*2),MyCall,strlen(MyCall)+1);//mycall the call we wish to unregister MoveMemory(szTemp+(sizeof(int)*2)+10,ToCall,strlen(MyCall)+1); MoveMemory(szTemp+(sizeof(int)*2)+10+10,&count,4);//length of the data we send to other station MoveMemory(szTemp+(sizeof(int)*3)+10+10,&count,4);//User is undefined MoveMemory(szTemp+(sizeof(int)*4)+10+10,str,count);//vi list formatted string TXDATA(szTemp,count+36); int PrepareViaList(char *InVia,char *OutVia) { //InVia string contains the via list like SV2AGW,SV2BBO,SV2DFK //OutVia is the same list suitable prepared for agwpe char *token; char temp[15]; char HowVia=0; token=strtok(InVia,", "); if (token) { HowVia++; 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); } DisConnect ....... Port field is the port where we want the Disconnection to be done DataKind field =MAKELONG('d',0); The ASCII value of letter d(Lower case d) CallFrom is our call CallTo is the call of the other station DataLen must be 0 USER is undefined No data field must be present the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes ASK how many outstanding frames are for a station .................................................. Port field is the port DataKind field =MAKELONG('Y',0); The ASCII value of letter Y CallFrom is our call CallTo is the call of the other station DataLen must be 0 USER is undefined No data field must be present the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes ASK MHEARD list for a radioport ............................... Port field is the port DataKind field =MAKELONG('H',0); The ASCII value of letter H CallFrom is empty no needed CallTo is empty no needed DataLen must be 0 USER is undefined No data field must be present the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes ASK To start receiving Monitor Frames Port field no needed set it to 0 DataKind field =MAKELONG('m',0); The ASCII value of lower case letter m CallFrom is empty no needed CallTo is empty no needed DataLen must be 0 USER is undefined No data field must be present the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes ASK To Receive RadioPort CapaBilities Port field LOWORD is the radioPort to query DataKind field =MAKELONG('g',0); The ASCII value of lower case letter g CallFrom is empty no needed CallTo is empty no needed DataLen must be 0 USER is undefined No data field must be present the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes ASK To Receive AGWPE Version Info Port field is undefined (no needed) DataKind field =MKELONG('R',0); The ASCII value of letter R CallFrom is empty no needed CallTo is empty no needed DataLen must be 0 USER is undefined No data field must be present the whole frame with the header is [ HEADER ] [port][DataKind][CallFrom][CallTo ][DataLen][USER] 4bytes 4bytes 10bytes 10bytes 4bytes 4bytes ******* NEW COMMANDS ******** Confirmation of Registration Port field is undefined DataKind field ='X' CallFrom empty CallTo empty DataLen 1 User empty DataField 1 byte 0x00 Registration Failed 0x01 Registration Succeed Return of Y Command Port Field empty DataKind 'Y' CallFrom Call From Sent with 'Y' CallTo Call To Sent with 'Y' DataLen 4 User empty Data 32 bits integer with Outstanding frames for this callsign Query of Outstanding frames on a given Port Port Field Port to Query DataKind 'y' CallFrom Empty CallTo Empty DataLen 4 User Empty Data 32 bits integer with Outstanding frames for this port