1
1
//
2
2
// This file is part of Dire Wolf, an amateur radio packet TNC.
3
3
//
4
- // Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017 John Langner, WB2OSZ
4
+ // Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2020 John Langner, WB2OSZ
5
5
//
6
6
// This program is free software: you can redistribute it and/or modify
7
7
// it under the terms of the GNU General Public License as published by
45
45
* 'k' Ask to start receiving RAW AX25 frames.
46
46
*
47
47
* 'm' Ask to start receiving Monitor AX25 frames.
48
+ * Enables sending of U, I, S, and T messages to client app.
48
49
*
49
50
* 'V' Transmit UI data frame.
50
- * Generate audio for transmission.
51
51
*
52
52
* 'H' Report recently heard stations. Not implemented yet.
53
53
*
89
89
* 'K' Received AX.25 frame in raw format.
90
90
* (Enabled with 'k' command.)
91
91
*
92
- * 'U' Received AX.25 frame in monitor format.
92
+ * 'U' Received AX.25 "UI" frames in monitor format.
93
+ * (Enabled with 'm' command.)
94
+ *
95
+ * 'I' Received AX.25 "I" frames in monitor format. (new in 1.6)
96
+ * (Enabled with 'm' command.)
97
+ *
98
+ * 'S' Received AX.25 "S" and "U" (other than UI) frames in monitor format. (new in 1.6)
99
+ * (Enabled with 'm' command.)
100
+ *
101
+ * 'T' Own Transmitted AX.25 frames in monitor format. (new in 1.6)
93
102
* (Enabled with 'm' command.)
94
103
*
95
104
* 'y' Outstanding frames waiting on a Port (new in 1.2)
@@ -768,10 +777,13 @@ static THREAD_F connect_listen_thread (void *arg)
768
777
*
769
778
* There are two different formats:
770
779
* RAW - the original received frame.
771
- * MONITOR - just the information part .
780
+ * MONITOR - human readable monitoring format .
772
781
*
773
782
*--------------------------------------------------------------------*/
774
783
784
+ static void mon_addrs (int chan , packet_t pp , char * result , int result_size );
785
+ static char mon_desc (packet_t pp , char * result , int result_size );
786
+
775
787
776
788
void server_send_rec_packet (int chan , packet_t pp , unsigned char * fbuf , int flen )
777
789
{
@@ -781,15 +793,11 @@ void server_send_rec_packet (int chan, packet_t pp, unsigned char *fbuf, int fl
781
793
} agwpe_msg ;
782
794
783
795
int err ;
784
- int info_len ;
785
- unsigned char * pinfo ;
786
- int client ;
787
-
788
796
789
797
/*
790
798
* RAW format
791
799
*/
792
- for (client = 0 ; client < MAX_NET_CLIENTS ; client ++ ) {
800
+ for (int client = 0 ; client < MAX_NET_CLIENTS ; client ++ ) {
793
801
794
802
if (enable_send_raw_to_client [client ] && client_sock [client ] > 0 ){
795
803
@@ -839,32 +847,37 @@ void server_send_rec_packet (int chan, packet_t pp, unsigned char *fbuf, int fl
839
847
}
840
848
}
841
849
850
+ // Application might want more human readable format.
842
851
843
- /* MONITOR format - only for UI frames. */
852
+ server_send_monitored ( chan , pp , 0 );
844
853
845
- for (client = 0 ; client < MAX_NET_CLIENTS ; client ++ ) {
846
-
847
- if (enable_send_monitor_to_client [client ] && client_sock [client ] > 0
848
- && ax25_get_control (pp ) == AX25_UI_FRAME ){
854
+ } /* end server_send_rec_packet */
849
855
850
- time_t clock ;
851
- struct tm * tm ;
852
- int num_digi ;
853
856
854
- clock = time (NULL );
855
- tm = localtime (& clock ); // TODO: should use localtime_r
856
857
857
- memset (& agwpe_msg .hdr , 0 , sizeof (agwpe_msg .hdr ));
858
+ void server_send_monitored (int chan , packet_t pp , int own_xmit )
859
+ {
860
+ /*
861
+ * MONITOR format - 'I' for information frames.
862
+ * 'U' for unnumbered information.
863
+ * 'S' for supervisory and other unnumbered.
864
+ */
865
+ struct {
866
+ struct agwpe_s hdr ;
867
+ char data [1 + AX25_MAX_PACKET_LEN ];
868
+ } agwpe_msg ;
858
869
859
- agwpe_msg . hdr . portx = chan ;
870
+ int err ;
860
871
861
- agwpe_msg . hdr . datakind = 'U' ;
872
+ for ( int client = 0 ; client < MAX_NET_CLIENTS ; client ++ ) {
862
873
863
- ax25_get_addr_with_ssid ( pp , AX25_SOURCE , agwpe_msg . hdr . call_from );
874
+ if ( enable_send_monitor_to_client [ client ] && client_sock [ client ] > 0 ) {
864
875
865
- ax25_get_addr_with_ssid ( pp , AX25_DESTINATION , agwpe_msg .hdr . call_to );
876
+ memset ( & agwpe_msg . hdr , 0 , sizeof ( agwpe_msg .hdr ) );
866
877
867
- info_len = ax25_get_info (pp , & pinfo );
878
+ agwpe_msg .hdr .portx = chan ; // datakind is added later.
879
+ ax25_get_addr_with_ssid (pp , AX25_SOURCE , agwpe_msg .hdr .call_from );
880
+ ax25_get_addr_with_ssid (pp , AX25_DESTINATION , agwpe_msg .hdr .call_to );
868
881
869
882
/* http://uz7ho.org.ua/includes/agwpeapi.htm#_Toc500723812 */
870
883
@@ -883,34 +896,34 @@ void server_send_rec_packet (int chan, packet_t pp, unsigned char *fbuf, int fl
883
896
// AGWPE:
884
897
// [AGWE-IN] 1:Fm ZL4FOX-8 To Q7P2U2 Via WIDE3-3 [08:32:14]`I0*l V>/"98}[:Barts Tracker 3.83V X
885
898
886
- num_digi = ax25_get_num_repeaters ( pp );
899
+ // Format the channel and addresses, with leading and trailing space.
887
900
888
- if ( num_digi > 0 ) {
901
+ mon_addrs ( chan , pp , ( char * )( agwpe_msg . data ), sizeof ( agwpe_msg . data ));
889
902
890
- char via [AX25_MAX_REPEATERS * (AX25_MAX_ADDR_LEN + 1 )];
891
- char stemp [AX25_MAX_ADDR_LEN + 1 ];
892
- int j ;
903
+ // Add the description with <... >
893
904
894
- ax25_get_addr_with_ssid (pp , AX25_REPEATER_1 , via );
895
- for (j = 1 ; j < num_digi ; j ++ ) {
896
- ax25_get_addr_with_ssid (pp , AX25_REPEATER_1 + j , stemp );
897
- strlcat (via , "," , sizeof (via ));
898
- strlcat (via , stemp , sizeof (via ));
899
- }
900
-
901
- snprintf (agwpe_msg .data , sizeof (agwpe_msg .data ), " %d:Fm %s To %s Via %s <UI pid=%02X Len=%d >[%02d:%02d:%02d]\r%s\r\r" ,
902
- chan + 1 , agwpe_msg .hdr .call_from , agwpe_msg .hdr .call_to , via ,
903
- ax25_get_pid (pp ), info_len ,
904
- tm -> tm_hour , tm -> tm_min , tm -> tm_sec ,
905
- pinfo );
905
+ char desc [80 ];
906
+ agwpe_msg .hdr .datakind = mon_desc (pp , desc , sizeof (desc ));
907
+ if (own_xmit ) {
908
+ agwpe_msg .hdr .datakind = 'T' ;
906
909
}
907
- else {
910
+ strlcat ((char * )(agwpe_msg .data ), desc , sizeof (agwpe_msg .data ));
911
+
912
+ // Timestamp with [...]\r
913
+
914
+ time_t clock = time (NULL );
915
+ struct tm * tm = localtime (& clock ); // TODO: use localtime_r ?
916
+ char ts [32 ];
917
+ snprintf (ts , sizeof (ts ), "[%02d:%02d:%02d]\r" , tm -> tm_hour , tm -> tm_min , tm -> tm_sec );
918
+ strlcat ((char * )(agwpe_msg .data ), ts , sizeof (agwpe_msg .data ));
908
919
909
- snprintf (agwpe_msg .data , sizeof (agwpe_msg .data ), " %d:Fm %s To %s <UI pid=%02X Len=%d >[%02d:%02d:%02d]\r%s\r\r" ,
910
- chan + 1 , agwpe_msg .hdr .call_from , agwpe_msg .hdr .call_to ,
911
- ax25_get_pid (pp ), info_len ,
912
- tm -> tm_hour , tm -> tm_min , tm -> tm_sec ,
913
- pinfo );
920
+ // Information if any with \r\r.
921
+
922
+ unsigned char * pinfo = NULL ;
923
+ int info_len = ax25_get_info (pp , & pinfo );
924
+ if (info_len > 0 && pinfo != NULL ) {
925
+ strlcat ((char * )(agwpe_msg .data ), (char * )pinfo , sizeof (agwpe_msg .data ));
926
+ strlcat ((char * )(agwpe_msg .data ), "\r" , sizeof (agwpe_msg .data ));
914
927
}
915
928
916
929
agwpe_msg .hdr .data_len_NETLE = host2netle (strlen (agwpe_msg .data ) + 1 ) /* +1 to include terminating null */ ;
@@ -944,9 +957,103 @@ void server_send_rec_packet (int chan, packet_t pp, unsigned char *fbuf, int fl
944
957
}
945
958
}
946
959
947
- } /* server_send_rec_packet */
960
+ } /* server_send_monitored */
961
+
962
+
963
+ // Next two are broken out in case they can be reused elsewhere.
964
+
965
+ // Format addresses in AGWPR monitoring format such as:
966
+ // 1:Fm ZL4FOX-8 To Q7P2U2 Via WIDE3-3
967
+
968
+ static void mon_addrs (int chan , packet_t pp , char * result , int result_size )
969
+ {
970
+ char src [AX25_MAX_ADDR_LEN ];
971
+ char dst [AX25_MAX_ADDR_LEN ];
972
+
973
+ ax25_get_addr_with_ssid (pp , AX25_SOURCE , src );
974
+ ax25_get_addr_with_ssid (pp , AX25_DESTINATION , dst );
975
+ int num_digi = ax25_get_num_repeaters (pp );
976
+
977
+ if (num_digi > 0 ) {
978
+
979
+ char via [AX25_MAX_REPEATERS * (AX25_MAX_ADDR_LEN + 1 )];
980
+ char stemp [AX25_MAX_ADDR_LEN + 1 ];
981
+ int j ;
982
+
983
+ ax25_get_addr_with_ssid (pp , AX25_REPEATER_1 , via );
984
+ for (j = 1 ; j < num_digi ; j ++ ) {
985
+ ax25_get_addr_with_ssid (pp , AX25_REPEATER_1 + j , stemp );
986
+ strlcat (via , "," , sizeof (via ));
987
+ strlcat (via , stemp , sizeof (via ));
988
+ }
989
+ snprintf (result , result_size , " %d:Fm %s To %s Via %s " ,
990
+ chan + 1 , src , dst , via );
991
+ }
992
+ else {
993
+ snprintf (result , result_size , " %d:Fm %s To %s " ,
994
+ chan + 1 , src , dst );
995
+ }
996
+ }
948
997
949
998
999
+ // Generate frame description in AGWPE monitoring format such as
1000
+ // <UI pid=F0 Len=123 >
1001
+ // <I R1 S3 pid=F0 Len=123 >
1002
+ // <RR P1 R5 >
1003
+ //
1004
+ // Returns:
1005
+ // 'I' for information frame.
1006
+ // 'U' for unnumbered information frame.
1007
+ // 'S' for supervisory and other unnumbered frames.
1008
+
1009
+ static char mon_desc (packet_t pp , char * result , int result_size )
1010
+ {
1011
+ cmdres_t cr ; // command/response.
1012
+ char ignore [80 ]; // direwolf description. not used here.
1013
+ int pf ; // poll/final bit.
1014
+ int ns ; // N(S) Send sequence number.
1015
+ int nr ; // N(R) Received sequence number.
1016
+ char pf_text [4 ]; // P or F depending on whether command or response.
1017
+
1018
+ ax25_frame_type_t ftype = ax25_frame_type (pp , & cr , ignore , & pf , & nr , & ns );
1019
+
1020
+ switch (cr ) {
1021
+ case cr_cmd : strcpy (pf_text , "P" ); break ; // P only: I, SABME, SABM, DISC
1022
+ case cr_res : strcpy (pf_text , "F" ); break ; // F only: DM, UA, FRMR
1023
+ // Either: RR, RNR, REJ, SREJ, UI, XID, TEST
1024
+
1025
+ default : strcpy (pf_text , "PF" ); break ; // Not AX.25 version >= 2.0
1026
+ // APRS is often sloppy about this but it
1027
+ // is essential for connected mode.
1028
+ }
1029
+
1030
+ unsigned char * pinfo = NULL ; // I, UI, XID, SREJ, TEST can have information part.
1031
+ int info_len = ax25_get_info (pp , & pinfo );
1032
+
1033
+ switch (ftype ) {
1034
+
1035
+ case frame_type_I : snprintf (result , result_size , "<I S%d R%d pid=0x%02X Len=%d %s=%d >" , ns , nr , ax25_get_pid (pp ), info_len , pf_text , pf ); return ('I' );
1036
+
1037
+ case frame_type_U_UI : snprintf (result , result_size , "<UI pid=%02X Len=%d %s=%d >" , ax25_get_pid (pp ), info_len , pf_text , pf ); return ('U' ); break ;
1038
+
1039
+ case frame_type_S_RR : snprintf (result , result_size , "<RR R%d %s=%d >" , nr , pf_text , pf ); return ('S' ); break ;
1040
+ case frame_type_S_RNR : snprintf (result , result_size , "<RNR R%d %s=%d >" , nr , pf_text , pf ); return ('S' ); break ;
1041
+ case frame_type_S_REJ : snprintf (result , result_size , "<REJ R%d %s=%d >" , nr , pf_text , pf ); return ('S' ); break ;
1042
+ case frame_type_S_SREJ : snprintf (result , result_size , "<SREJ R%d %s=%d Len=%d >" , nr , pf_text , pf , info_len ); return ('S' ); break ;
1043
+
1044
+ case frame_type_U_SABME : snprintf (result , result_size , "<SABME %s=%d >" , pf_text , pf ); return ('S' ); break ;
1045
+ case frame_type_U_SABM : snprintf (result , result_size , "<SABM %s=%d >" , pf_text , pf ); return ('S' ); break ;
1046
+ case frame_type_U_DISC : snprintf (result , result_size , "<DISC %s=%d >" , pf_text , pf ); return ('S' ); break ;
1047
+ case frame_type_U_DM : snprintf (result , result_size , "<DM %s=%d >" , pf_text , pf ); return ('S' ); break ;
1048
+ case frame_type_U_UA : snprintf (result , result_size , "<UA %s=%d >" , pf_text , pf ); return ('S' ); break ;
1049
+ case frame_type_U_FRMR : snprintf (result , result_size , "<FRMR %s=%d >" , pf_text , pf ); return ('S' ); break ;
1050
+ case frame_type_U_XID : snprintf (result , result_size , "<XID %s=%d Len=%d >" , pf_text , pf , info_len ); return ('S' ); break ;
1051
+ case frame_type_U_TEST : snprintf (result , result_size , "<TEST %s=%d Len=%d >" , pf_text , pf , info_len ); return ('S' ); break ;
1052
+ default :
1053
+ case frame_type_U : snprintf (result , result_size , "<U other??? >" ); return ('S' ); break ;
1054
+ }
1055
+ }
1056
+
950
1057
951
1058
/*-------------------------------------------------------------------
952
1059
*
0 commit comments