1
1
//
2
2
// This file is part of Dire Wolf, an amateur radio packet TNC.
3
3
//
4
- // Copyright (C) 2016, 2017, 2018, 2023, 2024 John Langner, WB2OSZ
4
+ // Copyright (C) 2016, 2017, 2018, 2023, 2024, 2025 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
@@ -599,6 +599,8 @@ static int AX25MODULO(int n, int m, const char *file, const char *func, int line
599
599
// TODO: add SELECT_T1_VALUE for debugging.
600
600
601
601
602
+ static void dl_connection_cleanup (ax25_dlsm_t * S );
603
+ static void dl_connection_terminated (ax25_dlsm_t * S );
602
604
static void dl_data_indication (ax25_dlsm_t * S , int pid , char * data , int len );
603
605
604
606
static void i_frame (ax25_dlsm_t * S , cmdres_t cr , int p , int nr , int ns , int pid , char * info_ptr , int info_len );
@@ -1101,6 +1103,7 @@ void dl_disconnect_request (dlq_item_t *E)
1101
1103
text_color_set (DW_COLOR_INFO );
1102
1104
dw_printf ("Stream %d: Disconnected from %s.\n" , S -> stream_id , S -> addrs [PEERCALL ]);
1103
1105
server_link_terminated (S -> chan , S -> client , S -> addrs [PEERCALL ], S -> addrs [OWNCALL ], 0 );
1106
+ dl_connection_terminated (S );
1104
1107
break ;
1105
1108
1106
1109
case state_1_awaiting_connection :
@@ -1129,6 +1132,7 @@ void dl_disconnect_request (dlq_item_t *E)
1129
1132
STOP_T3 ; // probably don't need.
1130
1133
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
1131
1134
server_link_terminated (S -> chan , S -> client , S -> addrs [PEERCALL ], S -> addrs [OWNCALL ], 0 );
1135
+ dl_connection_terminated (S );
1132
1136
break ;
1133
1137
1134
1138
case state_2_awaiting_release :
@@ -1159,6 +1163,7 @@ void dl_disconnect_request (dlq_item_t *E)
1159
1163
1160
1164
STOP_T1 ;
1161
1165
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
1166
+ dl_connection_terminated (S );
1162
1167
}
1163
1168
break ;
1164
1169
@@ -1742,6 +1747,133 @@ void dl_outstanding_frames_request (dlq_item_t *E)
1742
1747
1743
1748
1744
1749
1750
+ /*------------------------------------------------------------------------------
1751
+ *
1752
+ * Name: dl_connection_cleanup
1753
+ *
1754
+ * Purpose: Clean out a specific state machine and its references, freeing
1755
+ * associated memory.
1756
+ *
1757
+ * Inputs: S - Data Link State Machine.
1758
+ *
1759
+ * Description: Clean out a specific state machine and anything related to it.
1760
+ * Free the associated memory.
1761
+ *
1762
+ *------------------------------------------------------------------------------*/
1763
+
1764
+ static void dl_connection_cleanup (ax25_dlsm_t * S )
1765
+ {
1766
+ int n ;
1767
+
1768
+ if (s_debug_stats ) {
1769
+ text_color_set (DW_COLOR_INFO );
1770
+ dw_printf ("%d I frames received\n" , S -> count_recv_frame_type [frame_type_I ]);
1771
+
1772
+ dw_printf ("%d RR frames received\n" , S -> count_recv_frame_type [frame_type_S_RR ]);
1773
+ dw_printf ("%d RNR frames received\n" , S -> count_recv_frame_type [frame_type_S_RNR ]);
1774
+ dw_printf ("%d REJ frames received\n" , S -> count_recv_frame_type [frame_type_S_REJ ]);
1775
+ dw_printf ("%d SREJ frames received\n" , S -> count_recv_frame_type [frame_type_S_SREJ ]);
1776
+
1777
+ dw_printf ("%d SABME frames received\n" , S -> count_recv_frame_type [frame_type_U_SABME ]);
1778
+ dw_printf ("%d SABM frames received\n" , S -> count_recv_frame_type [frame_type_U_SABM ]);
1779
+ dw_printf ("%d DISC frames received\n" , S -> count_recv_frame_type [frame_type_U_DISC ]);
1780
+ dw_printf ("%d DM frames received\n" , S -> count_recv_frame_type [frame_type_U_DM ]);
1781
+ dw_printf ("%d UA frames received\n" , S -> count_recv_frame_type [frame_type_U_UA ]);
1782
+ dw_printf ("%d FRMR frames received\n" , S -> count_recv_frame_type [frame_type_U_FRMR ]);
1783
+ dw_printf ("%d UI frames received\n" , S -> count_recv_frame_type [frame_type_U_UI ]);
1784
+ dw_printf ("%d XID frames received\n" , S -> count_recv_frame_type [frame_type_U_XID ]);
1785
+ dw_printf ("%d TEST frames received\n" , S -> count_recv_frame_type [frame_type_U_TEST ]);
1786
+
1787
+ dw_printf ("%d peak retry count\n" , S -> peak_rc_value );
1788
+ }
1789
+
1790
+ if (s_debug_client_app ) {
1791
+ text_color_set (DW_COLOR_DEBUG );
1792
+ dw_printf ("dl_connection_cleanup: remove %s>%s\n" , S -> addrs [AX25_SOURCE ], S -> addrs [AX25_DESTINATION ]);
1793
+ }
1794
+
1795
+ discard_i_queue (S );
1796
+
1797
+ for (n = 0 ; n < 128 ; n ++ ) {
1798
+ if (S -> txdata_by_ns [n ] != NULL ) {
1799
+ cdata_delete (S -> txdata_by_ns [n ]);
1800
+ S -> txdata_by_ns [n ] = NULL ;
1801
+ }
1802
+ }
1803
+
1804
+ for (n = 0 ; n < 128 ; n ++ ) {
1805
+ if (S -> rxdata_by_ns [n ] != NULL ) {
1806
+ cdata_delete (S -> rxdata_by_ns [n ]);
1807
+ S -> rxdata_by_ns [n ] = NULL ;
1808
+ }
1809
+ }
1810
+
1811
+ if (S -> ra_buff != NULL ) {
1812
+ cdata_delete (S -> ra_buff );
1813
+ S -> ra_buff = NULL ;
1814
+ }
1815
+
1816
+ // Put into disconnected state.
1817
+ // If "connected" indicator (e.g. LED) was on, this will turn it off.
1818
+
1819
+ enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
1820
+
1821
+ S -> magic1 = 0 ;
1822
+ S -> magic2 = 0 ;
1823
+ S -> magic3 = 0 ;
1824
+
1825
+ free (S );
1826
+
1827
+ } /* end dl_connection_cleanup */
1828
+
1829
+
1830
+
1831
+ /*------------------------------------------------------------------------------
1832
+ *
1833
+ * Name: dl_connection_terminated
1834
+ *
1835
+ * Purpose: Connection has gone away. Clean up any data associated with it.
1836
+ *
1837
+ * Inputs: S - Data Link State Machine.
1838
+ *
1839
+ * Description: Clean out anything related to the specified connection, and
1840
+ * remove the associated state machine from the list.
1841
+ *
1842
+ *------------------------------------------------------------------------------*/
1843
+
1844
+ static void dl_connection_terminated (ax25_dlsm_t * S )
1845
+ {
1846
+ ax25_dlsm_t * dlentry ;
1847
+ ax25_dlsm_t * dlprev ;
1848
+
1849
+ // Look for corruption or double freeing.
1850
+
1851
+ assert (S -> magic1 == MAGIC1 );
1852
+ assert (S -> magic2 == MAGIC2 );
1853
+ assert (S -> magic3 == MAGIC3 );
1854
+
1855
+ // Remove from the list.
1856
+
1857
+ dlprev = NULL ;
1858
+ dlentry = list_head ;
1859
+ while (dlentry != S ) {
1860
+ dlprev = dlentry ;
1861
+ dlentry = dlentry -> next ;
1862
+ }
1863
+ if (!dlprev ) {
1864
+ list_head = dlentry -> next ;
1865
+ } else {
1866
+ dlprev -> next = dlentry -> next ;
1867
+ }
1868
+
1869
+ // Clean up the connection.
1870
+
1871
+ dl_connection_cleanup (S );
1872
+
1873
+ } /* end dl_connection_terminated */
1874
+
1875
+
1876
+
1745
1877
/*------------------------------------------------------------------------------
1746
1878
*
1747
1879
* Name: dl_client_cleanup
@@ -1785,76 +1917,15 @@ void dl_client_cleanup (dlq_item_t *E)
1785
1917
1786
1918
if (S -> client == E -> client ) {
1787
1919
1788
- int n ;
1789
-
1790
- if (s_debug_stats ) {
1791
- text_color_set (DW_COLOR_INFO );
1792
- dw_printf ("%d I frames received\n" , S -> count_recv_frame_type [frame_type_I ]);
1793
-
1794
- dw_printf ("%d RR frames received\n" , S -> count_recv_frame_type [frame_type_S_RR ]);
1795
- dw_printf ("%d RNR frames received\n" , S -> count_recv_frame_type [frame_type_S_RNR ]);
1796
- dw_printf ("%d REJ frames received\n" , S -> count_recv_frame_type [frame_type_S_REJ ]);
1797
- dw_printf ("%d SREJ frames received\n" , S -> count_recv_frame_type [frame_type_S_SREJ ]);
1798
-
1799
- dw_printf ("%d SABME frames received\n" , S -> count_recv_frame_type [frame_type_U_SABME ]);
1800
- dw_printf ("%d SABM frames received\n" , S -> count_recv_frame_type [frame_type_U_SABM ]);
1801
- dw_printf ("%d DISC frames received\n" , S -> count_recv_frame_type [frame_type_U_DISC ]);
1802
- dw_printf ("%d DM frames received\n" , S -> count_recv_frame_type [frame_type_U_DM ]);
1803
- dw_printf ("%d UA frames received\n" , S -> count_recv_frame_type [frame_type_U_UA ]);
1804
- dw_printf ("%d FRMR frames received\n" , S -> count_recv_frame_type [frame_type_U_FRMR ]);
1805
- dw_printf ("%d UI frames received\n" , S -> count_recv_frame_type [frame_type_U_UI ]);
1806
- dw_printf ("%d XID frames received\n" , S -> count_recv_frame_type [frame_type_U_XID ]);
1807
- dw_printf ("%d TEST frames received\n" , S -> count_recv_frame_type [frame_type_U_TEST ]);
1808
-
1809
- dw_printf ("%d peak retry count\n" , S -> peak_rc_value );
1810
- }
1811
-
1812
- if (s_debug_client_app ) {
1813
- text_color_set (DW_COLOR_DEBUG );
1814
- dw_printf ("dl_client_cleanup: remove %s>%s\n" , S -> addrs [AX25_SOURCE ], S -> addrs [AX25_DESTINATION ]);
1815
- }
1816
-
1817
- discard_i_queue (S );
1818
-
1819
- for (n = 0 ; n < 128 ; n ++ ) {
1820
- if (S -> txdata_by_ns [n ] != NULL ) {
1821
- cdata_delete (S -> txdata_by_ns [n ]);
1822
- S -> txdata_by_ns [n ] = NULL ;
1823
- }
1824
- }
1825
-
1826
- for (n = 0 ; n < 128 ; n ++ ) {
1827
- if (S -> rxdata_by_ns [n ] != NULL ) {
1828
- cdata_delete (S -> rxdata_by_ns [n ]);
1829
- S -> rxdata_by_ns [n ] = NULL ;
1830
- }
1831
- }
1832
-
1833
- if (S -> ra_buff != NULL ) {
1834
- cdata_delete (S -> ra_buff );
1835
- S -> ra_buff = NULL ;
1836
- }
1837
-
1838
- // Put into disconnected state.
1839
- // If "connected" indicator (e.g. LED) was on, this will turn it off.
1840
-
1841
- enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
1842
-
1843
- // Take S out of list.
1844
-
1845
- S -> magic1 = 0 ;
1846
- S -> magic2 = 0 ;
1847
- S -> magic3 = 0 ;
1848
-
1849
1920
if (S == list_head ) { // first one on list.
1850
1921
1851
1922
list_head = S -> next ;
1852
- free (S );
1923
+ dl_connection_cleanup (S );
1853
1924
S = list_head ;
1854
1925
}
1855
1926
else { // not the first one.
1856
1927
dlprev -> next = S -> next ;
1857
- free (S );
1928
+ dl_connection_cleanup (S );
1858
1929
S = dlprev -> next ;
1859
1930
}
1860
1931
}
@@ -4504,6 +4575,7 @@ static void disc_frame (ax25_dlsm_t *S, int p)
4504
4575
STOP_T1 ;
4505
4576
STOP_T3 ;
4506
4577
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
4578
+ dl_connection_terminated (S );
4507
4579
}
4508
4580
break ;
4509
4581
}
@@ -4591,6 +4663,7 @@ static void dm_frame (ax25_dlsm_t *S, int f)
4591
4663
server_link_terminated (S -> chan , S -> client , S -> addrs [PEERCALL ], S -> addrs [OWNCALL ], 0 );
4592
4664
STOP_T1 ;
4593
4665
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
4666
+ dl_connection_terminated (S );
4594
4667
}
4595
4668
else {
4596
4669
// keep current state.
@@ -4613,6 +4686,7 @@ static void dm_frame (ax25_dlsm_t *S, int f)
4613
4686
server_link_terminated (S -> chan , S -> client , S -> addrs [PEERCALL ], S -> addrs [OWNCALL ], 0 );
4614
4687
STOP_T1 ;
4615
4688
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
4689
+ dl_connection_terminated (S );
4616
4690
}
4617
4691
else {
4618
4692
// keep current state.
@@ -4634,6 +4708,7 @@ static void dm_frame (ax25_dlsm_t *S, int f)
4634
4708
STOP_T1 ;
4635
4709
STOP_T3 ;
4636
4710
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
4711
+ dl_connection_terminated (S );
4637
4712
break ;
4638
4713
4639
4714
case state_5_awaiting_v22_connection :
@@ -4651,6 +4726,7 @@ static void dm_frame (ax25_dlsm_t *S, int f)
4651
4726
server_link_terminated (S -> chan , S -> client , S -> addrs [PEERCALL ], S -> addrs [OWNCALL ], 0 );
4652
4727
STOP_T1 ;
4653
4728
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
4729
+ dl_connection_terminated (S );
4654
4730
}
4655
4731
else {
4656
4732
// keep current state.
@@ -4858,6 +4934,7 @@ static void ua_frame (ax25_dlsm_t *S, int f)
4858
4934
server_link_terminated (S -> chan , S -> client , S -> addrs [PEERCALL ], S -> addrs [OWNCALL ], 0 );
4859
4935
STOP_T1 ;
4860
4936
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
4937
+ dl_connection_terminated (S );
4861
4938
}
4862
4939
else {
4863
4940
if (s_debug_protocol_errors ) {
@@ -5374,6 +5451,7 @@ static void t1_expiry (ax25_dlsm_t *S)
5374
5451
dw_printf ("Failed to connect to %s after %d tries.\n" , S -> addrs [PEERCALL ], S -> n2_retry );
5375
5452
server_link_terminated (S -> chan , S -> client , S -> addrs [PEERCALL ], S -> addrs [OWNCALL ], 1 );
5376
5453
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
5454
+ dl_connection_terminated (S );
5377
5455
}
5378
5456
else {
5379
5457
cmdres_t cmd = cr_cmd ;
@@ -5400,6 +5478,7 @@ static void t1_expiry (ax25_dlsm_t *S)
5400
5478
dw_printf ("Stream %d: Disconnected from %s.\n" , S -> stream_id , S -> addrs [PEERCALL ]);
5401
5479
server_link_terminated (S -> chan , S -> client , S -> addrs [PEERCALL ], S -> addrs [OWNCALL ], 0 );
5402
5480
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
5481
+ dl_connection_terminated (S );
5403
5482
}
5404
5483
else {
5405
5484
cmdres_t cmd = cr_cmd ;
@@ -5473,6 +5552,7 @@ static void t1_expiry (ax25_dlsm_t *S)
5473
5552
lm_data_request (S -> chan , TQ_PRIO_1_LO , pp );
5474
5553
5475
5554
enter_new_state (S , state_0_disconnected , __func__ , __LINE__ );
5555
+ dl_connection_terminated (S );
5476
5556
}
5477
5557
else {
5478
5558
SET_RC (S -> rc + 1 );
0 commit comments