@@ -1265,6 +1265,15 @@ void dl_data_request (dlq_item_t *E)
12651265 dw_printf ("\") state=%d\n" , S -> state );
12661266 }
12671267
1268+ // JWL - I think we want to discard if in disconnected state.
1269+ // App could contine sending data after a disconnection.
1270+
1271+ if (S -> state == state_0_disconnected ) {
1272+ cdata_delete (E -> txdata );
1273+ E -> txdata = NULL ;
1274+ return ;
1275+ }
1276+
12681277 if (E -> txdata -> len <= S -> n1_paclen ) {
12691278 data_request_good_size (S , E -> txdata );
12701279 E -> txdata = NULL ; // Now part of transmit I frame queue.
@@ -5078,9 +5087,9 @@ static void ui_frame (ax25_dlsm_t *S, cmdres_t cr, int pf)
50785087static void xid_frame (ax25_dlsm_t * S , cmdres_t cr , int pf , unsigned char * info_ptr , int info_len )
50795088{
50805089 struct xid_param_s param ;
5081- char desc [150 ];
5090+ char desc [256 ];
50825091 int ok ;
5083- unsigned char xinfo [40 ];
5092+ unsigned char xinfo [80 ]; // about twice max possible size
50845093 int xlen ;
50855094 cmdres_t res = cr_res ;
50865095 int f = 1 ;
@@ -5546,7 +5555,7 @@ static void tm201_expiry (ax25_dlsm_t *S)
55465555{
55475556
55485557 struct xid_param_s param ;
5549- unsigned char xinfo [40 ];
5558+ unsigned char xinfo [80 ]; // about twice max possible size
55505559 int xlen ;
55515560 cmdres_t cmd = cr_cmd ;
55525561 int p = 1 ;
@@ -6603,8 +6612,8 @@ static void enter_new_state (ax25_dlsm_t *S, enum dlsm_state_e new_state, const
66036612static void mdl_negotiate_request (ax25_dlsm_t * S )
66046613{
66056614 struct xid_param_s param ;
6606- unsigned char xinfo [40 ];
6607- int xlen ;
6615+ unsigned char xinfo [80 ]; // about twice max possible size
6616+ int xlen ;
66086617 cmdres_t cmd = cr_cmd ;
66096618 int p = 1 ;
66106619 int nopid = 0 ;
@@ -6661,6 +6670,7 @@ static void mdl_negotiate_request (ax25_dlsm_t *S)
66616670static void initiate_negotiation (ax25_dlsm_t * S , struct xid_param_s * param )
66626671{
66636672 param -> full_duplex = 0 ;
6673+
66646674 switch (S -> srej_enable ) {
66656675 case srej_single :
66666676 case srej_multi :
@@ -6673,20 +6683,66 @@ static void initiate_negotiation (ax25_dlsm_t *S, struct xid_param_s *param)
66736683 }
66746684
66756685 param -> modulo = S -> modulo ;
6676- param -> i_field_length_rx = S -> n1_paclen ; // Hmmmm. Should we ask for what the user
6677- // specified for PACLEN or offer the maximum
6678- // that we can handle, AX25_N1_PACLEN_MAX?
6679- param -> window_size_rx = S -> k_maxframe ;
6680- param -> ack_timer = (int )(g_misc_config_p -> frack * 1000 );
6681- param -> retries = S -> n2_retry ;
6686+
6687+ /*
6688+ * I‑Field Length TX
6689+ * This is the maximum I‑frame payload size that I will transmit.
6690+ * The XID command tells the peer:
6691+ * "The largest I‑frame I will send to you is N bytes."
6692+ * This is about my outbound frame size.
6693+ *
6694+ * Note that the response could be smaller so we'd have
6695+ * to reduce working paclen.
6696+ */
6697+ param -> i_field_length_tx = S -> n1_paclen ; // PACLEN from configuration file.
6698+
6699+ /*
6700+ * I‑Field Length RX
6701+ * This is the maximum I‑frame payload size that I am capable of receiving.
6702+ * The XID command tells the peer:
6703+ * "The largest I‑frame I can handle from you is N bytes."
6704+ * This is about my inbound frame size.
6705+ */
6706+ param -> i_field_length_rx = AX25_N1_PACLEN_MAX ;
6707+
6708+ /*
6709+ * window_size_tx
6710+ * This is the size of the transmit window that I will use when sending I‑frames.
6711+ * - The XID command tells the peer:
6712+ * "I will send up to N unacknowledged frames at a time."
6713+ * - It defines my outbound pipeline depth.
6714+ * - Larger TX window = I can send more before waiting for RR/RNR/ACK.
6715+ * This initially comes from the configuration file EMAXFRAME but
6716+ * can be scaled back by the XID exchange if the other side doesn't
6717+ * have enough buffer space. Also known as "k".
6718+ */
6719+ param -> window_size_tx = S -> k_maxframe ;
6720+
6721+ /*
6722+ * window_size_rx
6723+ * This is the size of the receive window that I can accept from the peer.
6724+ * - The XID command tells the peer:
6725+ * "You may send me up to N unacknowledged frames before I must ACK."
6726+ * - It defines my inbound buffering capability.
6727+ * - Larger RX window = the peer can send more before needing my RR.
6728+ * I would offer AX25_K_MAXFRAME_EXTENDED_MAX (63) because I don't have memory
6729+ * constraints. I really don't care what the peer has to say about this.
6730+ * I generate an ack, of some sort, at the end of the incoming
6731+ * transmission, i.e. when DCD drops.
6732+ */
6733+ param -> window_size_rx = AX25_K_MAXFRAME_EXTENDED_MAX ;
6734+
6735+ param -> ack_timer = (int )(g_misc_config_p -> frack * 1000 ); // "T1" in milliseconds
6736+
6737+ param -> retries = S -> n2_retry ; // "N1"
66826738}
66836739
66846740
66856741/*------------------------------------------------------------------------------
66866742 *
66876743 * Name: negotiation_response
66886744 *
6689- * Purpose: Used when receiving the XID command and preparing the XID response.
6745+ * Purpose: Used when receiving the XID * command* and preparing the XID response.
66906746 *
66916747 * Description: Take what other station has asked for and reduce if we have lesser capabilities.
66926748 * For example if other end wants 8k information part we reduce it to 2k.
@@ -6711,9 +6767,11 @@ static void negotiation_response (ax25_dlsm_t *S, struct xid_param_s *param)
67116767
67126768// Other end might want 8.
67136769// Seems unlikely. If it implements XID it should have modulo 128.
6770+ // It would be REALLY BAD if we started out with 128, started exchanging
6771+ // I Frames, then the XID exchange wanted to change it to 8.
67146772
67156773 if (param -> modulo == modulo_unknown ) {
6716- param -> modulo = 8 ; // Not specified. Set default.
6774+ param -> modulo = 128 ; // Not specified. Set default.
67176775 }
67186776 else {
67196777 param -> modulo = MIN (param -> modulo , 128 );
@@ -6727,29 +6785,54 @@ static void negotiation_response (ax25_dlsm_t *S, struct xid_param_s *param)
67276785 param -> srej = (param -> modulo == 128 ) ? srej_single : srej_none ; // not specified, set default
67286786 }
67296787
6730- // We can currently do up to 2k.
6788+ // i_field_length_TX is what other station wants for it's outgoing paclen.
6789+ // We can currently handle up to 2k.
67316790// Take minimum of that and what other guy asks for.
67326791
6792+ if (param -> i_field_length_tx == G_UNKNOWN ) {
6793+ param -> i_field_length_tx = AX25_N1_PACLEN_DEFAULT ; // Not specified, take default.
6794+ }
6795+ else {
6796+ param -> i_field_length_tx = MIN (param -> i_field_length_tx , AX25_N1_PACLEN_MAX );
6797+ }
6798+
6799+ // i_field_length_RX is what other station is capable of receiving.
6800+ // Take minimum of our desired paclen and capability other station to receive.
6801+
67336802 if (param -> i_field_length_rx == G_UNKNOWN ) {
6734- param -> i_field_length_rx = 256 ; // Not specified, take default.
6803+ param -> i_field_length_rx = AX25_N1_PACLEN_DEFAULT ; // Not specified, take default.
67356804 }
67366805 else {
6737- param -> i_field_length_rx = MIN (param -> i_field_length_rx , AX25_N1_PACLEN_MAX );
6806+ param -> i_field_length_rx = MIN (param -> i_field_length_rx , S -> n1_paclen );
67386807 }
67396808
6740- // In theory extended mode can have window size of 127 but
6809+ // window_size_TX is what the other end has requested.
6810+ // In theory extended mode can have window size of 127 (for REJ) but
67416811// I'm limiting it to 63 for the reason mentioned in the SREJ logic.
67426812
6743- if (param -> window_size_rx == G_UNKNOWN ) {
6744- param -> window_size_rx = (param -> modulo == 128 ) ? 32 : 4 ; // not specified, set default.
6813+ if (param -> window_size_tx == G_UNKNOWN ) {
6814+ param -> window_size_tx = (param -> modulo == 128 ) ?
6815+ AX25_K_MAXFRAME_EXTENDED_DEFAULT : AX25_K_MAXFRAME_BASIC_DEFAULT ; // not specified, set default.
67456816 }
67466817 else {
67476818 if (param -> modulo == 128 )
6748- param -> window_size_rx = MIN (param -> window_size_rx , AX25_K_MAXFRAME_EXTENDED_MAX );
6819+ param -> window_size_tx = MIN (param -> window_size_tx , AX25_K_MAXFRAME_EXTENDED_MAX );
67496820 else
6750- param -> window_size_rx = MIN (param -> window_size_rx , AX25_K_MAXFRAME_BASIC_MAX );
6821+ param -> window_size_tx = MIN (param -> window_size_tx , AX25_K_MAXFRAME_BASIC_MAX );
67516822 }
67526823
6824+ // window_size_RX is what the other end is capable of.
6825+ // We should not exceed that for our outgoing I frames.
6826+
6827+ if (param -> window_size_rx == G_UNKNOWN ) {
6828+ param -> window_size_rx = (param -> modulo == 128 ) ?
6829+ AX25_K_MAXFRAME_EXTENDED_DEFAULT : AX25_K_MAXFRAME_BASIC_DEFAULT ; // not specified, assume default.
6830+ }
6831+ else {
6832+ param -> window_size_rx = MIN (param -> window_size_rx , S -> k_maxframe );
6833+ }
6834+
6835+
67536836// Erratum: Unclear. Is the Acknowledgement Timer before or after compensating for digipeaters
67546837// in the path? e.g. Typically TNCs use the FRACK parameter for this and it often defaults to 3.
67556838// However, the actual timeout value might be something like FRACK*(2*m+1) where m is the number of
@@ -6801,14 +6884,46 @@ static void complete_negotiation (ax25_dlsm_t *S, struct xid_param_s *param)
68016884 S -> modulo = param -> modulo ;
68026885 }
68036886
6887+ // i_field_length_TX is from viewpoint of other station.
6888+ // Do anything with this?
6889+
6890+ //if (param->i_field_length_tx != G_UNKNOWN) {
6891+ // ...
6892+ //}
6893+
6894+ // i_field_length_RX is from viewpoint of other station.
6895+ // We might need to reduce our paclen value if other station has lower limit.
6896+
68046897 if (param -> i_field_length_rx != G_UNKNOWN ) {
6805- S -> n1_paclen = param -> i_field_length_rx ;
6898+ if (S -> n1_paclen > param -> i_field_length_rx ) {
6899+ text_color_set (DW_COLOR_INFO );
6900+ dw_printf ("Reducing our PACLEN from %d to %d as result of XID exchange.\n" ,
6901+ S -> n1_paclen , param -> i_field_length_rx );
6902+ S -> n1_paclen = param -> i_field_length_rx ;
6903+ }
68066904 }
68076905
6906+ // window_size_TX from view point of other station. What it wants to send.
6907+ // Do anything with this?
6908+
6909+ //if (param->window_size_tx != G_UNKNOWN) {
6910+ // ...
6911+ //}
6912+
6913+ // window_size_RX from view point of other station.
6914+ // We might need to reduce our maxframe value if other station has lower limit.
6915+
68086916 if (param -> window_size_rx != G_UNKNOWN ) {
6809- S -> k_maxframe = param -> window_size_rx ;
6917+ if (S -> k_maxframe > param -> window_size_rx ) {
6918+ text_color_set (DW_COLOR_INFO );
6919+ dw_printf ("Reducing our EMAXFRAME from %d to %d as result of XID exchange.\n" ,
6920+ S -> k_maxframe , param -> window_size_rx );
6921+ S -> k_maxframe = param -> window_size_rx ;
6922+ }
68106923 }
68116924
6925+ // FIXME: revisit this.
6926+
68126927 if (param -> ack_timer != G_UNKNOWN ) {
68136928 S -> t1v = param -> ack_timer * 0.001 ;
68146929 }
@@ -6952,6 +7067,14 @@ static void resume_t1 (ax25_dlsm_t *S, const char *from_func, int from_line)
69527067 text_color_set (DW_COLOR_DEBUG );
69537068 dw_printf ("Resumed T1 after pausing for %.3f sec, %.3f still remaining, [now=%.3f]\n" , paused_for_sec , S -> t1_exp - now , now - S -> start_time );
69547069 }
7070+
7071+ // Did it expire already?
7072+ if (S -> t1_exp <= now ) {
7073+ S -> t1_exp = 0 ;
7074+ S -> t1_paused_at = 0 ;
7075+ S -> t1_had_expired = 1 ;
7076+ t1_expiry (S );
7077+ }
69557078 }
69567079
69577080} /* end resume_t1 */
0 commit comments