1 //
2 // This file is part of Dire Wolf, an amateur radio packet TNC.
3 //
4 // Copyright (C) 2016, 2017, 2018 John Langner, WB2OSZ
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 //
19
20
21 /*------------------------------------------------------------------
22 *
23 * Name: ax25_link
24 *
25 * Purpose: Data Link State Machine.
26 * Establish connections and transfer data in the proper
27 * order with retries.
28 *
29 * Description:
30 *
31 * Typical sequence for establishing a connection
32 * initiated by a client application. Try version 2.2,
33 * get refused, and fall back to trying version 2.0.
34 *
35 *
36 * State Client App State Machine Peer
37 * ----- ---------- ------------- ----
38 *
39 * 0 disc
40 * Conn. Req --->
41 * SABME --->
42 * 5 await 2.2
43 * <--- FRMR or DM *note
44 * SABM --->
45 * 1 await 2.0
46 * <--- UA
47 * <--- CONN Ind.
48 * 3 conn
49 *
50 *
51 * Typical sequence when other end initiates connection.
52 *
53 *
54 * State Client App State Machine Peer
55 * ----- ---------- ------------- ----
56 *
57 * 0 disc
58 * <--- SABME or SABM
59 * UA --->
60 * <--- CONN Ind.
61 * 3 conn
62 *
63 *
64 * *note:
65 *
66 * After carefully studying the v2.2 spec, I expected a 2.0 implementation to send
67 * FRMR in response to SABME. This is important. If a v2.2 implementation
68 * gets FRMR, in response to SABME, it switches to v2.0 and sends SABM instead.
69 *
70 * The v2.0 protocol spec, section 2.3.4.3.3.1, states that FRMR should be sent when
71 * an invalid or not implemented command is received. That all fits together.
72 *
73 * In testing, I found that the KPC-3+ sent DM.
74 *
75 * I can see where they might get that idea.
76 * The v2.0 spec says that when in disconnected mode, it should respond to any
77 * command other than SABM or UI frame with a DM response with P/F set to 1.
78 * I think it was implemented wrong. 2.3.4.3.3.1 should take precedence.
79 *
80 * The TM-D710 does absolutely nothing in response to SABME.
81 * Not responding at all is just plain wrong. To work around this, I put
82 * in a special hack to start sending SABM after a certain number of
83 * SABME go unanswered. There is more discussion in the User Guide.
84 *
85 * References:
86 * * AX.25 Amateur Packet-Radio Link-Layer Protocol Version 2.0, October 1984
87 *
88 * https://www.tapr.org/pub_ax25.html
89 * http://lea.hamradio.si/~s53mv/nbp/nbp/AX25V20.pdf
90 *
91 * At first glance, they look pretty much the same, but the second one
92 * is more complete with 4 appendices, including a state table.
93 *
94 * * AX.25 Link Access Protocol for Amateur Packet Radio Version 2.2 Revision: July 1998
95 *
96 * https://www.tapr.org/pdf/AX25.2.2.pdf
97 *
98 * * AX.25 Link Access Protocol for Amateur Packet Radio Version 2.2 Revision: July 1998
99 *
100 * http://www.ax25.net/AX25.2.2-Jul%2098-2.pdf
101 *
102 * I accidentally stumbled across this one when searching for some sort of errata
103 * list for the original protocol specification.
104 *
105 * "This is a new version of the 1998 standard. It has had all figures
106 * redone using Microsoft Visio. Errors in the SDL have been corrected."
107 *
108 * The SDL diagrams are dated 2006. I wish I had known about this version, with
109 * several corrections, before doing most of the implementation. :-(
110 *
111 * The title page still says July 1998 so it's not immediately obvious this
112 * is different than the one on the TAPR site.
113 *
114 * * AX.25 ... Latest revision, in progress.
115 *
116 * http://www.nj7p.org/
117 *
118 * This is currently being revised in cooperation with software authors
119 * who have noticed some issues during implementation.
120 *
121 * The functions here are based on the SDL diagrams but turned inside out.
122 * It seems more intuitive to have a function for each type of input and then decide
123 * what to do depending on the state. This also reduces duplicate code because we
124 * often see the same flow chart segments, for the same input, appearing in multiple states.
125 *
126 * Errata: The protocol spec has many places that appear to be errors or are ambiguous so I wasn't
127 * sure what to do. These should be annotated with "erratum" comments so we can easily go
128 * back and revisit them.
129 *
130 * X.25: The AX.25 protocol is based on, but does not necessarily adhere to, the X.25 protocol.
131 * Consulting this might provide some insights where the AX.25 spec is not clear.
132 *
133 * http://www.itu.int/rec/T-REC-X.25-199610-I/en/
134 *
135 * Version 1.4, released April 2017:
136 *
137 * Features tested reasonably well:
138 *
139 * Connect to/from a KPC-3+ and send I frames in both directions.
140 * Same with TM-D710A.
141 * v2.2 connect between two instances of direwolf. (Can't find another v2.2 for testing.)
142 * Modulo 8 & 128 sequence numbers.
143 * Recovery from simulated transmission errors using either REJ or SREJ.
144 * XID frame for parameter negotiation.
145 * Segments to allow data larger than max info part size.
146 *
147 * Implemented but not tested properly:
148 *
149 * Connecting thru digipeater(s).
150 * Acting as a digipeater.
151 * T3 timer.
152 * Compatibility with additional types of TNC.
153 *
154 * Version 1.5, December 2017:
155 *
156 * Implemented Multi Selective Reject.
157 * More efficient generation of SREJ frames.
158 * Reduced number of duplicate I frames sent for both REJ and SREJ cases.
159 * Avoided unnecessary RR when I frame could take care of the ack.
160 * (This led to issue 132 where outgoing data sometimes got stuck in the queue.)
161 *
162 *------------------------------------------------------------------*/
163
164 #include "direwolf.h"
165
166
167 #include <stdlib.h>
168 #include <string.h>
169 #include <assert.h>
170 #include <stdio.h>
171 #include <ctype.h>
172 #include <math.h>
173
174
175 #include "ax25_pad.h"
176 #include "ax25_pad2.h"
177 #include "xid.h"
178 #include "textcolor.h"
179 #include "dlq.h"
180 #include "tq.h"
181 #include "ax25_link.h"
182 #include "dtime_now.h"
183 #include "server.h"
184 #include "ptt.h"
185
186
187 #define MIN(a,b) ((a)<(b)?(a):(b))
188 #define MAX(a,b) ((a)>(b)?(a):(b))
189
190 // Debug switches for different types of information.
191 // Should have command line options instead of changing source and recompiling.
192
193 static int s_debug_protocol_errors = 1; // Less serious Protocol errors.
194 // Useful for debugging but unnecessarily alarming other times.
195
196 static int s_debug_client_app = 0; // Interaction with client application.
197 // dl_connect_request, dl_data_request, dl_data_indication, etc.
198
199 static int s_debug_radio = 0; // Received frames and channel busy status.
200 // lm_data_indication, lm_channel_busy
201 static int s_debug_variables = 0; // Variables, state changes.
202
203 static int s_debug_retry = 0; // Related to lost I frames, REJ, SREJ, timeout, resending.
204
205 static int s_debug_timers = 0; // Timer details.
206
207 static int s_debug_link_handle = 0; // Create data link state machine or pick existing one,
208 // based on my address, peer address, client app index, and radio channel.
209
210 static int s_debug_stats = 0; // Statistics when connection is closed.
211
212 static int s_debug_misc = 0; // Anything left over that might be interesting.
213
214
215 /*
216 * AX.25 data link state machine.
217 *
218 * One instance for each link identified by
219 * [ client, channel, owncall, peercall ]
220 */
221
222 enum dlsm_state_e {
223 state_0_disconnected = 0,
224 state_1_awaiting_connection = 1,
225 state_2_awaiting_release = 2,
226 state_3_connected = 3,
227 state_4_timer_recovery = 4,
228 state_5_awaiting_v22_connection = 5 };
229
230
231 typedef struct ax25_dlsm_s {
232
233 int magic1; // Look out for bad pointer or corruption.
234 #define MAGIC1 0x11592201
235
236 struct ax25_dlsm_s *next; // Next in linked list.
237
238 int stream_id; // Unique number for each stream.
239 // Internally we use a pointer but this is more user-friendly.
240
241 int chan; // Radio channel being used.
242
243 int client; // We have have multiple client applications,
244 // each with their own links. We need to know
245 // which client should receive the data or
246 // notifications about state changes.
247
248
249 char addrs[AX25_MAX_REPEATERS][AX25_MAX_ADDR_LEN];
250 // Up to 10 addresses, same order as in frame.
251
252 int num_addr; // Number of addresses. Should be in range 2 .. 10.
253
254 #define OWNCALL AX25_SOURCE
255 // addrs[OWNCALL] is owncall for this end of link.
256 // Note that we are acting on behalf of
257 // a client application so the APRS mycall
258 // might not be relevent.
259
260 #define PEERCALL AX25_DESTINATION
261 // addrs[PEERCALL] is call for other end.
262
263
264 double start_time; // Clock time when this was allocated. Used only for
265 // debug output for timestamps relative to start.
266
267 enum dlsm_state_e state; // Current state.
268
269 int modulo; // 8 or 128.
270 // Determines whether we have one or two control
271 // octets. 128 allows a much larger window size.
272
273 enum srej_e srej_enable; // Is other end capable of processing SREJ? (Am I allowed to send it?)
274 // Starts out as 'srej_none' for v2.0 or 'srej_single' for v2.2.
275 // Can be changed to 'srej_multi' with XID exchange.
276 // Should be used only with modulo 128. (Is this enforced?)
277
278 int n1_paclen; // Maximum length of information field, in bytes.
279 // Starts out as 256 but can be negotiated higher.
280 // (Protocol Spec has this in bits. It is in bytes here.)
281 // "PACLEN" in configuration file.
282
283 int n2_retry; // Maximum number of retries permitted.
284 // Typically 10.
285 // "RETRY" parameter in configuration file.
286
287
288 int k_maxframe; // Window size. Defaults to 4 (mod 8) or 32 (mod 128).
289 // Maximum number of unacknowledged information
290 // frames that can be outstanding.
291 // "MAXFRAME" or "EMAXFRAME" parameter in configuration file.
292
293 int rc; // Retry count. Give up after n2.
294
295 int vs; // 4.2.4.1. Send State Variable V(S)
296 // The send state variable exists within the TNC and is never sent.
297 // It contains the next sequential number to be assigned to the next
298 // transmitted I frame.
299 // This variable is updated with the transmission of each I frame.
300
301 int va; // 4.2.4.5. Acknowledge State Variable V(A)
302 // The acknowledge state variable exists within the TNC and is never sent.
303 // It contains the sequence number of the last frame acknowledged by
304 // its peer [V(A)-1 equals the N(S) of the last acknowledged I frame].
305
306 int vr; // 4.2.4.3. Receive State Variable V(R)
307 // The receive state variable exists within the TNC.
308 // It contains the sequence number of the next expected received I frame
309 // This variable is updated upon the reception of an error-free I frame
310 // whose send sequence number equals the present received state variable value.
311
312 int layer_3_initiated; // SABM(E) was sent by request of Layer 3; i.e. DL-CONNECT request primitive.
313 // I think this means that it is set only if we initiated the connection.
314 // It would not be set if we are in the middle of accepting a connection from the other station.
315
316 // Next 5 are called exception conditions.
317
318 int peer_receiver_busy; // Remote station is busy and can't receive I frames.
319
320 int reject_exception; // A REJ frame has been sent to the remote station. (boolean)
321
322 // This is used only when receving an I frame, in states 3 & 4, SREJ not enabled.
323 // When an I frame has an unepected N(S),
324 // - if not already set, set it and send REJ.
325 // When an I frame with expected N(S) is received, clear it.
326 // This would prevent us from sending additional REJ while
327 // waiting for result from first one.
328 // What happens if the REJ gets lost? Is it resent somehow?
329
330 int own_receiver_busy; // Layer 3 is busy and can't receive I frames.
331 // We have no API to convey this information so it should always be 0.
332
333 int acknowledge_pending; // I frames have been successfully received but not yet
334 // acknowledged TO the remote station.
335 // Set when receiving the next expected I frame and P=0.
336 // This gets cleared by sending any I, RR, RNR, REJ.
337 // Cleared when sending SREJ with F=1.
338
339 // Timing.
340
341 float srt; // Smoothed roundtrip time in seconds.
342 // This is used to dynamically adjust t1v.
343 // Sometimes the flow chart has SAT instead of SRT.
344 // I think that is a typographical error.
345
346 float t1v; // How long to wait for an acknowlegement before resending.
347 // Value used when starting timer T1, in seconds.
348 // "FRACK" parameter in some implementations.
349 // Typically it might be 3 seconds after frame has been
350 // sent. Add more for each digipeater in path.
351 // Here it is dynamically adjusted.
352
353 // Set initial value for T1V.
354 // Multiply FRACK by 2*m+1, where m is number of digipeaters.
355
356 #define INIT_T1V_SRT \
357 S->t1v = g_misc_config_p->frack * (2 * (S->num_addr - 2) + 1); \
358 S->srt = S->t1v / 2.0;
359
360
361 int radio_channel_busy; // Either due to DCD or PTT.
362
363
364 // Timer T1.
365
366 // Timer values all use the usual unix time() value but double precision
367 // so we can have fractions of seconds.
368
369 // T1 is used for retries along with the retry counter, "rc."
370 // When timer T1 is started, the value is obtained from t1v plus the current time.
371
372
373 // Appropriate functions should be used rather than accessing the values directly.
374
375
376
377 // This gets a little tricky because we need to pause the timers when the radio
378 // channel is busy. Suppose we sent an I frame and set T1 to 4 seconds so we could
379 // take corrective action if there is no response in a reasonable amount of time.
380 // What if some other station has the channel tied up for 10 seconds? We don't want
381 // T1 to timeout and start a retry sequence. The solution is to pause the timers while
382 // the channel is busy. We don't want to get a timer expiry event when t1_exp is in
383 // the past if it is currently paused. When it is un-paused, the expiration time is adjusted
384 // for the amount of time it was paused.
385
386
387 double t1_exp; // This is the time when T1 will expire or 0 if not running.
388
389 double t1_paused_at; // Time when it was paused or 0 if not paused.
390
391 float t1_remaining_when_last_stopped; // Number of seconds that were left on T1 when it was stopped.
392 // This is used to fine tune t1v.
393 // Set to negative initially to mean invalid, don't use in calculation.
394
395 int t1_had_expired; // Set when T1 expires.
396 // Cleared for start & stop.
397
398
399 // Timer T3.
400
401 // T3 is used to terminate connection after extended inactivity.
402
403
404 // Similar to T1 except there is not mechanism to capture the remaining time when it is stopped
405 // and it is not paused when the channel is busy.
406
407
408 double t3_exp; // When it expires or 0 if not running.
409
410 #define T3_DEFAULT 300.0 // Copied 5 minutes from Ax.25 for Linux.
411 // http://www.linux-ax25.org/wiki/Run_time_configurable_parameters
412 // D710A also defaults to 30*10 = 300 seconds.
413 // Should it be user-configurable?
414 // KPC-3+ and TM-D710A have "CHECK" command for this purpose.
415
416 // Statistics for testing purposes.
417
418 // Count how many frames of each type we received.
419 // This is easy to do because they all come in thru lm_data_indication.
420 // Counting outgoing could probably be done in lm_data_request so
421 // it would not have to be scattered all over the place. TBD
422
423 int count_recv_frame_type[frame_not_AX25+1];
424
425 int peak_rc_value; // Peak value of retry count (rc).
426
427
428 // For sending data.
429
430 cdata_t *i_frame_queue; // Connected data from client which has not been transmitted yet.
431 // Linked list.
432 // The name is misleading because these are just blocks of
433 // data, not "I frames" at this point. The name comes from
434 // the protocol specification.
435
436 cdata_t *txdata_by_ns[128]; // Data which has already been transmitted.
437 // Indexed by N(S) in case it gets lost and needs to be sent again.
438 // Cleared out when we get ACK for it.
439
440 int magic3; // Look out for out of bounds for above.
441 #define MAGIC3 0x03331301
442
443 cdata_t *rxdata_by_ns[128]; // "Receive buffer"
444 // Data which has been received out of sequence.
445 // Indexed by N(S).
446
447 int magic2; // Look out for out of bounds for above.
448 #define MAGIC2 0x02221201
449
450
451
452 // "Management Data Link" (MDL) state machine for XID exchange.
453
454
455 enum mdl_state_e { mdl_state_0_ready=0, mdl_state_1_negotiating=1 } mdl_state;
456
457 int mdl_rc; // Retry count, waiting to get XID response.
458 // The spec has provision for a separate maximum, NM201, but we
459 // just use the regular N2 same as other retries.
460
461 double tm201_exp; // Timer. Similar to T1.
462 // The spec mentions a separate timeout value but
463 // we will just use the same as T1.
464
465 double tm201_paused_at; // Time when it was paused or 0 if not paused.
466
467 // Segment reassembler.
468
469 cdata_t *ra_buff; // Reassembler buffer. NULL when in ready state.
470
471 int ra_following; // Most recent number following to predict next expected.
472
473
474 } ax25_dlsm_t;
475
476
477 /*
478 * List of current state machines for each link.
479 * There is potential many client apps, each with multiple links
480 * connected all at the same time.
481 *
482 * Everything coming thru here should be from a single thread.
483 * The Data Link Queue should serialize all processing.
484 * Therefore, we don't have to worry about critical regions.
485 */
486
487 static ax25_dlsm_t *list_head = NULL;
488
489
490 /*
491 * Registered callsigns for incoming connections.
492 */
493
494 #define RC_MAGIC 0x08291951
495
496 typedef struct reg_callsign_s {
497 char callsign[AX25_MAX_ADDR_LEN];
498 int chan;
499 int client;
500 struct reg_callsign_s *next;
501 int magic;
502 } reg_callsign_t;
503
504 static reg_callsign_t *reg_callsign_list = NULL;
505
506
507 // Use these, rather than setting variables directly, to make debug out easier.
508
509 #define SET_VS(n) { S->vs = (n); \
510 if (s_debug_variables) { \
511 text_color_set(DW_COLOR_DEBUG); \
512 dw_printf ("V(S) = %d at %s %d\n", S->vs, __func__, __LINE__); \
513 } \
514 assert (S->vs >= 0 && S->vs < S->modulo); \
515 }
516
517 // If other guy acks reception of an I frame, we should never get an REJ or SREJ
518 // asking for it again. When we update V(A), we should be able to remove the saved
519 // transmitted data, and everything preceding it, from S->txdata_by_ns[].
520
521 #define SET_VA(n) { S->va = (n); \
522 if (s_debug_variables) { \
523 text_color_set(DW_COLOR_DEBUG); \
524 dw_printf ("V(A) = %d at %s %d\n", S->va, __func__, __LINE__); \
525 } \
526 assert (S->va >= 0 && S->va < S->modulo); \
527 int x = AX25MODULO(n-1, S->modulo, __FILE__, __func__, __LINE__); \
528 while (S->txdata_by_ns[x] != NULL) { \
529 cdata_delete (S->txdata_by_ns[x]); \
530 S->txdata_by_ns[x] = NULL; \
531 x = AX25MODULO(x-1, S->modulo, __FILE__, __func__, __LINE__); \
532 } \
533 }
534
535 #define SET_VR(n) { S->vr = (n); \
536 if (s_debug_variables) { \
537 text_color_set(DW_COLOR_DEBUG); \
538 dw_printf ("V(R) = %d at %s %d\n", S->vr, __func__, __LINE__); \
539 } \
540 assert (S->vr >= 0 && S->vr < S->modulo); \
541 }
542
543 #define SET_RC(n) { S->rc = (n); \
544 if (s_debug_variables) { \
545 text_color_set(DW_COLOR_DEBUG); \
546 dw_printf ("rc = %d at %s %d, state = %d\n", S->rc, __func__, __LINE__, S->state); \
547 } \
548 }
549
550
551 //TODO: Make this a macro so we can simplify calls yet keep debug output if something goes wrong.
552
553 #if 0
554 #define AX25MODULO(n) ax25modulo((n), S->modulo, __FILE__, __func__, __LINE__)
555 static int ax25modulo(int n, int m, const char *file, const char *func, int line)
556 #else
AX25MODULO(int n,int m,const char * file,const char * func,int line)557 static int AX25MODULO(int n, int m, const char *file, const char *func, int line)
558 #endif
559 {
560 if (m != 8 && m != 128) {
561 text_color_set(DW_COLOR_ERROR);
562 dw_printf ("INTERNAL ERROR: %d modulo %d, %s, %s, %d\n", n, m, file, func, line);
563 m = 8;
564 }
565 // Use masking, rather than % operator, so negative numbers are handled properly.
566 return (n & (m-1));
567 }
568
569
570 // Test whether we can send more or if we need to wait
571 // because we have reached 'maxframe' outstanding frames.
572 // Argument must be 'S'.
573
574 #define WITHIN_WINDOW_SIZE(x) (x->vs != AX25MODULO(x->va + x->k_maxframe, x->modulo, __FILE__, __func__, __LINE__))
575
576
577 // Timer macros to provide debug output with location from where they are called.
578
579 #define START_T1 start_t1(S, __func__, __LINE__)
580 #define IS_T1_RUNNING is_t1_running(S, __func__, __LINE__)
581 #define STOP_T1 stop_t1(S, __func__, __LINE__)
582 #define PAUSE_T1 pause_t1(S, __func__, __LINE__)
583 #define RESUME_T1 resume_t1(S, __func__, __LINE__)
584
585 #define START_T3 start_t3(S, __func__, __LINE__)
586 #define STOP_T3 stop_t3(S, __func__, __LINE__)
587
588 #define START_TM201 start_tm201(S, __func__, __LINE__)
589 #define STOP_TM201 stop_tm201(S, __func__, __LINE__)
590 #define PAUSE_TM201 pause_tm201(S, __func__, __LINE__)
591 #define RESUME_TM201 resume_tm201(S, __func__, __LINE__)
592
593
594 static void dl_data_indication (ax25_dlsm_t *S, int pid, char *data, int len);
595
596 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);
597 static void i_frame_continued (ax25_dlsm_t *S, int p, int ns, int pid, char *info_ptr, int info_len);
598 static int is_ns_in_window (ax25_dlsm_t *S, int ns);
599 static void send_srej_frames (ax25_dlsm_t *S, int *resend, int count, int allow_f1);
600 static void rr_rnr_frame (ax25_dlsm_t *S, int ready, cmdres_t cr, int pf, int nr);
601 static void rej_frame (ax25_dlsm_t *S, cmdres_t cr, int pf, int nr);
602 static void srej_frame (ax25_dlsm_t *S, cmdres_t cr, int pf, int nr, unsigned char *info_ptr, int info_len);
603
604 static void sabm_e_frame (ax25_dlsm_t *S, int extended, int p);
605 static void disc_frame (ax25_dlsm_t *S, int f);
606 static void dm_frame (ax25_dlsm_t *S, int f);
607 static void ua_frame (ax25_dlsm_t *S, int f);
608 static void frmr_frame (ax25_dlsm_t *S);
609 static void ui_frame (ax25_dlsm_t *S, cmdres_t cr, int pf);
610 static void xid_frame (ax25_dlsm_t *S, cmdres_t cr, int pf, unsigned char *info_ptr, int info_len);
611 static void test_frame (ax25_dlsm_t *S, cmdres_t cr, int pf, unsigned char *info_ptr, int info_len);
612
613 static void t1_expiry (ax25_dlsm_t *S);
614 static void t3_expiry (ax25_dlsm_t *S);
615 static void tm201_expiry (ax25_dlsm_t *S);
616
617 static void nr_error_recovery (ax25_dlsm_t *S);
618 static void clear_exception_conditions (ax25_dlsm_t *S);
619 static void transmit_enquiry (ax25_dlsm_t *S);
620 static void select_t1_value (ax25_dlsm_t *S);
621 static void establish_data_link (ax25_dlsm_t *S);
622 static void set_version_2_0 (ax25_dlsm_t *S);
623 static void set_version_2_2 (ax25_dlsm_t *S);
624 static int is_good_nr (ax25_dlsm_t *S, int nr);
625 static void i_frame_pop_off_queue (ax25_dlsm_t *S);
626 static void discard_i_queue (ax25_dlsm_t *S);
627 static void invoke_retransmission (ax25_dlsm_t *S, int nr_input);
628 static void check_i_frame_ackd (ax25_dlsm_t *S, int nr);
629 static void check_need_for_response (ax25_dlsm_t *S, ax25_frame_type_t frame_type, cmdres_t cr, int pf);
630 static void enquiry_response (ax25_dlsm_t *S, ax25_frame_type_t frame_type, int f);
631
632 static void enter_new_state(ax25_dlsm_t *S, enum dlsm_state_e new_state, const char *from_func, int from_line);
633
634 static void mdl_negotiate_request (ax25_dlsm_t *S);
635 static void initiate_negotiation (ax25_dlsm_t *S, struct xid_param_s *param);
636 static void negotiation_response (ax25_dlsm_t *S, struct xid_param_s *param);
637 static void complete_negotiation (ax25_dlsm_t *S, struct xid_param_s *param);
638
639
640 // Use macros above rather than calling these directly.
641
642 static void start_t1 (ax25_dlsm_t *S, const char *from_func, int from_line);
643 static void stop_t1 (ax25_dlsm_t *S, const char *from_func, int from_line);
644 static int is_t1_running (ax25_dlsm_t *S, const char *from_func, int from_line);
645 static void pause_t1 (ax25_dlsm_t *S, const char *from_func, int from_line);
646 static void resume_t1 (ax25_dlsm_t *S, const char *from_func, int from_line);
647
648 static void start_t3 (ax25_dlsm_t *S, const char *from_func, int from_line);
649 static void stop_t3 (ax25_dlsm_t *S, const char *from_func, int from_line);
650
651 static void start_tm201 (ax25_dlsm_t *S, const char *from_func, int from_line);
652 static void stop_tm201 (ax25_dlsm_t *S, const char *from_func, int from_line);
653 static void pause_tm201 (ax25_dlsm_t *S, const char *from_func, int from_line);
654 static void resume_tm201 (ax25_dlsm_t *S, const char *from_func, int from_line);
655
656
657
658 /*
659 * Configuration settings from file or command line.
660 */
661
662 static struct misc_config_s *g_misc_config_p;
663
664
665 /*-------------------------------------------------------------------
666 *
667 * Name: ax25_link_init
668 *
669 * Purpose: Initialize the ax25_link module.
670 *
671 * Inputs: pconfig - misc. configuration from config file or command line.
672 * Beacon stuff ended up here.
673 *
674 * Outputs: Remember required information for future use. That's all.
675 *
676 *--------------------------------------------------------------------*/
677
ax25_link_init(struct misc_config_s * pconfig)678 void ax25_link_init (struct misc_config_s *pconfig)
679 {
680
681 /*
682 * Save parameters for later use.
683 */
684 g_misc_config_p = pconfig;
685
686 } /* end ax25_link_init */
687
688
689
690
691 /*------------------------------------------------------------------------------
692 *
693 * Name: get_link_handle
694 *
695 * Purpose: Find existing (or possibly create) state machine for a given link.
696 * It should be possible to have a large number of links active at the
697 * same time. They are uniquely identified by
698 * (owncall, peercall, client id, radio channel)
699 * Note that we could have multiple client applications, all sharing one
700 * TNC, on the same or different radio channels, completely unware of each other.
701 *
702 * Inputs: addrs - Owncall, peercall, and optional digipeaters.
703 * For ease of passing this around, it is an array in the
704 * same order as in the frame.
705 *
706 * num_addr - Number of addresses, 2 thru 10.
707 *
708 * chan - Radio channel number.
709 *
710 * client - Client app number.
711 * We allow multiple concurrent applications with the
712 * AGW network protocol. These are identified as 0, 1, ...
713 * We don't know this for an incoming frame from the radio
714 * so it is -1 at this point. At a later time will will
715 * associate the stream with the right client.
716 *
717 * create - True if OK to create a new one.
718 * Otherwise, return only one already existing.
719 *
720 * This should always be true for outgoing frames.
721 * For incoming frames this would be true only for SABM(e)
722 * with all digipeater fields marked as used.
723 *
724 * Here, we will also check to see if it is in our
725 * registered callsign list.
726 *
727 * Returns: Handle for data link state machine.
728 * NULL if not found and 'create' is false.
729 *
730 * Description: Try to find an existing entry matching owncall, peercall, channel,
731 * and client. If not found create a new one.
732 *
733 *------------------------------------------------------------------------------*/
734
735 static int next_stream_id = 0;
736
get_link_handle(char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN],int num_addr,int chan,int client,int create)737 static ax25_dlsm_t *get_link_handle (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, int chan, int client, int create)
738 {
739
740 ax25_dlsm_t *p;
741
742
743 if (s_debug_link_handle) {
744 text_color_set(DW_COLOR_DECODED);
745 dw_printf ("get_link_handle (%s>%s, chan=%d, client=%d, create=%d)\n",
746 addrs[AX25_SOURCE], addrs[AX25_DESTINATION], chan, client, create);
747 }
748
749
750 // Look for existing.
751
752 if (client == -1) { // from the radio.
753 // address order is reversed for compare.
754 for (p = list_head; p != NULL; p = p->next) {
755
756 if (p->chan == chan &&
757 strcmp(addrs[AX25_DESTINATION], p->addrs[OWNCALL]) == 0 &&
758 strcmp(addrs[AX25_SOURCE], p->addrs[PEERCALL]) == 0) {
759
760 if (s_debug_link_handle) {
761 text_color_set(DW_COLOR_DECODED);
762 dw_printf ("get_link_handle returns existing stream id %d for incoming.\n", p->stream_id);
763 }
764 return (p);
765 }
766 }
767 }
768 else { // from client app
769 for (p = list_head; p != NULL; p = p->next) {
770
771 if (p->chan == chan &&
772 p->client == client &&
773 strcmp(addrs[AX25_SOURCE], p->addrs[OWNCALL]) == 0 &&
774 strcmp(addrs[AX25_DESTINATION], p->addrs[PEERCALL]) == 0) {
775
776 if (s_debug_link_handle) {
777 text_color_set(DW_COLOR_DECODED);
778 dw_printf ("get_link_handle returns existing stream id %d for outgoing.\n", p->stream_id);
779 }
780 return (p);
781 }
782 }
783 }
784
785
786 // Could not find existing. Should we create a new one?
787
788 if ( ! create) {
789 if (s_debug_link_handle) {
790 text_color_set(DW_COLOR_DECODED);
791 dw_printf ("get_link_handle: Search failed. Do not create new.\n");
792 }
793 return (NULL);
794 }
795
796
797 // If it came from the radio, search for destination our registered callsign list.
798
799 int incoming_for_client = -1; // which client app registered the callsign?
800
801
802 if (client == -1) { // from the radio.
803
804 reg_callsign_t *r, *found;
805
806 found = NULL;
807 for (r = reg_callsign_list; r != NULL && found == NULL; r = r->next) {
808
809 if (strcmp(addrs[AX25_DESTINATION], r->callsign) == 0 && chan == r->chan) {
810 found = r;
811 incoming_for_client = r->client;
812 }
813 }
814
815 if (found == NULL) {
816 if (s_debug_link_handle) {
817 text_color_set(DW_COLOR_DECODED);
818 dw_printf ("get_link_handle: not for me. Ignore it.\n");
819 }
820 return (NULL);
821 }
822 }
823
824 // Create new data link state machine.
825
826 p = calloc (sizeof(ax25_dlsm_t), 1);
827 p->magic1 = MAGIC1;
828 p->start_time = dtime_now();
829 p->stream_id = next_stream_id++;
830 p->modulo = 8;
831
832 p->chan = chan;
833 p->num_addr = num_addr;
834
835 // If it came in over the radio, we need to swap source/destination and reverse any digi path.
836
837 if (incoming_for_client >= 0) {
838 strlcpy (p->addrs[AX25_SOURCE], addrs[AX25_DESTINATION], sizeof(p->addrs[AX25_SOURCE]));
839 strlcpy (p->addrs[AX25_DESTINATION], addrs[AX25_SOURCE], sizeof(p->addrs[AX25_DESTINATION]));
840
841 int j = AX25_REPEATER_1;
842 int k = num_addr - 1;
843 while (k >= AX25_REPEATER_1) {
844 strlcpy (p->addrs[j], addrs[k], sizeof(p->addrs[j]));
845 j++;
846 k--;
847 }
848
849 p->client = incoming_for_client;
850 }
851 else {
852 memcpy (p->addrs, addrs, sizeof(p->addrs));
853 p->client = client;
854 }
855
856 p->state = state_0_disconnected;
857 p->t1_remaining_when_last_stopped = -999; // Invalid, don't use.
858
859 p->magic2 = MAGIC2;
860 p->magic3 = MAGIC3;
861
862 // No need for critical region because this should all be in one thread.
863 p->next = list_head;
864 list_head = p;
865
866 if (s_debug_link_handle) {
867 text_color_set(DW_COLOR_DECODED);
868 dw_printf ("get_link_handle returns NEW stream id %d\n", p->stream_id);
869 }
870
871 return (p);
872 }
873
874
875
876
877
878
879 //###################################################################################
880 //###################################################################################
881 //
882 // Data Link state machine for sending data in connected mode.
883 //
884 // Incoming:
885 //
886 // Requests from the client application. Set s_debug_client_app for debugging.
887 //
888 // dl_connect_request
889 // dl_disconnect_request
890 // dl_outstanding_frames_request - (mine) Ask about outgoing queue for a link.
891 // dl_data_request - send connected data
892 // dl_unit_data_request - not implemented. APRS & KISS bypass this
893 // dl_flow_off - not implemented. Not in AGW API.
894 // dl_flow_on - not implemented. Not in AGW API.
895 // dl_register_callsign - Register callsigns(s) for incoming connection requests.
896 // dl_unregister_callsign - Unregister callsigns(s) ...
897 // dl_client_cleanup - Clean up after client which has disappeared.
898 //
899 // Stuff from the radio channel. Set s_debug_radio for debugging.
900 //
901 // lm_data_indication - Received frame.
902 // lm_channel_busy - Change in PTT or DCD.
903 // lm_seize_confirm - We have started to transmit.
904 //
905 // Timer expiration. Set s_debug_timers for debugging.
906 //
907 // dl_timer_expiry
908 //
909 // Outgoing:
910 //
911 // To the client application:
912 //
913 // dl_data_indication - received connected data.
914 //
915 // To the transmitter:
916 //
917 // lm_data_request - Queue up a frame for transmission.
918 //
919 // lm_seize_request - Start transmitter when possible.
920 // lm_seize_confirm will be called when it has.
921 //
922 //
923 // It is important that all requests come thru the data link queue so
924 // everything is serialized.
925 // We don't have to worry about being reentrant or critical regions.
926 // Nothing here should consume a significant amount of time.
927 // i.e. There should be no sleep delay or anything that would block waiting on someone else.
928 //
929 //###################################################################################
930 //###################################################################################
931
932
933
934 /*------------------------------------------------------------------------------
935 *
936 * Name: dl_connect_request
937 *
938 * Purpose: Client app wants to connect to another station.
939 *
940 * Inputs: E - Event from the queue.
941 * The caller will free it.
942 *
943 * Description:
944 *
945 *------------------------------------------------------------------------------*/
946
dl_connect_request(dlq_item_t * E)947 void dl_connect_request (dlq_item_t *E)
948 {
949 ax25_dlsm_t *S;
950 int ok_to_create = 1;
951 int old_version;
952 int n;
953
954 if (s_debug_client_app) {
955 text_color_set(DW_COLOR_DEBUG);
956 dw_printf ("dl_connect_request ()\n");
957 }
958
959 text_color_set(DW_COLOR_INFO);
960 dw_printf ("Attempting connect to %s ...\n", E->addrs[PEERCALL]);
961
962 S = get_link_handle (E->addrs, E->num_addr, E->chan, E->client, ok_to_create);
963
964 switch (S->state) {
965
966 case state_0_disconnected:
967
968 INIT_T1V_SRT;
969
970 // See if destination station is in list for v2.0 only.
971
972 old_version = 0;
973 for (n = 0; n < g_misc_config_p->v20_count && ! old_version; n++) {
974 if (strcmp(E->addrs[AX25_DESTINATION],g_misc_config_p->v20_addrs[n]) == 0) {
975 old_version = 1;
976 }
977 }
978
979 if (old_version || g_misc_config_p->maxv22 == 0) { // Don't attempt v2.2.
980
981 set_version_2_0 (S);
982
983 establish_data_link (S);
984 S->layer_3_initiated = 1;
985 enter_new_state (S, state_1_awaiting_connection, __func__, __LINE__);
986 }
987 else { // Try v2.2 first, then fall back if appropriate.
988
989 set_version_2_2 (S);
990
991 establish_data_link (S);
992 S->layer_3_initiated = 1;
993 enter_new_state (S, state_5_awaiting_v22_connection, __func__, __LINE__);
994 }
995 break;
996
997 case state_1_awaiting_connection:
998 case state_5_awaiting_v22_connection:
999
1000 discard_i_queue(S);
1001 S->layer_3_initiated = 1;
1002 // Keep current state.
1003 break;
1004
1005 case state_2_awaiting_release:
1006
1007 // Keep current state.
1008 break;
1009
1010 case state_3_connected:
1011 case state_4_timer_recovery:
1012
1013 discard_i_queue(S);
1014 establish_data_link(S);
1015 S->layer_3_initiated = 1;
1016 // My enhancement. Original always sent SABM and went to state 1.
1017 // If we were using v2.2, why not reestablish with that?
1018 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
1019 break;
1020 }
1021
1022 } /* end dl_connect_request */
1023
1024
1025 /*------------------------------------------------------------------------------
1026 *
1027 * Name: dl_disconnect_request
1028 *
1029 * Purpose: Client app wants to terminate connection with another station.
1030 *
1031 * Inputs: E - Event from the queue.
1032 * The caller will free it.
1033 *
1034 * Outputs:
1035 *
1036 * Description:
1037 *
1038 *------------------------------------------------------------------------------*/
1039
dl_disconnect_request(dlq_item_t * E)1040 void dl_disconnect_request (dlq_item_t *E)
1041 {
1042 ax25_dlsm_t *S;
1043 int ok_to_create = 1;
1044
1045
1046 if (s_debug_client_app) {
1047 text_color_set(DW_COLOR_DEBUG);
1048 dw_printf ("dl_disconnect_request ()\n");
1049 }
1050
1051 text_color_set(DW_COLOR_INFO);
1052 dw_printf ("Disconnect from %s ...\n", E->addrs[PEERCALL]);
1053
1054 S = get_link_handle (E->addrs, E->num_addr, E->chan, E->client, ok_to_create);
1055
1056 switch (S->state) {
1057
1058 case state_0_disconnected:
1059
1060 // DL-DISCONNECT *confirm*
1061 text_color_set(DW_COLOR_INFO);
1062 dw_printf ("Stream %d: Disconnected from %s.\n", S->stream_id, S->addrs[PEERCALL]);
1063 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 0);
1064 break;
1065
1066 case state_1_awaiting_connection:
1067 case state_5_awaiting_v22_connection:
1068
1069 // TODO: "requeue." Not sure what to do here.
1070 // If we put it back in the queue we will get it back again probably still in same state.
1071 // Need a way to defer it until the next state change.
1072
1073 break;
1074
1075 case state_2_awaiting_release:
1076 {
1077 // We have previously started the disconnect sequence and are waiting
1078 // for a UA from the other guy. Meanwhile, the application got
1079 // impatient and sent us another disconnect request. What should
1080 // we do? Ignore it and let the disconnect sequence run its
1081 // course? Or should we complete the sequence without waiting
1082 // for the other guy to ack?
1083
1084 // Erratum. Flow chart simply says "DM (expedited)."
1085 // This is the only place we have expedited. Is this correct?
1086
1087 cmdres_t cr = cr_res; // DM can only be response.
1088 int p = 0;
1089 int nopid = 0; // PID applies only to I and UI frames.
1090
1091 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, cr, frame_type_U_DM, p, nopid, NULL, 0);
1092 lm_data_request (S->chan, TQ_PRIO_0_HI, pp); // HI means expedited.
1093
1094 // Erratum: Shouldn't we inform the user when going to disconnected state?
1095 // Notifying the application, here, is my own enhancement.
1096
1097 text_color_set(DW_COLOR_INFO);
1098 dw_printf ("Stream %d: Disconnected from %s.\n", S->stream_id, S->addrs[PEERCALL]);
1099 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 0);
1100
1101 STOP_T1;
1102 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
1103 }
1104 break;
1105
1106 case state_3_connected:
1107 case state_4_timer_recovery:
1108
1109 discard_i_queue (S);
1110 SET_RC(0); // I think this should be 1 but I'm not that worried about it.
1111
1112 cmdres_t cmd = cr_cmd;
1113 int p = 1;
1114 int nopid = 0;
1115
1116 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, cmd, frame_type_U_DISC, p, nopid, NULL, 0);
1117 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
1118
1119 STOP_T3;
1120 START_T1;
1121 enter_new_state (S, state_2_awaiting_release, __func__, __LINE__);
1122
1123 break;
1124 }
1125
1126 } /* end dl_disconnect_request */
1127
1128
1129 /*------------------------------------------------------------------------------
1130 *
1131 * Name: dl_data_request
1132 *
1133 * Purpose: Client app wants to send data to another station.
1134 *
1135 * Inputs: E - Event from the queue.
1136 * The caller will free it.
1137 *
1138 * Description: Append the transmit data block to the I frame queue for later processing.
1139 *
1140 * We also perform the segmentation handling here.
1141 *
1142 * C6.1 Segmenter State Machine
1143 * Only the following DL primitives will be candidates for modification by the segmented
1144 * state machine:
1145
1146 * * DL-DATA Request. The user employs this primitive to provide information to be
1147 * transmitted using connection-oriented procedures; i.e., using I frames. The
1148 * segmenter state machine examines the quantity of data to be transmitted. If the
1149 * quantity of data to be transmitted is less than or equal to the data link parameter
1150 * N1, the segmenter state machine passes the primitive through transparently. If the
1151 * quantity of data to be transmitted exceeds the data link parameter N1, the
1152 * segmenter chops up the data into segments of length N1-2 octets. Each segment is
1153 * prepended with a two octet header. (See Figures 3.1 and 3.2.) The segments are
1154 * then turned over to the Data-link State Machine for transmission, using multiple DL
1155 * Data Request primitives. All segments are turned over immediately; therefore the
1156 * Data-link State Machine will transmit them consecutively on the data link.
1157 *
1158 * Erratum: Not sure how to interpret that. See example below for how it was implemented.
1159 *
1160 * Version 1.6: Bug 252. Segmentation was occuring for a V2.0 link. From the spec:
1161 * "The receipt of an XID response from the other station establishes that both
1162 * stations are using AX.25 version 2.2 or higher and enables the use of the
1163 * segmenter/reassembler and selective reject."
1164 * "The segmenter/reassembler procedure is only enabled if both stations on the
1165 * link are using AX.25 version 2.2 or higher."
1166 *
1167 * The Segmenter Ready State SDL has no decision based on protocol version.
1168 *
1169 *------------------------------------------------------------------------------*/
1170
1171 static void data_request_good_size (ax25_dlsm_t *S, cdata_t *txdata);
1172
1173
dl_data_request(dlq_item_t * E)1174 void dl_data_request (dlq_item_t *E)
1175 {
1176 ax25_dlsm_t *S;
1177 int ok_to_create = 1;
1178
1179
1180 S = get_link_handle (E->addrs, E->num_addr, E->chan, E->client, ok_to_create);
1181
1182 if (s_debug_client_app) {
1183 text_color_set(DW_COLOR_DEBUG);
1184 dw_printf ("dl_data_request (\"");
1185 ax25_safe_print (E->txdata->data, E->txdata->len, 1);
1186 dw_printf ("\") state=%d\n", S->state);
1187 }
1188
1189 if (E->txdata->len <= S->n1_paclen) {
1190 data_request_good_size (S, E->txdata);
1191 E->txdata = NULL; // Now part of transmit I frame queue.
1192 return;
1193 }
1194
1195 #define DIVROUNDUP(a,b) (((a)+(b)-1) / (b))
1196
1197 // Erratum: Don't do V2.2 segmentation for a V2.0 link.
1198 // In this case, we can just split it into multiple frames not exceeding the specified max size.
1199 // Hopefully the receiving end treats it like a stream and doesn't care about length of each frame.
1200
1201 if (S->modulo == 8) {
1202
1203 int num_frames = 0;
1204 int remaining_len = E->txdata->len;
1205 int offset = 0;
1206
1207 while (remaining_len > 0) {
1208 int this_len = MIN(remaining_len, S->n1_paclen);
1209
1210 cdata_t *new_txdata = cdata_new(E->txdata->pid, E->txdata->data + offset, this_len);
1211 data_request_good_size (S, new_txdata);
1212
1213 offset += this_len;
1214 remaining_len -= this_len;
1215 num_frames++;
1216 }
1217
1218 if (num_frames != DIVROUNDUP(E->txdata->len, S->n1_paclen) || remaining_len != 0) {
1219 text_color_set(DW_COLOR_ERROR);
1220 dw_printf ("INTERNAL ERROR, Segmentation line %d, data length = %d, N1 = %d, num frames = %d, remaining len = %d\n",
1221 __LINE__, E->txdata->len, S->n1_paclen, num_frames, remaining_len);
1222 }
1223 cdata_delete (E->txdata);
1224 E->txdata = NULL;
1225 return;
1226 }
1227
1228 // More interesting case.
1229 // It is too large to fit in one frame so we segment it.
1230
1231 // As an example, suppose we had 6 bytes of data "ABCDEF".
1232
1233 // If N1 >= 6, it would be sent normally.
1234
1235 // (addresses)
1236 // (control bytes)
1237 // PID, typically 0xF0
1238 // 'A' - first byte of information field
1239 // 'B'
1240 // 'C'
1241 // 'D'
1242 // 'E'
1243 // 'F'
1244
1245 // Now consider the case where it would not fit.
1246 // We would change the PID to 0x08 meaning a segment.
1247 // The information part is the segment identifier of this format:
1248 //
1249 // x xxxxxxx
1250 // | ---+---
1251 // | |
1252 // | +- Number of additional segments to follow.
1253 // |
1254 // +- '1' means it is the first segment.
1255
1256 // If N1 = 4, it would be split up like this:
1257
1258 // (addresses)
1259 // (control bytes)
1260 // PID = 0x08 means segment
1261 // 0x82 - Start of info field.
1262 // MSB set indicates FIRST segment.
1263 // 2, in lower 7 bits, means 2 more segments to follow.
1264 // 0xF0 - original PID, typical value.
1265 // 'A' - For the FIRST segment, we have PID and N1-2 data bytes.
1266 // 'B'
1267
1268 // (addresses)
1269 // (control bytes)
1270 // PID = 0x08 means segment
1271 // 0x01 - Means 1 more segment follows.
1272 // 'C' - For subsequent (not first) segments, we have up to N1-1 data bytes.
1273 // 'D'
1274 // 'E'
1275
1276 // (addresses)
1277 // (control bytes)
1278 // PID = 0x08
1279 // 0x00 - 0 means no more to follow. i.e. This is the last.
1280 // 'E'
1281
1282
1283 // Number of segments is ceiling( (datalen + 1 ) / (N1 - 1))
1284
1285 // we add one to datalen for the original PID.
1286 // We subtract one from N1 for the segment identifier header.
1287
1288 #define DIVROUNDUP(a,b) (((a)+(b)-1) / (b))
1289
1290 // Compute number of segments.
1291 // We will decrement this before putting it in the frame so the first
1292 // will have one less than this number.
1293
1294 int nseg_to_follow = DIVROUNDUP(E->txdata->len + 1, S->n1_paclen - 1);
1295
1296 if (nseg_to_follow < 2 || nseg_to_follow > 128) {
1297 text_color_set(DW_COLOR_ERROR);
1298 dw_printf ("INTERNAL ERROR, Segmentation line %d, data length = %d, N1 = %d, number of segments = %d\n",
1299 __LINE__, E->txdata->len, S->n1_paclen, nseg_to_follow);
1300 cdata_delete (E->txdata);
1301 E->txdata = NULL;
1302 return;
1303 }
1304
1305 int orig_offset = 0;
1306 int remaining_len = E->txdata->len;
1307
1308 // First segment.
1309
1310 int seglen;
1311 struct {
1312 char header; // 0x80 + number of segments to follow.
1313 char original_pid;
1314 char segdata[AX25_N1_PACLEN_MAX];
1315 } first_segment;
1316 cdata_t *new_txdata;
1317
1318 nseg_to_follow--;
1319
1320 first_segment.header = 0x80 | nseg_to_follow;
1321 first_segment.original_pid = E->txdata->pid;
1322 seglen = MIN(S->n1_paclen - 2, remaining_len);
1323
1324 if (seglen < 1 || seglen > S->n1_paclen - 2 || seglen > remaining_len || seglen > (int)(sizeof(first_segment.segdata))) {
1325 text_color_set(DW_COLOR_ERROR);
1326 dw_printf ("INTERNAL ERROR, Segmentation line %d, data length = %d, N1 = %d, segment length = %d, number to follow = %d\n",
1327 __LINE__, E->txdata->len, S->n1_paclen, seglen, nseg_to_follow);
1328 cdata_delete (E->txdata);
1329 E->txdata = NULL;
1330 return;
1331 }
1332
1333 memcpy (first_segment.segdata, E->txdata->data + orig_offset, seglen);
1334
1335 new_txdata = cdata_new(AX25_PID_SEGMENTATION_FRAGMENT, (char*)(&first_segment), seglen+2);
1336
1337 data_request_good_size (S, new_txdata);
1338
1339 orig_offset += seglen;
1340 remaining_len -= seglen;
1341
1342
1343 // Subsequent segments.
1344
1345 do {
1346 struct {
1347 char header; // Number of segments to follow.
1348 char segdata[AX25_N1_PACLEN_MAX];
1349 } subsequent_segment;
1350
1351 nseg_to_follow--;
1352
1353 subsequent_segment.header = nseg_to_follow;
1354 seglen = MIN(S->n1_paclen - 1, remaining_len);
1355
1356 if (seglen < 1 || seglen > S->n1_paclen - 1 || seglen > remaining_len || seglen > (int)(sizeof(subsequent_segment.segdata))) {
1357 text_color_set(DW_COLOR_ERROR);
1358 dw_printf ("INTERNAL ERROR, Segmentation line %d, data length = %d, N1 = %d, segment length = %d, number to follow = %d\n",
1359 __LINE__, E->txdata->len, S->n1_paclen, seglen, nseg_to_follow);
1360 cdata_delete (E->txdata);
1361 E->txdata = NULL;
1362 return;
1363 }
1364
1365 memcpy (subsequent_segment.segdata, E->txdata->data + orig_offset, seglen);
1366
1367 new_txdata = cdata_new(AX25_PID_SEGMENTATION_FRAGMENT, (char*)(&subsequent_segment), seglen+1);
1368
1369 data_request_good_size (S, new_txdata);
1370
1371 orig_offset += seglen;
1372 remaining_len -= seglen;
1373
1374 } while (nseg_to_follow > 0);
1375
1376 if (remaining_len != 0 || orig_offset != E->txdata->len) {
1377 text_color_set(DW_COLOR_ERROR);
1378 dw_printf ("INTERNAL ERROR, Segmentation line %d, data length = %d, N1 = %d, remaining length = %d (not 0), orig offset = %d (not %d)\n",
1379 __LINE__, E->txdata->len, S->n1_paclen, remaining_len, orig_offset, E->txdata->len);
1380 }
1381
1382 cdata_delete (E->txdata);
1383 E->txdata = NULL;
1384
1385 } /* end dl_data_request */
1386
1387
data_request_good_size(ax25_dlsm_t * S,cdata_t * txdata)1388 static void data_request_good_size (ax25_dlsm_t *S, cdata_t *txdata)
1389 {
1390 switch (S->state) {
1391
1392 case state_0_disconnected:
1393 case state_2_awaiting_release:
1394 /*
1395 * Discard it.
1396 */
1397 cdata_delete (txdata);
1398 break;
1399
1400 case state_1_awaiting_connection:
1401 case state_5_awaiting_v22_connection:
1402 /*
1403 * Erratum?
1404 * The flow chart shows "push on I frame queue" if layer 3 initiated
1405 * is NOT set. This seems backwards but I don't understand enough yet
1406 * to make a compelling argument that it is wrong.
1407 * Implemented as in flow chart.
1408 * TODO: Get better understanding of what'layer_3_initiated' means.
1409 */
1410 if (S->layer_3_initiated) {
1411 cdata_delete (txdata);
1412 break;
1413 }
1414 // otherwise fall thru.
1415
1416 case state_3_connected:
1417 case state_4_timer_recovery:
1418 /*
1419 * "push on I frame queue"
1420 * Append to the end would have been a better description because push implies a stack.
1421 */
1422
1423 if (S->i_frame_queue == NULL) {
1424 txdata->next = NULL;
1425 S->i_frame_queue = txdata;
1426 }
1427 else {
1428 cdata_t *plast = S->i_frame_queue;
1429 while (plast->next != NULL) {
1430 plast = plast->next;
1431 }
1432 txdata->next = NULL;
1433 plast->next = txdata;
1434 }
1435 break;
1436 }
1437
1438 // v1.5 change in strategy.
1439 // New I frames, not sent yet, are delayed until after processing anything in the received transmission.
1440 // Give the transmit process a kick unless other side is busy or we have reached our window size.
1441 // Previously we had i_frame_pop_off_queue here which would start sending new stuff before we
1442 // finished dealing with stuff already in progress.
1443
1444 switch (S->state) {
1445
1446 case state_3_connected:
1447 case state_4_timer_recovery:
1448
1449 if ( ( ! S->peer_receiver_busy ) &&
1450 WITHIN_WINDOW_SIZE(S) ) {
1451 S->acknowledge_pending = 1;
1452 lm_seize_request (S->chan);
1453 }
1454 break;
1455
1456 default:
1457 break;
1458 }
1459
1460 } /* end data_request_good_size */
1461
1462
1463 /*------------------------------------------------------------------------------
1464 *
1465 * Name: dl_register_callsign
1466 * dl_unregister_callsign
1467 *
1468 * Purpose: Register / Unregister callsigns that we will accept connections for.
1469 *
1470 * Inputs: E - Event from the queue.
1471 * The caller will free it.
1472 *
1473 * Outputs: New item is pushed on the head of the reg_callsign_list.
1474 * We don't bother checking for duplicates so the most recent wins.
1475 *
1476 * Description: The data link state machine does not use MYCALL from the APRS configuration.
1477 * For outgoing frames, the client supplies the source callsign.
1478 * For incoming connection requests, we need to know what address(es) to respond to.
1479 *
1480 * Note that one client application can register multiple callsigns for
1481 * multiple channels.
1482 * Different clients can register different different addresses on the same channel.
1483 *
1484 *------------------------------------------------------------------------------*/
1485
dl_register_callsign(dlq_item_t * E)1486 void dl_register_callsign (dlq_item_t *E)
1487 {
1488 reg_callsign_t *r;
1489
1490 if (s_debug_client_app) {
1491 text_color_set(DW_COLOR_DEBUG);
1492 dw_printf ("dl_register_callsign (%s, chan=%d, client=%d)\n", E->addrs[0], E->chan, E->client);
1493 }
1494
1495 r = calloc(sizeof(reg_callsign_t),1);
1496 strlcpy (r->callsign, E->addrs[0], sizeof(r->callsign));
1497 r->chan = E->chan;
1498 r->client = E->client;
1499 r->next = reg_callsign_list;
1500 r->magic = RC_MAGIC;
1501
1502 reg_callsign_list = r;
1503
1504 } /* end dl_register_callsign */
1505
1506
dl_unregister_callsign(dlq_item_t * E)1507 void dl_unregister_callsign (dlq_item_t *E)
1508 {
1509 reg_callsign_t *r, *prev;
1510
1511 if (s_debug_client_app) {
1512 text_color_set(DW_COLOR_DEBUG);
1513 dw_printf ("dl_unregister_callsign (%s, chan=%d, client=%d)\n", E->addrs[0], E->chan, E->client);
1514 }
1515
1516 prev = NULL;
1517 r = reg_callsign_list;
1518 while (r != NULL) {
1519
1520 assert (r->magic == RC_MAGIC);
1521
1522 if (strcmp(r->callsign,E->addrs[0]) == 0 && r->chan == E->chan && r->client == E->client) {
1523
1524 if (r == reg_callsign_list) {
1525
1526 reg_callsign_list = r->next;
1527 memset (r, 0, sizeof(reg_callsign_t));
1528 free (r);
1529 r = reg_callsign_list;
1530 }
1531 else {
1532
1533 prev->next = r->next;
1534 memset (r, 0, sizeof(reg_callsign_t));
1535 free (r);
1536 r = prev->next;
1537 }
1538 }
1539 else {
1540 prev = r;
1541 r = r->next;
1542 }
1543 }
1544
1545 } /* end dl_unregister_callsign */
1546
1547
1548
1549 /*------------------------------------------------------------------------------
1550 *
1551 * Name: dl_outstanding_frames_request
1552 *
1553 * Purpose: Client app wants to know how many frames are still on their way
1554 * to other station. This is handy for flow control. We would like
1555 * to keep the pipeline filled sufficiently to take advantage of a
1556 * large window size (MAXFRAMES). It is also good to know that the
1557 * the last packet sent was actually received before we commence
1558 * the disconnect.
1559 *
1560 * Inputs: E - Event from the queue.
1561 * The caller will free it.
1562 *
1563 * Outputs: This gets back to the AGW server which sends the 'Y' reply.
1564 *
1565 * Description: This is the sum of:
1566 * - Incoming connected data, from application still in the queue.
1567 * - I frames which have been transmitted but not yet acknowleged.
1568 *
1569 *------------------------------------------------------------------------------*/
1570
dl_outstanding_frames_request(dlq_item_t * E)1571 void dl_outstanding_frames_request (dlq_item_t *E)
1572 {
1573 ax25_dlsm_t *S;
1574 int ok_to_create = 0; // must exist already.
1575
1576
1577 if (s_debug_client_app) {
1578 text_color_set(DW_COLOR_DEBUG);
1579 dw_printf ("dl_outstanding_frames_request ( to %s )\n", E->addrs[PEERCALL]);
1580 }
1581
1582 S = get_link_handle (E->addrs, E->num_addr, E->chan, E->client, ok_to_create);
1583
1584 if (S == NULL) {
1585 text_color_set(DW_COLOR_ERROR);
1586 dw_printf ("Can't get outstanding frames for %s -> %s, chan %d\n", E->addrs[OWNCALL], E->addrs[PEERCALL], E->chan);
1587 server_outstanding_frames_reply (E->chan, E->client, E->addrs[OWNCALL], E->addrs[PEERCALL], 0);
1588 return;
1589 }
1590
1591 // Add up these
1592 //
1593 // cdata_t *i_frame_queue; // Connected data from client which has not been transmitted yet.
1594 // // Linked list.
1595 // // The name is misleading because these are just blocks of
1596 // // data, not "I frames" at this point. The name comes from
1597 // // the protocol specification.
1598 //
1599 // cdata_t *txdata_by_ns[128]; // Data which has already been transmitted.
1600 // // Indexed by N(S) in case it gets lost and needs to be sent again.
1601 // // Cleared out when we get ACK for it.
1602
1603 int count1 = 0;
1604 cdata_t *incoming;
1605 for (incoming = S->i_frame_queue; incoming != NULL; incoming = incoming->next) {
1606 count1++;
1607 }
1608
1609 int count2 = 0;
1610 int k;
1611 for (k = 0; k < S->modulo; k++) {
1612 if (S->txdata_by_ns[k] != NULL) {
1613 count2++;
1614 }
1615 }
1616
1617 server_outstanding_frames_reply (S->chan, S->client, S->addrs[OWNCALL], S->addrs[PEERCALL], count1 + count2);
1618
1619 } // end dl_outstanding_frames_request
1620
1621
1622
1623 /*------------------------------------------------------------------------------
1624 *
1625 * Name: dl_client_cleanup
1626 *
1627 * Purpose: Client app has gone away. Clean up any data associated with it.
1628 *
1629 * Inputs: E - Event from the queue.
1630 * The caller will free it.
1631 *
1632
1633 * Description: By client application we mean something that attached with the
1634 * AGW network protocol.
1635 *
1636 * Clean out anything related to the specfied client application.
1637 * This would include state machines and registered callsigns.
1638 *
1639 *------------------------------------------------------------------------------*/
1640
dl_client_cleanup(dlq_item_t * E)1641 void dl_client_cleanup (dlq_item_t *E)
1642 {
1643 ax25_dlsm_t *S;
1644 ax25_dlsm_t *dlprev;
1645 reg_callsign_t *r, *rcprev;
1646
1647
1648 if (s_debug_client_app) {
1649 text_color_set(DW_COLOR_INFO);
1650 dw_printf ("dl_client_cleanup (%d)\n", E->client);
1651 }
1652
1653
1654 dlprev = NULL;
1655 S = list_head;
1656 while (S != NULL) {
1657
1658 // Look for corruption or double freeing.
1659
1660 assert (S->magic1 == MAGIC1);
1661 assert (S->magic2 == MAGIC2);
1662 assert (S->magic3 == MAGIC3);
1663
1664 if (S->client == E->client ) {
1665
1666 int n;
1667
1668 if (s_debug_stats) {
1669 text_color_set(DW_COLOR_INFO);
1670 dw_printf ("%d I frames received\n", S->count_recv_frame_type[frame_type_I]);
1671
1672 dw_printf ("%d RR frames received\n", S->count_recv_frame_type[frame_type_S_RR]);
1673 dw_printf ("%d RNR frames received\n", S->count_recv_frame_type[frame_type_S_RNR]);
1674 dw_printf ("%d REJ frames received\n", S->count_recv_frame_type[frame_type_S_REJ]);
1675 dw_printf ("%d SREJ frames received\n", S->count_recv_frame_type[frame_type_S_SREJ]);
1676
1677 dw_printf ("%d SABME frames received\n", S->count_recv_frame_type[frame_type_U_SABME]);
1678 dw_printf ("%d SABM frames received\n", S->count_recv_frame_type[frame_type_U_SABM]);
1679 dw_printf ("%d DISC frames received\n", S->count_recv_frame_type[frame_type_U_DISC]);
1680 dw_printf ("%d DM frames received\n", S->count_recv_frame_type[frame_type_U_DM]);
1681 dw_printf ("%d UA frames received\n", S->count_recv_frame_type[frame_type_U_UA]);
1682 dw_printf ("%d FRMR frames received\n", S->count_recv_frame_type[frame_type_U_FRMR]);
1683 dw_printf ("%d UI frames received\n", S->count_recv_frame_type[frame_type_U_UI]);
1684 dw_printf ("%d XID frames received\n", S->count_recv_frame_type[frame_type_U_XID]);
1685 dw_printf ("%d TEST frames received\n", S->count_recv_frame_type[frame_type_U_TEST]);
1686
1687 dw_printf ("%d peak retry count\n", S->peak_rc_value);
1688 }
1689
1690 if (s_debug_client_app) {
1691 text_color_set(DW_COLOR_DEBUG);
1692 dw_printf ("dl_client_cleanup: remove %s>%s\n", S->addrs[AX25_SOURCE], S->addrs[AX25_DESTINATION]);
1693 }
1694
1695 discard_i_queue (S);
1696
1697 for (n = 0; n < 128; n++) {
1698 if (S->txdata_by_ns[n] != NULL) {
1699 cdata_delete (S->txdata_by_ns[n]);
1700 S->txdata_by_ns[n] = NULL;
1701 }
1702 }
1703
1704 for (n = 0; n < 128; n++) {
1705 if (S->rxdata_by_ns[n] != NULL) {
1706 cdata_delete (S->rxdata_by_ns[n]);
1707 S->rxdata_by_ns[n] = NULL;
1708 }
1709 }
1710
1711 if (S->ra_buff != NULL) {
1712 cdata_delete (S->ra_buff);
1713 S->ra_buff = NULL;
1714 }
1715
1716 // Put into disconnected state.
1717 // If "connected" indicator (e.g. LED) was on, this will turn it off.
1718
1719 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
1720
1721 // Take S out of list.
1722
1723 S->magic1 = 0;
1724 S->magic2 = 0;
1725 S->magic3 = 0;
1726
1727 if (S == list_head) { // first one on list.
1728
1729 list_head = S->next;
1730 free (S);
1731 S = list_head;
1732 }
1733 else { // not the first one.
1734 dlprev->next = S->next;
1735 free (S);
1736 S = dlprev->next;
1737 }
1738 }
1739 else {
1740 dlprev = S;
1741 S = S->next;
1742 }
1743 }
1744
1745 /*
1746 * If there are no link state machines (streams) remaining, there should be no txdata items still allocated.
1747 */
1748 if (list_head == NULL) {
1749 cdata_check_leak();
1750 }
1751
1752 /*
1753 * Remove registered callsigns for this client.
1754 */
1755
1756 rcprev = NULL;
1757 r = reg_callsign_list;
1758 while (r != NULL) {
1759
1760 assert (r->magic == RC_MAGIC);
1761
1762 if (r->client == E->client) {
1763
1764 if (r == reg_callsign_list) {
1765
1766 reg_callsign_list = r->next;
1767 memset (r, 0, sizeof(reg_callsign_t));
1768 free (r);
1769 r = reg_callsign_list;
1770 }
1771 else {
1772
1773 rcprev->next = r->next;
1774 memset (r, 0, sizeof(reg_callsign_t));
1775 free (r);
1776 r = rcprev->next;
1777 }
1778 }
1779 else {
1780 rcprev = r;
1781 r = r->next;
1782 }
1783 }
1784
1785 } /* end dl_client_cleanup */
1786
1787
1788
1789 /*------------------------------------------------------------------------------
1790 *
1791 * Name: dl_data_indication
1792 *
1793 * Purpose: send connected data to client application.
1794 *
1795 * Inputs: pid - Protocol ID.
1796 *
1797 * data - Pointer to array of bytes.
1798 *
1799 * len - Number of bytes in data.
1800 *
1801 *
1802 * Description: TODO: We perform reassembly of segments here if necessary.
1803 *
1804 *------------------------------------------------------------------------------*/
1805
dl_data_indication(ax25_dlsm_t * S,int pid,char * data,int len)1806 static void dl_data_indication (ax25_dlsm_t *S, int pid, char *data, int len)
1807 {
1808
1809
1810
1811 // Now it gets more interesting. We need to combine segments before passing it along.
1812
1813 // See example in dl_data_request.
1814
1815 if (S->ra_buff == NULL) {
1816
1817 // Ready state.
1818
1819 if (pid != AX25_PID_SEGMENTATION_FRAGMENT) {
1820 server_rec_conn_data (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], pid, data, len);
1821 return;
1822 }
1823 else if (data[0] & 0x80) {
1824
1825 // Ready state, First segment.
1826
1827 S->ra_following = data[0] & 0x7f;
1828 int total = (S->ra_following + 1) * (len - 1) - 1; // len should be other side's N1
1829 S->ra_buff = cdata_new(data[1], NULL, total);
1830 S->ra_buff->size = total; // max that we are expecting.
1831 S->ra_buff->len = len - 2; // how much accumulated so far.
1832 memcpy (S->ra_buff->data, data + 2, len - 2);
1833 }
1834 else {
1835 text_color_set(DW_COLOR_ERROR);
1836 dw_printf ("Stream %d: AX.25 Reassembler Protocol Error Z: Not first segment in ready state.\n", S->stream_id);
1837 }
1838 }
1839 else {
1840
1841 // Reassembling data state
1842
1843 if (pid != AX25_PID_SEGMENTATION_FRAGMENT) {
1844
1845 server_rec_conn_data (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], pid, data, len);
1846
1847 text_color_set(DW_COLOR_ERROR);
1848 dw_printf ("Stream %d: AX.25 Reassembler Protocol Error Z: Not segment in reassembling state.\n", S->stream_id);
1849 cdata_delete(S->ra_buff);
1850 S->ra_buff = NULL;
1851 return;
1852 }
1853 else if (data[0] & 0x80) {
1854 text_color_set(DW_COLOR_ERROR);
1855 dw_printf ("Stream %d: AX.25 Reassembler Protocol Error Z: First segment in reassembling state.\n", S->stream_id);
1856 cdata_delete(S->ra_buff);
1857 S->ra_buff = NULL;
1858 return;
1859 }
1860 else if ((data[0] & 0x7f) != S->ra_following - 1) {
1861 text_color_set(DW_COLOR_ERROR);
1862 dw_printf ("Stream %d: AX.25 Reassembler Protocol Error Z: Segments out of sequence.\n", S->stream_id);
1863 cdata_delete(S->ra_buff);
1864 S->ra_buff = NULL;
1865 return;
1866 }
1867 else {
1868
1869 // Reassembling data state, Not first segment.
1870
1871 S->ra_following = data[0] & 0x7f;
1872 if (S->ra_buff->len + len - 1 <= S->ra_buff->size) {
1873 memcpy (S->ra_buff->data + S->ra_buff->len, data + 1, len - 1);
1874 S->ra_buff->len += len - 1;
1875 }
1876 else {
1877 text_color_set(DW_COLOR_ERROR);
1878 dw_printf ("Stream %d: AX.25 Reassembler Protocol Error Z: Segments exceed buffer space.\n", S->stream_id);
1879 cdata_delete(S->ra_buff);
1880 S->ra_buff = NULL;
1881 return;
1882 }
1883
1884 if (S->ra_following == 0) {
1885 // Last one.
1886 server_rec_conn_data (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], S->ra_buff->pid, S->ra_buff->data, S->ra_buff->len);
1887 cdata_delete(S->ra_buff);
1888 S->ra_buff = NULL;
1889 }
1890 }
1891 }
1892
1893
1894 } /* end dl_data_indication */
1895
1896
1897
1898 /*------------------------------------------------------------------------------
1899 *
1900 * Name: lm_channel_busy
1901 *
1902 * Purpose: Change in DCD or PTT status for channel so we know when it is busy.
1903 *
1904 * Inputs: E - Event from the queue.
1905 *
1906 * E->chan - Radio channel number.
1907 *
1908 * E->activity - OCTYPE_PTT for my transmission start/end.
1909 * - OCTYPE_DCD if we hear someone else.
1910 *
1911 * E->status - 1 for active or 0 for quiet.
1912 *
1913 * Outputs: S->radio_channel_busy
1914 *
1915 * T1 & TM201 paused/resumed if running.
1916 *
1917 * Description: We need to pause the timers when the channel is busy.
1918 *
1919 *------------------------------------------------------------------------------*/
1920
1921 static int dcd_status[MAX_CHANS];
1922 static int ptt_status[MAX_CHANS];
1923
lm_channel_busy(dlq_item_t * E)1924 void lm_channel_busy (dlq_item_t *E)
1925 {
1926 int busy;
1927
1928 assert (E->chan >= 0 && E->chan < MAX_CHANS);
1929 assert (E->activity == OCTYPE_PTT || E->activity == OCTYPE_DCD);
1930 assert (E->status == 1 || E->status == 0);
1931
1932 switch (E->activity) {
1933
1934 case OCTYPE_DCD:
1935
1936 if (s_debug_radio) {
1937 text_color_set(DW_COLOR_DEBUG);
1938 dw_printf ("lm_channel_busy: DCD chan %d = %d\n", E->chan, E->status);
1939 }
1940
1941 dcd_status[E->chan] = E->status;
1942 break;
1943
1944 case OCTYPE_PTT:
1945
1946 if (s_debug_radio) {
1947 text_color_set(DW_COLOR_DEBUG);
1948 dw_printf ("lm_channel_busy: PTT chan %d = %d\n", E->chan, E->status);
1949 }
1950
1951 ptt_status[E->chan] = E->status;
1952 break;
1953
1954 default:
1955 break;
1956 }
1957
1958 busy = dcd_status[E->chan] | ptt_status[E->chan];
1959
1960 /*
1961 * We know if the given radio channel is busy or not.
1962 * This must be applied to all data link state machines associated with that radio channel.
1963 */
1964
1965 ax25_dlsm_t *S;
1966
1967 for (S = list_head; S != NULL; S = S->next) {
1968
1969 if (E->chan == S->chan) {
1970
1971 if (busy && ! S->radio_channel_busy) {
1972 S->radio_channel_busy = 1;
1973 PAUSE_T1;
1974 PAUSE_TM201;
1975 }
1976 else if ( ! busy && S->radio_channel_busy) {
1977 S->radio_channel_busy = 0;
1978 RESUME_T1;
1979 RESUME_TM201;
1980 }
1981 }
1982 }
1983
1984 } /* end lm_channel_busy */
1985
1986
1987
1988
1989 /*------------------------------------------------------------------------------
1990 *
1991 * Name: lm_seize_confirm
1992 *
1993 * Purpose: Notification the the channel is clear.
1994 *
1995 * Description: C4.2. This primitive indicates to the Data-link State Machine that
1996 * the transmission opportunity has arrived.
1997 *
1998 * Version 1.5: Originally this only invoked inquiry_response to provide an ack if not already
1999 * taken care of by an earlier frame in this transmission.
2000 * After noticing the unnecessary I frame duplication and differing N(R) in the same
2001 * transmission, I came to the conclusion that we should delay sending of new
2002 * (not resends as a result of rej or srej) frames until after after processing
2003 * of everything in the incoming transmission.
2004 * The protocol spec simply has "I frame pops off queue" without any indication about
2005 * what might trigger this event.
2006 *
2007 *------------------------------------------------------------------------------*/
2008
lm_seize_confirm(dlq_item_t * E)2009 void lm_seize_confirm (dlq_item_t *E)
2010 {
2011
2012 assert (E->chan >= 0 && E->chan < MAX_CHANS);
2013
2014 ax25_dlsm_t *S;
2015
2016 for (S = list_head; S != NULL; S = S->next) {
2017
2018 if (E->chan == S->chan) {
2019
2020
2021 switch (S->state) {
2022
2023 case state_0_disconnected:
2024 case state_1_awaiting_connection:
2025 case state_2_awaiting_release:
2026 case state_5_awaiting_v22_connection:
2027
2028 break;
2029
2030 case state_3_connected:
2031 case state_4_timer_recovery:
2032
2033 // v1.5 change in strategy.
2034 // New I frames, not sent yet, are delayed until after processing anything in the received transmission.
2035 // Previously we started sending new frames, from the client app, as soon as they arrived.
2036 // Now, we first take care of those in progress before throwing more into the mix.
2037
2038 i_frame_pop_off_queue(S);
2039
2040 // Need an RR if we didn't have I frame send the necessary ack.
2041
2042 if (S->acknowledge_pending) {
2043 S->acknowledge_pending = 0;
2044 enquiry_response (S, frame_not_AX25, 0);
2045 }
2046
2047 // Implementation difference: The flow chart for state 3 has LM-RELEASE Request here.
2048 // I don't think I need it because the transmitter will turn off
2049 // automatically once the queue is empty.
2050
2051 // Erratum: The original spec had LM-SEIZE request here, for state 4, which didn't seem right.
2052 // The 2006 revision has LM-RELEASE Request so states 3 & 4 are the same.
2053
2054 break;
2055 }
2056 }
2057 }
2058
2059 } /* lm_seize_confirm */
2060
2061
2062
2063 /*------------------------------------------------------------------------------
2064 *
2065 * Name: lm_data_indication
2066 *
2067 * Purpose: We received some sort of frame over the radio.
2068 *
2069 * Inputs: E - Event from the queue.
2070 * Caller is responsible for freeing it.
2071 *
2072 * Description: First determine if is of interest to me. Two cases:
2073 *
2074 * (1) We already have a link handle for (from-addr, to-addr, channel).
2075 * This could have been set up by an outgoing connect request.
2076 *
2077 * (2) It is addressed to one of the registered callsigns. This would
2078 * catch the case of incoming connect requests. The APRS MYCALL
2079 * is not involved at all. The attached client app might have
2080 * much different ideas about what the station is called or
2081 * aliases it might respond to.
2082 *
2083 *------------------------------------------------------------------------------*/
2084
lm_data_indication(dlq_item_t * E)2085 void lm_data_indication (dlq_item_t *E)
2086 {
2087 ax25_frame_type_t ftype;
2088 char desc[80];
2089 cmdres_t cr;
2090 int pf;
2091 int nr;
2092 int ns;
2093 ax25_dlsm_t *S;
2094 int client_not_applicable = -1;
2095 int n;
2096 int any_unused_digi;
2097
2098
2099 if (E->pp == NULL) {
2100 text_color_set(DW_COLOR_ERROR);
2101 dw_printf ("Internal Error, packet pointer is null. %s %s %d\n", __FILE__, __func__, __LINE__);
2102 return;
2103 }
2104
2105 E->num_addr = ax25_get_num_addr(E->pp);
2106
2107 // Digipeating is not done here so consider only those with no unused digipeater addresses.
2108
2109 any_unused_digi = 0;
2110
2111 for (n = AX25_REPEATER_1; n < E->num_addr; n++) {
2112 if ( ! ax25_get_h(E->pp, n)) {
2113 any_unused_digi = 1;
2114 }
2115 }
2116
2117 if (any_unused_digi) {
2118 if (s_debug_radio) {
2119 text_color_set(DW_COLOR_DEBUG);
2120 dw_printf ("lm_data_indication (%d, %s>%s) - ignore due to unused digi address.\n", E->chan, E->addrs[AX25_SOURCE], E->addrs[AX25_DESTINATION]);
2121 }
2122 return;
2123 }
2124
2125 // Copy addresses from frame into event structure.
2126
2127 for (n = 0; n < E->num_addr; n++) {
2128 ax25_get_addr_with_ssid (E->pp, n, E->addrs[n]);
2129 }
2130
2131 if (s_debug_radio) {
2132 text_color_set(DW_COLOR_DEBUG);
2133 dw_printf ("lm_data_indication (%d, %s>%s)\n", E->chan, E->addrs[AX25_SOURCE], E->addrs[AX25_DESTINATION]);
2134 }
2135
2136 // Look for existing, or possibly create new, link state matching addresses and channel.
2137
2138 // In most cases, we can ignore the frame if we don't have a corresponding
2139 // data link state machine. However, we might want to create a new one for SABM or SABME.
2140 // get_link_handle will check to see if the destination matches my address.
2141
2142 // TODO: This won't work right because we don't know the modulo yet.
2143 // Maybe we should have a shorter form that only returns the frame type.
2144 // That is all we need at this point.
2145
2146 ftype = ax25_frame_type (E->pp, &cr, desc, &pf, &nr, &ns);
2147
2148 S = get_link_handle (E->addrs, E->num_addr, E->chan, client_not_applicable,
2149 (ftype == frame_type_U_SABM) | (ftype == frame_type_U_SABME));
2150
2151 if (S == NULL) {
2152 return;
2153 }
2154
2155 /*
2156 * There is not a reliable way to tell if a frame, out of context, has modulo 8 or 128
2157 * sequence numbers. This needs to be supplied from the data link state machine.
2158 *
2159 * We can't do this until we get the link handle.
2160 */
2161
2162 ax25_set_modulo (E->pp, S->modulo);
2163
2164 /*
2165 * Now we need to use ax25_frame_type again because the previous results, for nr and ns, might be wrong.
2166 */
2167
2168 ftype = ax25_frame_type (E->pp, &cr, desc, &pf, &nr, &ns);
2169
2170 // Gather statistics useful for testing.
2171
2172 if (ftype <= frame_not_AX25) {
2173 S->count_recv_frame_type[ftype]++;
2174 }
2175
2176 switch (ftype) {
2177
2178 case frame_type_I:
2179 if (cr != cr_cmd) {
2180 text_color_set(DW_COLOR_ERROR);
2181 dw_printf ("Stream %d: AX.25 Protocol Error S: %s must be COMMAND.\n", S->stream_id, desc);
2182 }
2183 break;
2184
2185 case frame_type_S_RR:
2186 case frame_type_S_RNR:
2187 case frame_type_S_REJ:
2188 if (cr != cr_cmd && cr != cr_res) {
2189 text_color_set(DW_COLOR_ERROR);
2190 dw_printf ("Stream %d: AX.25 Protocol Error: %s must be COMMAND or RESPONSE.\n", S->stream_id, desc);
2191 }
2192 break;
2193
2194 case frame_type_U_SABME:
2195 case frame_type_U_SABM:
2196 case frame_type_U_DISC:
2197 if (cr != cr_cmd) {
2198 text_color_set(DW_COLOR_ERROR);
2199 dw_printf ("Stream %d: AX.25 Protocol Error: %s must be COMMAND.\n", S->stream_id, desc);
2200 }
2201 break;
2202
2203 // Erratum: The AX.25 spec is not clear about whether SREJ should be command, response, or both.
2204 // The underlying X.25 spec clearly says it is reponse only. Let's go with that.
2205
2206 case frame_type_S_SREJ:
2207 case frame_type_U_DM:
2208 case frame_type_U_UA:
2209 case frame_type_U_FRMR:
2210 if (cr != cr_res) {
2211 text_color_set(DW_COLOR_ERROR);
2212 dw_printf ("Stream %d: AX.25 Protocol Error: %s must be RESPONSE.\n", S->stream_id, desc);
2213 }
2214 break;
2215
2216 case frame_type_U_XID:
2217 case frame_type_U_TEST:
2218 if (cr != cr_cmd && cr != cr_res) {
2219 text_color_set(DW_COLOR_ERROR);
2220 dw_printf ("Stream %d: AX.25 Protocol Error: %s must be COMMAND or RESPONSE.\n", S->stream_id, desc);
2221 }
2222 break;
2223
2224 case frame_type_U_UI:
2225 // Don't test at this point in case an APRS frame gets thru.
2226 // APRS doesn't specify what to put in the Source and Dest C bits.
2227 // In practice we see all 4 possble combinations.
2228 // I have an opinion about what would be "correct" (discussed elsewhere)
2229 // but in practice no one seems to care.
2230 break;
2231
2232 case frame_type_U:
2233 case frame_not_AX25:
2234 // not expected.
2235 break;
2236 }
2237
2238
2239 switch (ftype) {
2240
2241 case frame_type_I: // Information
2242 {
2243 int pid;
2244 unsigned char *info_ptr;
2245 int info_len;
2246
2247 pid = ax25_get_pid (E->pp);
2248 info_len = ax25_get_info (E->pp, &info_ptr);
2249
2250 i_frame (S, cr, pf, nr, ns, pid, (char *)info_ptr, info_len);
2251 }
2252 break;
2253
2254 case frame_type_S_RR: // Receive Ready - System Ready To Receive
2255 rr_rnr_frame (S, 1, cr, pf, nr);
2256 break;
2257
2258 case frame_type_S_RNR: // Receive Not Ready - TNC Buffer Full
2259 rr_rnr_frame (S, 0, cr, pf, nr);
2260 break;
2261
2262 case frame_type_S_REJ: // Reject Frame - Out of Sequence or Duplicate
2263 rej_frame (S, cr, pf, nr);
2264 break;
2265
2266 case frame_type_S_SREJ: // Selective Reject - Ask for selective frame(s) repeat
2267 {
2268 unsigned char *info_ptr;
2269 int info_len;
2270
2271 info_len = ax25_get_info (E->pp, &info_ptr);
2272 srej_frame (S, cr, pf, nr, info_ptr, info_len);
2273 }
2274 break;
2275
2276 case frame_type_U_SABME: // Set Async Balanced Mode, Extended
2277 sabm_e_frame (S, 1, pf);
2278 break;
2279
2280 case frame_type_U_SABM: // Set Async Balanced Mode
2281 sabm_e_frame (S, 0, pf);
2282 break;
2283
2284 case frame_type_U_DISC: // Disconnect
2285 disc_frame (S, pf);
2286 break;
2287
2288 case frame_type_U_DM: // Disconnect Mode
2289 dm_frame (S, pf);
2290 break;
2291
2292 case frame_type_U_UA: // Unnumbered Acknowledge
2293 ua_frame (S, pf);
2294 break;
2295
2296 case frame_type_U_FRMR: // Frame Reject
2297 frmr_frame (S);
2298 break;
2299
2300 case frame_type_U_UI: // Unnumbered Information
2301 ui_frame (S, cr, pf);
2302 break;
2303
2304 case frame_type_U_XID: // Exchange Identification
2305 {
2306 unsigned char *info_ptr;
2307 int info_len;
2308
2309 info_len = ax25_get_info (E->pp, &info_ptr);
2310
2311 xid_frame (S, cr, pf, info_ptr, info_len);
2312 }
2313 break;
2314
2315 case frame_type_U_TEST: // Test
2316 {
2317 unsigned char *info_ptr;
2318 int info_len;
2319
2320 info_len = ax25_get_info (E->pp, &info_ptr);
2321
2322 test_frame (S, cr, pf, info_ptr, info_len);
2323 }
2324 break;
2325
2326 case frame_type_U: // other Unnumbered, not used by AX.25.
2327 break;
2328
2329 case frame_not_AX25: // Could not get control byte from frame.
2330 break;
2331 }
2332
2333 // An incoming frame might have ack'ed frames we sent or indicated peer is no longer busy.
2334 // Rather than putting this test in many places, where those conditions, may have changed,
2335 // we will try to catch them all on this single path.
2336 // Start transmission if we now have some outgoing data ready to go.
2337 // (Added in 1.5 beta 3 for issue 132.)
2338
2339 if ( S->i_frame_queue != NULL &&
2340 (S->state == state_3_connected || S->state == state_4_timer_recovery) &&
2341 ( ! S->peer_receiver_busy ) &&
2342 WITHIN_WINDOW_SIZE(S) ) {
2343
2344 //S->acknowledge_pending = 1;
2345 lm_seize_request (S->chan);
2346 }
2347
2348 } /* end lm_data_indication */
2349
2350
2351
2352 /*------------------------------------------------------------------------------
2353 *
2354 * Name: i_frame
2355 *
2356 * Purpose: Process I Frame.
2357 *
2358 * Inputs: S - Data Link State Machine.
2359 * cr - Command or Response. We have already issued an error if not command.
2360 * p - Poll bit. Assuming we checked earlier that it was a command.
2361 * The meaning is described below.
2362 * nr - N(R) from the frame. Next expected seq. for other end.
2363 * ns - N(S) from the frame. Seq. number of this incoming frame.
2364 * pid - protocol id.
2365 * info_ptr - pointer to information part of frame.
2366 * info_len - Number of bytes in information part of frame.
2367 * Should be in range of 0 thru n1_paclen.
2368 *
2369 * Description:
2370 * 6.4.2. Receiving I Frames
2371 *
2372 * The reception of I frames that contain zero-length information fields is reported to the next layer; no information
2373 * field will be transferred.
2374 *
2375 * 6.4.2.1. Not Busy
2376 *
2377 * If a TNC receives a valid I frame (one with a correct FCS and whose send sequence number equals the
2378 * receiver's receive state variable) and is not in the busy condition, it accepts the received I frame, increments its
2379 * receive state variable, and acts in one of the following manners:
2380 *
2381 * a) If it has an I frame to send, that I frame may be sent with the transmitted N(R) equal to its receive state
2382 * variable V(R) (thus acknowledging the received frame). Alternately, the TNC may send an RR frame with N(R)
2383 * equal to V(R), and then send the I frame.
2384 *
2385 * or b) If there are no outstanding I frames, the receiving TNC sends an RR frame with N(R) equal to V(R). The
2386 * receiving TNC may wait a small period of time before sending the RR frame to be sure additional I frames are
2387 * not being transmitted.
2388 *
2389 * 6.4.2.2. Busy
2390 *
2391 * If the TNC is in a busy condition, it ignores any received I frames without reporting this condition, other than
2392 * repeating the indication of the busy condition.
2393 * If a busy condition exists, the TNC receiving the busy condition indication polls the sending TNC periodically
2394 * until the busy condition disappears.
2395 * A TNC may poll the busy TNC periodically with RR or RNR frames with the P bit set to "1".
2396 *
2397 * 6.4.6. Receiving Acknowledgement
2398 *
2399 * Whenever an I or S frame is correctly received, even in a busy condition, the N(R) of the received frame is
2400 * checked to see if it includes an acknowledgement of outstanding sent I frames. The T1 timer is canceled if the
2401 * received frame actually acknowledges previously unacknowledged frames. If the T1 timer is canceled and there
2402 * are still some frames that have been sent that are not acknowledged, T1 is started again. If the T1 timer expires
2403 * before an acknowledgement is received, the TNC proceeds with the retransmission procedure outlined in Section
2404 * 6.4.11.
2405 *
2406 *
2407 * 6.2. Poll/Final (P/F) Bit Procedures
2408 *
2409 * The next response frame returned to an I frame with the P bit set to "1", received during the information
2410 * transfer state, is an RR, RNR or REJ response with the F bit set to "1".
2411 *
2412 * The next response frame returned to a S or I command frame with the P bit set to "1", received in the
2413 * disconnected state, is a DM response frame with the F bit set to "1".
2414 *
2415 *------------------------------------------------------------------------------*/
2416
i_frame(ax25_dlsm_t * S,cmdres_t cr,int p,int nr,int ns,int pid,char * info_ptr,int info_len)2417 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)
2418 {
2419 switch (S->state) {
2420
2421 case state_0_disconnected:
2422
2423 // Logic from flow chart for "all other commands."
2424
2425 if (cr == cr_cmd) {
2426 cmdres_t r = cr_res; // DM response with F taken from P.
2427 int f = p;
2428 int nopid = 0; // PID applies only for I and UI frames.
2429
2430 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, r, frame_type_U_DM, f, nopid, NULL, 0);
2431 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
2432 }
2433 break;
2434
2435 case state_1_awaiting_connection:
2436 case state_5_awaiting_v22_connection:
2437
2438 // Ignore it. Keep same state.
2439 break;
2440
2441 case state_2_awaiting_release:
2442
2443 // Logic from flow chart for "I, RR, RNR, REJ, SREJ commands."
2444
2445 if (cr == cr_cmd && p == 1) {
2446 cmdres_t r = cr_res; // DM response with F = 1.
2447 int f = 1;
2448 int nopid = 0; // PID applies only for I and UI frames.
2449
2450 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, r, frame_type_U_DM, f, nopid, NULL, 0);
2451 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
2452 }
2453 break;
2454
2455 case state_3_connected:
2456 case state_4_timer_recovery:
2457
2458 // Look carefully. The original had two tiny differences between the two states.
2459 // In the 2006 version, these differences no longer exist.
2460
2461 // Erratum: SDL asks: Is information field length <= N1 (paclen).
2462 // (github issue 102 - Thanks to KK6WHJ for pointing this out.)
2463 // Just because we are limiting the size of our transmitted data, it doesn't mean
2464 // that the other end will be doing the same. With v2.2, the XID frame can be
2465 // used to negotiate a maximum info length but with v2.0, there is no way for the
2466 // other end to know our paclen value.
2467
2468 if (info_len >= 0 && info_len <= AX25_MAX_INFO_LEN) {
2469
2470 if (is_good_nr(S,nr)) {
2471
2472 // Erratum?
2473 // I wonder if this difference is intentional or if only one place was
2474 // was modified after a cut-n-paste of the flow chart segment.
2475
2476 // Erratum: Discrepancy between original and 2006 version.
2477
2478 // Pattern noticed: Anytime we have "is_good_nr" which tests for V(A) <= N(R) <= V(S),
2479 // we should always call "check_i_frame_ackd" or at least set V(A) from N(R).
2480
2481 #if 0 // Erratum: original - states 3 & 4 differ here.
2482
2483 if (S->state == state_3_connected) {
2484 // This sets "S->va = nr" and also does some timer stuff.
2485 check_i_frame_ackd (S,nr);
2486 }
2487 else {
2488 SET_VA(nr);
2489 }
2490
2491 #else // 2006 version - states 3 & 4 same here.
2492
2493 // This sets "S->va = nr" and also does some timer stuff.
2494
2495 check_i_frame_ackd (S,nr);
2496 #endif
2497
2498 // Erratum: v1.5 - My addition.
2499 // I noticed that we sometimes got stuck in state 4 and rc crept up slowly even though
2500 // we received 'I' frames with N(R) values indicating that the other side received everything
2501 // that we sent. Eventually rc could reach the limit and we would get an error.
2502 // If we are in state 4, and other guy ack'ed last I frame we sent, transition to state 3.
2503 // We had a similar situation for RR/RNR for cases other than response, F=1.
2504
2505 if (S->state == state_4_timer_recovery && S->va == S->vs) {
2506
2507 STOP_T1;
2508 select_t1_value (S);
2509 START_T3;
2510 SET_RC(0);
2511 enter_new_state (S, state_3_connected, __func__, __LINE__);
2512 }
2513
2514 if (S->own_receiver_busy) {
2515 // This should be unreachable because we currently don't have a way to set own_receiver_busy.
2516 // But we might the capability someday so implement this while we are here.
2517
2518 if (p == 1) {
2519 cmdres_t cr = cr_res; // Erratum: The use of "F" in the flow chart implies that RNR is a response
2520 // in this case, but I'm not confident about that. The text says frame.
2521 int f = 1;
2522 int nr = S->vr;
2523 packet_t pp;
2524
2525 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_RNR, S->modulo, nr, f, NULL, 0);
2526
2527 // I wonder if this difference is intentional or if only one place was
2528 // was modified after a cut-n-paste of the flow chart segment.
2529
2530 #if 0 // Erratum: Original - state 4 has expedited.
2531
2532 if (S->state == state_4_timer_recovery) {
2533 lm_data_request (S->chan, TQ_PRIO_0_HI, pp); // "expedited"
2534 }
2535 else {
2536 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
2537 }
2538 #else // 2006 version - states 3 & 4 the same.
2539
2540 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
2541
2542 #endif
2543 S->acknowledge_pending = 0;
2544 }
2545
2546 }
2547 else { // Own receiver not busy.
2548
2549 i_frame_continued (S, p, ns, pid, info_ptr, info_len);
2550 }
2551
2552
2553 }
2554 else { // N(R) not in expected range.
2555
2556 nr_error_recovery (S);
2557 // my enhancement. See below.
2558 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
2559 }
2560 }
2561 else { // Bad information length.
2562 // Wouldn't even get to CRC check if not octet aligned.
2563
2564 text_color_set(DW_COLOR_ERROR);
2565 dw_printf ("Stream %d: AX.25 Protocol Error O: Information part length, %d, not in range of 0 thru %d.\n", S->stream_id, info_len, AX25_MAX_INFO_LEN);
2566
2567 establish_data_link (S);
2568 S->layer_3_initiated = 0;
2569
2570 // The original spec always sent SABM and went to state 1.
2571 // I was thinking, why not use v2.2 instead of we were already connected with v2.2?
2572 // My version of establish_data_link combined the two original functions and
2573 // already uses SABME or SABM based on S->modulo.
2574
2575 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
2576 }
2577 break;
2578 }
2579
2580 } /* end i_frame */
2581
2582
2583
2584 /*------------------------------------------------------------------------------
2585 *
2586 * Name: i_frame_continued
2587 *
2588 * Purpose: The I frame processing logic gets pretty complicated.
2589 * Some of it has been split out into a separate function to make
2590 * things more readable.
2591 * We have already done some error checking and processed N(R).
2592 * This is used for both states 3 & 4.
2593 *
2594 * Inputs: S - Data Link State Machine. We are in state 3.
2595 * p - Poll bit.
2596 * ns - N(S) from the frame. Seq. number of this incoming frame.
2597 * pid - protocol id.
2598 * info_ptr - pointer to information part of frame.
2599 * info_len - Number of bytes in information part of frame. Already verified.
2600 *
2601 * Description:
2602 *
2603 * 4.3.2.3. Reject (REJ) Command and Response
2604 *
2605 * The reject frame requests retransmission of I frames starting with N(R). Any frames sent with a sequence
2606 * number of N(R)-1 or less are acknowledged. Additional I frames which may exist may be appended to the
2607 * retransmission of the N(R) frame.
2608 * Only one reject frame condition is allowed in each direction at a time. The reject condition is cleared by the
2609 * proper reception of I frames up to the I frame that caused the reject condition to be initiated.
2610 * The status of the TNC at the other end of the link is requested by sending a REJ command frame with the P bit
2611 * set to one.
2612 *
2613 * 4.3.2.4. Selective Reject (SREJ) Command and Response
2614 *
2615 * (Erratum: SREJ is only response with F bit.)
2616 *
2617 * The selective reject, SREJ, frame is used by the receiving TNC to request retransmission of the single I frame
2618 * numbered N(R). If the P/F bit in the SREJ frame is set to "1", then I frames numbered up to N(R)-1 inclusive are
2619 * considered as acknowledged. However, if the P/F bit in the SREJ frame is set to "0", then the N(R) of the SREJ
2620 * frame does not indicate acknowledgement of I frames.
2621 *
2622 * Each SREJ exception condition is cleared (reset) upon receipt of the I frame with an N(S) equal to the N(R)
2623 * of the SREJ frame.
2624 *
2625 * A receiving TNC may transmit one or more SREJ frames, each containing a different N(R) with the P bit set
2626 * to "0", before one or more earlier SREJ exception conditions have been cleared. However, a SREJ is not
2627 * transmitted if an earlier REJ exception condition has not been cleared as indicated in Section 4.5.4. (To do so
2628 * would request retransmission of an I frame that would be retransmitted by the REJ operation.) Likewise, a REJ
2629 * frame is not transmitted if one or more earlier SREJ exception conditions have not been cleared as indicated in
2630 *
2631 * Section 4.5.4.
2632 *
2633 * I frames transmitted following the I frame indicated by the SREJ frame are not retransmitted as the result of
2634 * receiving a SREJ frame. Additional I frames awaiting initial transmission may be transmitted following the
2635 * retransmission of the specific I frame requested by the SREJ frame.
2636 *
2637 *
2638 * 6.4.4. Reception of Out-of-Sequence Frames
2639 *
2640 * 6.4.4.1. Implicit Reject (REJ)
2641 *
2642 * When an I frame is received with a correct FCS but its send sequence number N(S) does not match the current
2643 * receiver's receive state variable, the frame is discarded. A REJ frame is sent with a receive sequence number
2644 * equal to one higher than the last correctly received I frame if an uncleared N(S) sequence error condition has not
2645 * been previously established. The received state variable and poll bit of the discarded frame is checked and acted
2646 * upon, if necessary.
2647 * This mode requires no frame queueing and frame resequencing at the receiver. However, because the mode
2648 * requires transmission of frames that may not be in error, its throughput is not as high as selective reject. This
2649 * mode is ineffective on systems with long round-trip delays and high data rates.
2650 *
2651 * 6.4.4.2. Selective Reject (SREJ)
2652 *
2653 * When an I frame is received with a correct FCS but its send sequence number N(S) does not match the current
2654 * receiver's receive state variable, the frame is retained. SREJ frames are sent with a receive sequence number
2655 * equal to the value N(R) of the missing frame, and P=1 if an uncleared SREJ condition has not been previously
2656 * established. If an SREJ condition is already pending, an SREJ will be sent with P=0. The received state variable
2657 * and poll bit of the received frame are checked and acted upon, if necessary.
2658 * This mode requires frame queueing and frame resequencing at the receiver. The holding of frames can
2659 * consume precious buffer space, especially if the user device has limited memory available and several active
2660 * links are operational.
2661 *
2662 * 6.4.4.3. Selective Reject-Reject (SREJ/REJ)
2663 *
2664 * (Erratum: REJ/SREJ should not be mixed. Basic (mod 8) allows only REJ.
2665 * Extended (mod 128) gives you a choice of one or the other for a link.)
2666 *
2667 * When an I frame is received with a correct FCS but its send sequence number N(S) does not match the current
2668 * receiver's receive state variable, and if N(S) indicates 2 or more frames are missing, a REJ frame is transmitted.
2669 * All subsequently received frames are discarded until the lost frame is correctly received. If only one frame is
2670 * missing, a SREJ frame is sent with a receive sequence number equal to the value N(R) of the missing frame. The
2671 * received state variable and poll bit of the received frame are checked and acted upon. If another frame error
2672 * occurs prior to recovery of the SREJ condition, the receiver saves all frames received after the first errored frame
2673 * and discards frames received after the second errored frame until the first errored frame is recovered. Then, a
2674 * REJ is issued to recover the second errored frame and all subsequent discarded frames.
2675 *
2676 *------------------------------------------------------------------------------*/
2677
i_frame_continued(ax25_dlsm_t * S,int p,int ns,int pid,char * info_ptr,int info_len)2678 static void i_frame_continued (ax25_dlsm_t *S, int p, int ns, int pid, char *info_ptr, int info_len)
2679 {
2680
2681 if (ns == S->vr) {
2682
2683 // The receive sequence number, N(S), is the same as what we were expecting, V(R).
2684 // Send it to the application and increment the next expected.
2685 // It is possible that this was resent and we tucked away others with the following
2686 // sequence numbers. If so, process them too.
2687
2688
2689 SET_VR(AX25MODULO(S->vr + 1, S->modulo, __FILE__, __func__, __LINE__));
2690 S->reject_exception = 0;
2691
2692
2693 if (s_debug_client_app) {
2694 text_color_set(DW_COLOR_DEBUG);
2695 dw_printf ("call dl_data_indication() at %s %d, N(S)=%d, V(R)=%d, \"", __func__, __LINE__, ns, S->vr);
2696 ax25_safe_print (info_ptr, info_len, 1);
2697 dw_printf ("\"\n");
2698 }
2699
2700 dl_data_indication (S, pid, info_ptr, info_len);
2701
2702 if (S->rxdata_by_ns[ns] != NULL) {
2703 // There is a possibility that we might have another received frame stashed
2704 // away from 8 or 128 (modulo) frames back. Remove it so it doesn't accidently
2705 // show up at some future inopportune time.
2706
2707 cdata_delete (S->rxdata_by_ns[ns]);
2708 S->rxdata_by_ns[ns] = NULL;
2709
2710 }
2711
2712
2713 while (S->rxdata_by_ns[S->vr] != NULL) {
2714
2715 // dl_data_indication - send connected data to client application.
2716
2717 if (s_debug_client_app) {
2718 text_color_set(DW_COLOR_DEBUG);
2719 dw_printf ("call dl_data_indication() at %s %d, N(S)=%d, V(R)=%d, data=\"", __func__, __LINE__, ns, S->vr);
2720 ax25_safe_print (S->rxdata_by_ns[S->vr]->data, S->rxdata_by_ns[S->vr]->len, 1);
2721 dw_printf ("\"\n");
2722 }
2723
2724 dl_data_indication (S, S->rxdata_by_ns[S->vr]->pid, S->rxdata_by_ns[S->vr]->data, S->rxdata_by_ns[S->vr]->len);
2725
2726 // Don't keep around anymore after sending it to client app.
2727
2728 cdata_delete (S->rxdata_by_ns[S->vr]);
2729 S->rxdata_by_ns[S->vr] = NULL;
2730
2731 SET_VR(AX25MODULO(S->vr + 1, S->modulo, __FILE__, __func__, __LINE__));
2732 }
2733
2734 if (p) {
2735
2736 // Mentioned in section 6.2.
2737 // The next response frame returned to an I frame with the P bit set to "1", received during the information
2738 // transfer state, is an RR, RNR or REJ response with the F bit set to "1".
2739
2740 int f = 1;
2741 int nr = S->vr; // Next expected sequence number.
2742 cmdres_t cr = cr_res; // response with F set to 1.
2743 packet_t pp;
2744
2745 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_RR, S->modulo, nr, f, NULL, 0);
2746 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
2747 S->acknowledge_pending = 0;
2748 }
2749 else if ( ! S->acknowledge_pending) {
2750
2751 S->acknowledge_pending = 1; // Probably want to set this before the LM-SEIZE Request
2752 // in case the LM-SEIZE Confirm gets processed before we
2753 // return from it.
2754
2755 // Force start of transmission even if the transmit frame queue is empty.
2756 // Notify me, with lm_seize_confirm, when transmission has started.
2757 // When that event arrives, we check acknowledge_pending and send something
2758 // to be determined later.
2759
2760 lm_seize_request (S->chan);
2761 }
2762 }
2763 else if (S->reject_exception) {
2764
2765 // This is not the sequence we were expecting.
2766 // We previously sent REJ, asking for a resend so don't send another.
2767 // In this case, send RR only if the Poll bit is set.
2768 // Again, reference section 6.2.
2769
2770 if (p) {
2771 int f = 1;
2772 int nr = S->vr; // Next expected sequence number.
2773 cmdres_t cr = cr_res; // response with F set to 1.
2774 packet_t pp;
2775
2776 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_RR, S->modulo, nr, f, NULL, 0);
2777 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
2778 S->acknowledge_pending = 0;
2779 }
2780 }
2781 else if (S->srej_enable == srej_none) {
2782
2783 // The received sequence number is not the expected one and we can't use SREJ.
2784 // The old v2.0 approach is to send and REJ with the number we are expecting.
2785 // This can be very inefficient. For example if we received 1,3,4,5,6 in one transmission,
2786 // we discard 3,4,5,6, and tell the other end to resend everything starting with 2.
2787
2788 // At one time, I had some doubts about when to use command or response for REJ.
2789 // I now believe that reponse, as implied by setting F in the flow chart, is correct.
2790
2791 int f = p;
2792 int nr = S->vr; // Next expected sequence number.
2793 cmdres_t cr = cr_res; // response with F copied from P in I frame.
2794 packet_t pp;
2795
2796 S->reject_exception = 1;
2797
2798 if (s_debug_retry) {
2799 text_color_set(DW_COLOR_ERROR); // make it more noticable.
2800 dw_printf ("sending REJ, at %s %d, SREJ not enabled case, V(R)=%d", __func__, __LINE__, S->vr);
2801 }
2802
2803 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_REJ, S->modulo, nr, f, NULL, 0);
2804 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
2805
2806 S->acknowledge_pending = 0;
2807 }
2808 else {
2809
2810 // Selective reject is enabled so we can use the more efficient method.
2811 // This is normally enabled for v2.2 but XID can be used to change that.
2812 // First we save the current frame so we can retrieve it later after getting the fill in.
2813
2814 if (S->modulo != 128) {
2815 text_color_set(DW_COLOR_ERROR);
2816 dw_printf ("INTERNAL ERROR: Should not be sending SREJ in basic (modulo 8) mode.\n");
2817 }
2818
2819 #if 1
2820
2821 // Erratum: AX.25 protocol spec did not handle SREJ very well.
2822 // Based on X.25 section 2.4.6.4.
2823
2824
2825 if (is_ns_in_window(S, ns)) {
2826
2827 // X.25 2.4.6.4 (b)
2828 // v(R) < N(S) < V(R)+k so it is in the expected range.
2829 // Save it in the receive buffer.
2830
2831 if (S->rxdata_by_ns[ns] != NULL) {
2832 cdata_delete (S->rxdata_by_ns[ns]);
2833 S->rxdata_by_ns[ns] = NULL;
2834 }
2835 S->rxdata_by_ns[ns] = cdata_new(pid, info_ptr, info_len);
2836
2837 if (s_debug_misc) {
2838 dw_printf ("%s %d, save to rxdata_by_ns N(S)=%d, V(R)=%d, \"", __func__, __LINE__, ns, S->vr);
2839 ax25_safe_print (info_ptr, info_len, 1);
2840 dw_printf ("\"\n");
2841 }
2842
2843 if (p == 1) {
2844 int f = 1;
2845 enquiry_response (S, frame_type_I, f);
2846 }
2847 else if (S->own_receiver_busy) {
2848 cmdres_t cr = cr_res; // send RNR response
2849 int f = 0; // we know p=0 here.
2850 int nr = S->vr;
2851 packet_t pp;
2852
2853 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_RNR, S->modulo, nr, f, NULL, 0);
2854 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
2855 }
2856 else if (S->rxdata_by_ns[ AX25MODULO(ns - 1, S->modulo, __FILE__, __func__, __LINE__)] == NULL) {
2857
2858 // Ask for missing frames when we don't have N(S)-1 in the receive buffer.
2859
2860 // In version 1.4:
2861 // We end up sending more SREJ than necessary and and get back redundant information. Example:
2862 // When we see 113 missing, we ask for a resend.
2863 // When we see 115 & 116 missing, a cummulative SREJ asks for everything.
2864 // The other end dutifully sends 113 twice.
2865 //
2866 // [0.4] DW1>DW0:(SREJ res, n(r)=113, f=0)
2867 // [0.4] DW1>DW0:(SREJ res, n(r)=113, f=1)<0xe6><0xe8>
2868 //
2869 // [0L] DW0>DW1:(I cmd, n(s)=113, n(r)=11, p=0, pid=0xf0)0114 send data<0x0d>
2870 // [0L] DW0>DW1:(I cmd, n(s)=113, n(r)=11, p=0, pid=0xf0)0114 send data<0x0d>
2871 // [0L] DW0>DW1:(I cmd, n(s)=115, n(r)=11, p=0, pid=0xf0)0116 send data<0x0d>
2872 // [0L] DW0>DW1:(I cmd, n(s)=116, n(r)=11, p=0, pid=0xf0)0117 send data<0x0d>
2873
2874
2875 // Version 1.5:
2876 // Don't generate duplicate requests for gaps in the same transmission.
2877
2878 // Ideally, we might wait until carrier drops and then use one Multi-SREJ for entire transmission but
2879 // we will keep that for another day.
2880 // Probably need a flag similar to acknowledge_pending (or ask_resend_count, here) and the ask_for_resend array.
2881 // It could then be processed first in lm_seize_confirm.
2882
2883 int ask_for_resend[128];
2884 int ask_resend_count = 0;
2885 int x;
2886
2887 // Version 1.5
2888 // Erratum: AX.25 says use F=0 here. Doesn't make sense.
2889 // We would want to set F when sending N(R) = V(R).
2890 // int allow_f1 = 0; // F=1 from X.25 2.4.6.4 b) 3)
2891 int allow_f1 = 1; // F=1 from X.25 2.4.6.4 b) 3)
2892
2893 // send only for this gap, not cummulative from V(R).
2894
2895 int last = AX25MODULO(ns - 1, S->modulo, __FILE__, __func__, __LINE__);
2896 int first = last;
2897 while (first != S->vr && S->rxdata_by_ns[AX25MODULO(first - 1, S->modulo, __FILE__, __func__, __LINE__)] == NULL) {
2898 first = AX25MODULO(first - 1, S->modulo, __FILE__, __func__, __LINE__);
2899 }
2900 x = first;
2901 do {
2902 ask_for_resend[ask_resend_count++] = AX25MODULO(x, S->modulo, __FILE__, __func__, __LINE__);
2903 x = AX25MODULO(x + 1, S->modulo, __FILE__, __func__, __LINE__);
2904 } while (x != AX25MODULO(last + 1, S->modulo, __FILE__, __func__, __LINE__));
2905
2906 send_srej_frames (S, ask_for_resend, ask_resend_count, allow_f1);
2907 }
2908 }
2909 else {
2910
2911 // X.25 2.4.6.4 a)
2912 // N(S) is not in expected range. Discard it. Send response if P=1.
2913
2914 if (p == 1) {
2915 int f = 1;
2916 enquiry_response (S, frame_type_I, f);
2917 }
2918
2919 }
2920
2921 #else // my earlier attempt before taking a close look at X.25 spec.
2922 // Keeping it around for a little while because I might want to
2923 // use earlier technique of sending only needed SREJ for any second
2924 // and later gaps in a single multiframe transmission.
2925
2926
2927 if (S->rxdata_by_ns[ns] != NULL) {
2928 cdata_delete (S->rxdata_by_ns[ns]);
2929 S->rxdata_by_ns[ns] = NULL;
2930 }
2931 S->rxdata_by_ns[ns] = cdata_new(pid, info_ptr, info_len);
2932
2933 S->outstanding_srej[ns] = 0; // Don't care if it was previously set or not.
2934 // We have this one so there is no outstanding SREJ for it.
2935
2936 if (s_debug_misc) {
2937 dw_printf ("%s %d, save to rxdata_by_ns N(S)=%d, V(R)=%d, \"", __func__, __LINE__, ns, S->vr);
2938 ax25_safe_print (info_ptr, info_len, 1);
2939 dw_printf ("\"\n");
2940 }
2941
2942
2943
2944
2945 if (selective_reject_exception(S) == 0) {
2946
2947 // Erratum: This is vastly different than the SDL in the AX.25 protocol spec.
2948 // That would use SREJ if only one was missing and REJ instead.
2949 // Here we do not mix the them.
2950 // This agrees with the X.25 protocol spec that says use one or the other. Not both.
2951
2952 // Suppose we had incoming I frames 0, 3, 7.
2953 // 0 was already processed and V(R)=1 meaning that is the next expected.
2954 // At this point we area processing N(S)=3.
2955 // In this case, we need to ask for a resend of 1 & 2.
2956 // More generally, the range of V(R) thru N(S)-1.
2957
2958 int ask_for_resend[128];
2959 int ask_resend_count = 0;
2960 int i;
2961 int allow_f1 = 1;
2962
2963 text_color_set(DW_COLOR_ERROR);
2964 dw_printf ("%s:%d, zero exceptions, V(R)=%d, N(S)=%d\n", __func__, __LINE__, S->vr, ns);
2965
2966 for (i = S->vr; i != ns; i = AX25MODULO(i+1, S->modulo, __FILE__, __func__, __LINE__)) {
2967 ask_for_resend[ask_resend_count++] = i;
2968 }
2969
2970 send_srej_frames (S, ask_for_resend, ask_resend_count, allow_f1);
2971 }
2972 else {
2973
2974 // Erratum: The SDL says ask for N(S) which is clearly wrong because that's what we just received.
2975 // Instead we want to ask for any missing frames up to but not including N(S).
2976
2977 // Let's continue with the example above. I frames with N(S) of 0, 3, 7.
2978 // selective_reject_exception is non zero meaning there are outstanding requests to resend specified I frames.
2979 // V(R) is still 1 because 0 is the last one received with contiguous N(S) values.
2980 // 3 has been saved into S->rxdata_by_ns.
2981 // We now have N(S)=7. We want to ask for a resend of 4, 5, 6.
2982 // This can be achieved by searching S->rxdata_by_ns, starting with N(S)-1, and counting
2983 // how many empty slots we have before finding a saved frame.
2984
2985 int ask_resend_count = 0;
2986 int first;
2987
2988 text_color_set(DW_COLOR_ERROR);
2989 dw_printf ("%s:%d, %d srej exceptions, V(R)=%d, N(S)=%d\n", __func__, __LINE__, selective_reject_exception(S), S->vr, ns);
2990
2991 first = AX25MODULO(ns - 1, S->modulo, __FILE__, __func__, __LINE__);
2992 while (S->rxdata_by_ns[first] == NULL) {
2993 if (first == AX25MODULO(S->vr - 1, S->modulo, __FILE__, __func__, __LINE__)) {
2994 // Oops! Went too far. This I frame was already processed.
2995 text_color_set(DW_COLOR_ERROR);
2996 dw_printf ("INTERNAL ERROR calulating what to put in SREJ, %s line %d\n", __func__, __LINE__);
2997 dw_printf ("V(R)=%d, N(S)=%d, SREJ exception=%d, first=%d, ask_resend_count=%d\n", S->vr, ns, selective_reject_exception(S), first, ask_resend_count);
2998 int k;
2999 for (k=0; k<128; k++) {
3000 if (S->rxdata_by_ns[k] != NULL) {
3001 dw_printf ("rxdata_by_ns[%d] has data\n", k);
3002 }
3003 }
3004 break;
3005 }
3006 ask_resend_count++;
3007 first = AX25MODULO(first - 1, S->modulo, __FILE__, __func__, __LINE__);
3008 }
3009
3010 // Go beyond the slot where we already have an I frame.
3011 first = AX25MODULO(first + 1, S->modulo, __FILE__, __func__, __LINE__);
3012
3013 // The ask_resend_count could be 0. e.g. We got 4 rather than 7 in this example.
3014
3015 if (ask_resend_count > 0) {
3016 int ask_for_resend[128];
3017 int n;
3018 int allow_f1 = 1;
3019
3020 for (n = 0; n < ask_resend_count; n++) {
3021 ask_for_resend[n] = AX25MODULO(first + n, S->modulo, __FILE__, __func__, __LINE__);;
3022 }
3023
3024 send_srej_frames (S, ask_for_resend, ask_resend_count, allow_f1);
3025 }
3026
3027 } /* end SREJ exception */
3028
3029 #endif // my earlier attempt.
3030
3031
3032
3033
3034 // Erratum: original has following but 2006 rev does not.
3035 // I think the 2006 version is correct.
3036 // SREJ does not always satisfy the need for ack.
3037 // There is a special case where F=1. We take care of that inside of send_srej_frames.
3038
3039 #if 0
3040 S->acknowledge_pending = 0;
3041 #endif
3042
3043 } /* end srej enabled */
3044
3045
3046 } /* end i_frame_continued */
3047
3048
3049
3050 /*------------------------------------------------------------------------------
3051 *
3052 * Name: is_ns_in_window
3053 *
3054 * Purpose: Is the N(S) value of the incoming I frame in the expected range?
3055 *
3056 * Inputs: ns - Sequence from I frame.
3057 *
3058 * Description: With selective reject, it is possible that we could receive a repeat of
3059 * an I frame with N(S) less than V(R). In this case, we just want to
3060 * discard it rather than getting upset and reestablishing the connection.
3061 *
3062 * The X.25 spec,section 2.4.6.4 (b) asks whether V(R) < N(S) < V(R)+k.
3063 *
3064 * The problem here is that it depends on the value of k for the other end.
3065 * X.25 says that both sides need to agree on a common value of k ahead of time.
3066 * We might have k=8 for our sending but the other side could have k=32 so
3067 * this test could fail.
3068 *
3069 * As a hack, we could use the value 63 here. If too small we would discard
3070 * I frames that are in the acceptable range because they would be >= V(R)+k.
3071 * On the other hand, if this value is too big, the range < V(R) would not be
3072 * large enough and we would accept frame we shouldn't.
3073 * As a practical matter, using a window size that large is pretty unlikely.
3074 * Maybe I could put a limit of 63, rather than 127 in the configuration.
3075 *
3076 *------------------------------------------------------------------------------*/
3077
3078 #define GENEROUS_K 63
3079
is_ns_in_window(ax25_dlsm_t * S,int ns)3080 static int is_ns_in_window (ax25_dlsm_t *S, int ns)
3081 {
3082 int adjusted_vr, adjusted_ns, adjusted_vrpk;
3083 int result;
3084
3085 /* Shift all values relative to V(R) before comparing so we won't have wrap around. */
3086
3087 #define adjust_by_vr(x) (AX25MODULO((x) - S->vr, S->modulo, __FILE__, __func__, __LINE__))
3088
3089 adjusted_vr = adjust_by_vr(S->vr); // A clever compiler would know it is zero.
3090 adjusted_ns = adjust_by_vr(ns);
3091 adjusted_vrpk = adjust_by_vr(S->vr + GENEROUS_K);
3092
3093 result = adjusted_vr < adjusted_ns && adjusted_ns < adjusted_vrpk;
3094
3095 if (s_debug_retry) {
3096 text_color_set(DW_COLOR_DEBUG);
3097 dw_printf ("is_ns_in_window, V(R) %d < N(S) %d < V(R)+k %d, returns %d\n", S->vr, ns, S->vr + GENEROUS_K, result);
3098 }
3099
3100 return (result);
3101 }
3102
3103
3104 /*------------------------------------------------------------------------------
3105 *
3106 * Name: send_srej_frames
3107 *
3108 * Purpose: Ask for a resend of I frames with specified sequence numbers.
3109 *
3110 * Inputs: resend - Array of N(S) values for missing I frames.
3111 *
3112 * count - Number of items in array.
3113 *
3114 * allow_f1 - When true, set F=1 when asking for V(R).
3115 *
3116 * X.25 section 2.4.6.4 b) 3) says F should be set to 0
3117 * when receiving I frame out of sequence.
3118 *
3119 * X.25 sections 2.4.6.11 & 2.3.5.2.2 say set F to 1 when
3120 * responding to command with P=1. (our enquiry_response function).
3121 *
3122 * Version 1.5: The X.25 protocol spec allows additional sequence numbers in one frame
3123 * by using the INFO part.
3124 * By default that feature is off but can be negotiated with XID.
3125 * We should be able to use this between two direwolf stations while
3126 * maintaining compatibility with the original AX.25 v2.2.
3127 *
3128 *------------------------------------------------------------------------------*/
3129
3130
send_srej_frames(ax25_dlsm_t * S,int * resend,int count,int allow_f1)3131 static void send_srej_frames (ax25_dlsm_t *S, int *resend, int count, int allow_f1)
3132 {
3133 int f; // Set if we are ack-ing one before.
3134 int nr;
3135 cmdres_t cr = cr_res; // SREJ is always response.
3136 int i;
3137
3138 packet_t pp;
3139
3140 if (count <= 0) {
3141 text_color_set(DW_COLOR_ERROR);
3142 dw_printf ("INTERNAL ERROR, count=%d, %s line %d\n", count, __func__, __LINE__);
3143 return;
3144 }
3145
3146 if (s_debug_retry) {
3147 text_color_set(DW_COLOR_INFO);
3148 dw_printf ("%s line %d\n", __func__, __LINE__);
3149 //dw_printf ("state=%d, count=%d, k=%d, V(R)=%d, SREJ exeception=%d\n", S->state, count, S->k_maxframe, S->vr, selective_reject_exception(S));
3150 dw_printf ("state=%d, count=%d, k=%d, V(R)=%d\n", S->state, count, S->k_maxframe, S->vr);
3151
3152 dw_printf ("resend[]=");
3153 for (i = 0; i < count; i++) {
3154 dw_printf (" %d", resend[i]);
3155 }
3156 dw_printf ("\n");
3157
3158 dw_printf ("rxdata_by_ns[]=");
3159 for (i = 0; i < 128; i++) {
3160 if (S->rxdata_by_ns[i] != NULL) {
3161 dw_printf (" %d", i);
3162 }
3163 }
3164 dw_printf ("\n");
3165 }
3166
3167
3168 // Something is wrong! We ask for more than the window size.
3169
3170 if (count > S->k_maxframe) {
3171
3172 text_color_set(DW_COLOR_ERROR);
3173 dw_printf ("INTERNAL ERROR - Extreme number of SREJ, %s line %d\n", __func__, __LINE__);
3174 dw_printf ("state=%d, count=%d, k=%d, V(R)=%d\n", S->state, count, S->k_maxframe, S->vr);
3175
3176 dw_printf ("resend[]=");
3177 for (i = 0; i < count; i++) {
3178 dw_printf (" %d", resend[i]);
3179 }
3180 dw_printf ("\n");
3181
3182 dw_printf ("rxdata_by_ns[]=");
3183 for (i = 0; i < 128; i++) {
3184 if (S->rxdata_by_ns[i] != NULL) {
3185 dw_printf (" %d", i);
3186 }
3187 }
3188 dw_printf ("\n");
3189 }
3190
3191 // Multi-SREJ - Use info part for additional sequence number(s) instead of sending separate SREJ for each.
3192
3193 if (S->srej_enable == srej_multi && count > 1) {
3194
3195 unsigned char info[128];
3196 int info_len = 0;
3197
3198 for (i = 1; i < count; i++) { // skip first one
3199
3200 if (resend[i] < 0 || resend[i] >= S->modulo) {
3201 text_color_set(DW_COLOR_ERROR);
3202 dw_printf ("INTERNAL ERROR, additional nr=%d, modulo=%d, %s line %d\n", resend[i], S->modulo, __func__, __LINE__);
3203 }
3204
3205 // There is also a form to specify a range but I don't
3206 // think it is worth the effort to generate it. Maybe later.
3207
3208 if (S->modulo == 8) {
3209 info[info_len++] = resend[i] << 5;
3210 }
3211 else {
3212 info[info_len++] = resend[i] << 1;
3213 }
3214 }
3215
3216 f = 0;
3217 nr = resend[0];
3218 f = allow_f1 && (nr == S->vr);
3219 // Possibly set if we are asking for the next after
3220 // the last one received in contiguous order.
3221
3222 // This could only apply to the first in
3223 // the list so this would not go in the loop.
3224
3225 if (f) { // In this case the other end is being
3226 // informed of my V(R) so no additional
3227 // RR etc. is needed.
3228 // TODO: Need to think about this.
3229 S->acknowledge_pending = 0;
3230 }
3231
3232 if (nr < 0 || nr >= S->modulo) {
3233 text_color_set(DW_COLOR_ERROR);
3234 dw_printf ("INTERNAL ERROR, nr=%d, modulo=%d, %s line %d\n", nr, S->modulo, __func__, __LINE__);
3235 nr = AX25MODULO(nr, S->modulo, __FILE__, __func__, __LINE__);
3236 }
3237
3238 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_SREJ, S->modulo, nr, f, info, info_len);
3239 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
3240 return;
3241 }
3242
3243 // Multi-SREJ not enabled. Send separate SREJ for each desired sequence number.
3244
3245 for (i = 0; i < count; i++) {
3246
3247 nr = resend[i];
3248 f = allow_f1 && (nr == S->vr);
3249 // Possibly set if we are asking for the next after
3250 // the last one received in contiguous order.
3251
3252 if (f) {
3253 // In this case the other end is being
3254 // informed of my V(R) so no additional
3255 // RR etc. is needed.
3256 S->acknowledge_pending = 0;
3257 }
3258
3259 if (nr < 0 || nr >= S->modulo) {
3260 text_color_set(DW_COLOR_ERROR);
3261 dw_printf ("INTERNAL ERROR, nr=%d, modulo=%d, %s line %d\n", nr, S->modulo, __func__, __LINE__);
3262 nr = AX25MODULO(nr, S->modulo, __FILE__, __func__, __LINE__);
3263 }
3264
3265 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_SREJ, S->modulo, nr, f, NULL, 0);
3266 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
3267 }
3268
3269 } /* end send_srej_frames */
3270
3271
3272
3273 /*------------------------------------------------------------------------------
3274 *
3275 * Name: rr_rnr_frame
3276 *
3277 * Purpose: Process RR or RNR Frame.
3278 * Processing is the essentially the same so they are handled by a single function.
3279 *
3280 * Inputs: S - Data Link State Machine.
3281 * ready - True for RR, false for RNR
3282 * cr - Is this command or response?
3283 * pf - Poll/Final bit.
3284 * nr - N(R) from the frame.
3285 *
3286 * Description: 4.3.2.1. Receive Ready (RR) Command and Response
3287 *
3288 * Receive Ready accomplishes the following:
3289 * a) indicates that the sender of the RR is now able to receive more I frames;
3290 * b) acknowledges properly received I frames up to, and including N(R)-1;and
3291 * c) clears a previously-set busy condition created by an RNR command having been sent.
3292 * The status of the TNC at the other end of the link can be requested by sending an RR command frame with the
3293 * P-bit set to one.
3294 *
3295 * 4.3.2.2. Receive Not Ready (RNR) Command and Response
3296 *
3297 * Receive Not Ready indicates to the sender of I frames that the receiving TNC is temporarily busy and cannot
3298 * accept any more I frames. Frames up to N(R)-1 are acknowledged. Frames N(R) and above that may have been
3299 * transmitted are discarded and must be retransmitted when the busy condition clears.
3300 * The RNR condition is cleared by the sending of a UA, RR, REJ or SABM(E) frame.
3301 * The status of the TNC at the other end of the link is requested by sending an RNR command frame with the
3302 * P bit set to one.
3303 *
3304 *------------------------------------------------------------------------------*/
3305
3306
rr_rnr_frame(ax25_dlsm_t * S,int ready,cmdres_t cr,int pf,int nr)3307 static void rr_rnr_frame (ax25_dlsm_t *S, int ready, cmdres_t cr, int pf, int nr)
3308 {
3309
3310 // dw_printf ("rr_rnr_frame (ready=%d, cr=%d, pf=%d, nr=%d) state=%d\n", ready, cr, pf, nr, S->state);
3311
3312 switch (S->state) {
3313
3314 case state_0_disconnected:
3315
3316 if (cr == cr_cmd) {
3317 cmdres_t r = cr_res; // DM response with F taken from P.
3318 int f = pf;
3319 int nopid = 0; // PID only for I and UI frames.
3320 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, r, frame_type_U_DM, f, nopid, NULL, 0);
3321 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
3322 }
3323 break;
3324
3325 case state_1_awaiting_connection:
3326 case state_5_awaiting_v22_connection:
3327
3328 // do nothing.
3329 break;
3330
3331 case state_2_awaiting_release:
3332
3333 // Logic from flow chart for "I, RR, RNR, REJ, SREJ commands."
3334
3335 if (cr == cr_cmd && pf == 1) {
3336 cmdres_t r = cr_res; // DM response with F = 1.
3337 int f = 1;
3338 int nopid = 0; // PID applies only for I and UI frames.
3339
3340 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, r, frame_type_U_DM, f, nopid, NULL, 0);
3341 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
3342 }
3343
3344 // Erratum: We have a disagreement here between original and 2006 version.
3345 // RR, RNR, REJ, SREJ responses would fall under "all other primitives."
3346 // In the original, we simply ignore it and stay in state 2.
3347 // The 2006 version, page 94, says go into "1 awaiting connection" state.
3348 // That makes no sense to me.
3349
3350 break;
3351
3352 case state_3_connected:
3353
3354 S->peer_receiver_busy = ! ready;
3355
3356 // Erratum: the flow charts have unconditional check_need_for_response here.
3357 // I don't recall exactly why I added the extra test for command and P=1.
3358 // It might have been because we were reporting error A for response with F=1.
3359 // Other than avoiding that error message, this is functionally equivalent.
3360
3361 if (cr == cr_cmd && pf) {
3362 check_need_for_response (S, ready ? frame_type_S_RR : frame_type_S_RNR, cr, pf);
3363 }
3364
3365 if (is_good_nr(S,nr)) {
3366 // dw_printf ("rr_rnr_frame (), line %d, state=%d, good nr=%d, calling check_i_frame_ackd\n", __LINE__, S->state, nr);
3367
3368 check_i_frame_ackd (S, nr);
3369 }
3370 else {
3371 if (s_debug_retry) {
3372 text_color_set(DW_COLOR_DEBUG);
3373 dw_printf ("rr_rnr_frame (), line %d, state=%d, bad nr, calling nr_error_recovery\n", __LINE__, S->state);
3374 }
3375
3376 nr_error_recovery (S);
3377 // My enhancement. Original always sent SABM and went to state 1.
3378 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
3379 }
3380
3381 break;
3382
3383 case state_4_timer_recovery:
3384
3385 S->peer_receiver_busy = ! ready;
3386
3387 if (cr == cr_res && pf == 1) {
3388
3389 // RR/RNR Response with F==1.
3390
3391 if (s_debug_retry) {
3392 text_color_set(DW_COLOR_DEBUG);
3393 dw_printf ("rr_rnr_frame (), Response, f=%d, line %d, state=%d, good nr, calling check_i_frame_ackd\n", pf, __LINE__, S->state);
3394 }
3395
3396 STOP_T1;
3397 select_t1_value(S);
3398
3399 if (is_good_nr(S,nr)) {
3400
3401 SET_VA(nr);
3402 if (S->vs == S->va) { // all caught up with ack from other guy.
3403 START_T3;
3404 SET_RC(0); // My enhancement. See Erratum note in select_t1_value.
3405 enter_new_state (S, state_3_connected, __func__, __LINE__);
3406 }
3407 else {
3408 invoke_retransmission (S, nr);
3409 // my addition
3410
3411 // Erratum: We sent I frame(s) and want to timeout if no ack comes back.
3412 // We also sent N(R) so no need for extra RR at the end only for that.
3413
3414 STOP_T3;
3415 START_T1;
3416 S->acknowledge_pending = 0;
3417
3418 // end of my addition
3419 }
3420 }
3421 else {
3422 nr_error_recovery (S);
3423
3424 // Erratum: Another case of my enhancement.
3425 // The flow charts go into state 1 after nr_error_recovery.
3426 // I use state 5 instead if we were oprating in extended (modulo 128) mode.
3427
3428 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
3429 }
3430 }
3431 else {
3432
3433 // RR/RNR command, either P value.
3434 // RR/RNR response, F==0
3435
3436 if (cr == cr_cmd && pf == 1) {
3437 int f = 1;
3438 enquiry_response (S, ready ? frame_type_S_RR : frame_type_S_RNR, f);
3439 }
3440
3441 if (is_good_nr(S,nr)) {
3442
3443 SET_VA(nr);
3444
3445 // Erratum: v1.5 - my addition.
3446 // I noticed that we sometimes got stuck in state 4 and rc crept up slowly even though
3447 // we received RR frames with N(R) values indicating that the other side received everything
3448 // that we sent. Eventually rc could reach the limit and we would get an error.
3449 // If we are in state 4, and other guy ack'ed last I frame we sent, transition to state 3.
3450 // The same thing was done for receving I frames after check_i_frame_ackd.
3451
3452 // Thought: Could we simply call check_i_frame_ackd, for consistency, rather than only setting V(A)?
3453
3454 if (cr == cr_res && pf == 0) {
3455
3456 if (S->vs == S->va) { // all caught up with ack from other guy.
3457 STOP_T1;
3458 select_t1_value (S);
3459 START_T3;
3460 SET_RC(0);
3461 enter_new_state (S, state_3_connected, __func__, __LINE__);
3462 }
3463 }
3464 }
3465 else {
3466 nr_error_recovery (S);
3467 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
3468 }
3469 }
3470 break;
3471 }
3472
3473 } /* end rr_rnr_frame */
3474
3475
3476
3477 /*------------------------------------------------------------------------------
3478 *
3479 * Name: rej_frame
3480 *
3481 * Purpose: Process REJ Frame.
3482 *
3483 * Inputs: S - Data Link State Machine.
3484 * cr - Is this command or response?
3485 * pf - Poll/Final bit.
3486 * nr - N(R) from the frame.
3487 *
3488 * Description: 4.3.2.2. Receive Not Ready (RNR) Command and Response
3489 *
3490 * ... The RNR condition is cleared by the sending of a UA, RR, REJ or SABM(E) frame. ...
3491 *
3492 *
3493 * 4.3.2.3. Reject (REJ) Command and Response
3494 *
3495 * The reject frame requests retransmission of I frames starting with N(R). Any frames sent with a sequence
3496 * number of N(R)-1 or less are acknowledged. Additional I frames which may exist may be appended to the
3497 * retransmission of the N(R) frame.
3498 * Only one reject frame condition is allowed in each direction at a time. The reject condition is cleared by the
3499 * proper reception of I frames up to the I frame that caused the reject condition to be initiated.
3500 * The status of the TNC at the other end of the link is requested by sending a REJ command frame with the P bit
3501 * set to one.
3502 *
3503 * 4.4.3. Reject (REJ) Recovery
3504 *
3505 * The REJ frame requests a retransmission of I frames following the detection of a N(S) sequence error. Only
3506 * one outstanding "sent REJ" condition is allowed at a time. This condition is cleared when the requested I frame
3507 * has been received.
3508 * A TNC receiving the REJ command clears the condition by resending all outstanding I frames (up to the
3509 * window size), starting with the frame indicated in N(R) of the REJ frame.
3510 *
3511 *
3512 * 4.4.5.1. T1 Timer Recovery
3513 *
3514 * If a transmission error causes a TNC to fail to receive (or to receive and discard) a single I frame, or the last I
3515 * frame in a sequence of I frames, then the TNC does not detect a send-sequence-number error and consequently
3516 * does not transmit a REJ/SREJ. The TNC that transmitted the unacknowledged I frame(s) following the completion
3517 * of timeout period T1, takes appropriate recovery action to determine when I frame retransmission as described
3518 * in Section 6.4.10 should begin. This condition is cleared by the reception of an acknowledgement for the sent
3519 * frame(s), or by the link being reset.
3520 *
3521 * 6.2. Poll/Final (P/F) Bit Procedures
3522 *
3523 * The response frame returned by a TNC depends on the previous command received, as described in the
3524 * following paragraphs.
3525 * ...
3526 *
3527 * The next response frame returned to an I frame with the P bit set to "1", received during the information5
3528 * transfer state, is an RR, RNR or REJ response with the F bit set to "1".
3529 *
3530 * The next response frame returned to a supervisory command frame with the P bit set to "1", received during
3531 * the information transfer state, is an RR, RNR or REJ response frame with the F bit set to "1".
3532 * ...
3533 *
3534 * The P bit is used in conjunction with the timeout recovery condition discussed in Section 4.5.5.
3535 * When not used, the P/F bit is set to "0".
3536 *
3537 * 6.4.4.1. Implicit Reject (REJ)
3538 *
3539 * When an I frame is received with a correct FCS but its send sequence number N(S) does not match the current
3540 * receiver's receive state variable, the frame is discarded. A REJ frame is sent with a receive sequence number
3541 * equal to one higher than the last correctly received I frame if an uncleared N(S) sequence error condition has not
3542 * been previously established. The received state variable and poll bit of the discarded frame is checked and acted
3543 * upon, if necessary.
3544 * This mode requires no frame queueing and frame resequencing at the receiver. However, because the mode
3545 * requires transmission of frames that may not be in error, its throughput is not as high as selective reject. This
3546 * mode is ineffective on systems with long round-trip delays and high data rates.
3547 *
3548 * 6.4.7. Receiving REJ
3549 *
3550 * After receiving a REJ frame, the transmitting TNC sets its send state variable to the same value as the REJ
3551 * frame's received sequence number in the control field. The TNC then retransmits any I frame(s) outstanding at
3552 * the next available opportunity in accordance with the following:
3553 *
3554 * a) If the TNC is not transmitting at the time and the channel is open, the TNC may begin retransmission of the
3555 * I frame(s) immediately.
3556 * b) If the TNC is operating on a full-duplex channel transmitting a UI or S frame when it receives a REJ frame,
3557 * it may finish sending the UI or S frame and then retransmit the I frame(s).
3558 * c) If the TNC is operating in a full-duplex channel transmitting another I frame when it receives a REJ frame,
3559 * it may abort the I frame it was sending and start retransmission of the requested I frames immediately.
3560 * d) The TNC may send just the one I frame outstanding, or it may send more than the one indicated if more I
3561 * frames followed the first unacknowledged frame, provided that the total to be sent does not exceed the flowcontrol
3562 * window (k frames).
3563 * If the TNC receives a REJ frame with the poll bit set, it responds with either an RR or RNR frame with the
3564 * final bit set before retransmitting the outstanding I frame(s).
3565 *
3566 *------------------------------------------------------------------------------*/
3567
rej_frame(ax25_dlsm_t * S,cmdres_t cr,int pf,int nr)3568 static void rej_frame (ax25_dlsm_t *S, cmdres_t cr, int pf, int nr)
3569 {
3570
3571 switch (S->state) {
3572
3573 case state_0_disconnected:
3574
3575 // states 0 and 2 are very similar with one tiny little difference.
3576
3577 if (cr == cr_cmd) {
3578 cmdres_t r = cr_res; // DM response with F taken from P.
3579 int f = pf;
3580 int nopid = 0; // PID is only for I and UI.
3581
3582 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, r, frame_type_U_DM, f, nopid, NULL, 0);
3583 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
3584 }
3585 break;
3586
3587 case state_1_awaiting_connection:
3588 case state_5_awaiting_v22_connection:
3589 // Do nothing.
3590 break;
3591
3592 case state_2_awaiting_release:
3593
3594 if (cr == cr_cmd && pf == 1) {
3595 cmdres_t r = cr_res; // DM response with F = 1.
3596 int f = 1;
3597 int nopid = 0;
3598
3599 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, r, frame_type_U_DM, f, nopid, NULL, 0);
3600 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
3601 }
3602
3603 // Erratum: We have a disagreement here between original and 2006 version.
3604 // RR, RNR, REJ, SREJ responses would fall under "all other primitives."
3605 // In the original, we simply ignore it and stay in state 2.
3606 // The 2006 version, page 94, says go into "1 awaiting connection" state.
3607 // That makes no sense to me.
3608
3609 break;
3610
3611 case state_3_connected:
3612
3613 S->peer_receiver_busy = 0;
3614
3615 // Receipt of the REJ "frame" (either command or response) causes us to
3616 // start resending I frames at the specified number.
3617
3618 // I think there are 3 possibilities here:
3619 // Response is used when incoming I frame processing detects one is missing.
3620 // In this case, F is copied from the I frame P bit. I don't think we care here.
3621 // Command with P=1 is used during timeout recovery.
3622 // The rule is that we are supposed to send a response with F=1 for I, RR, RNR, or REJ with P=1.
3623
3624 check_need_for_response (S, frame_type_S_REJ, cr, pf);
3625
3626 if (is_good_nr(S,nr)) {
3627 SET_VA(nr);
3628 STOP_T1;
3629 STOP_T3;
3630 select_t1_value(S);
3631
3632 invoke_retransmission (S, nr);
3633
3634 // my addition
3635 // Erratum: We sent I frame(s) and want to timeout if no ack comes back.
3636 // We also sent N(R) so no need for extra RR at the end only for that.
3637
3638 // We ran into cases where I frame(s) would be resent but lost.
3639 // T1 was stopped so we just waited and waited and waited instead of trying again.
3640 // I added the following after each invoke_retransmission.
3641 // This seems clearer than hiding the timer stuff inside of it.
3642
3643 // T3 is already stopped.
3644 START_T1;
3645 S->acknowledge_pending = 0;
3646 }
3647 else {
3648 nr_error_recovery (S);
3649 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
3650 }
3651 break;
3652
3653 case state_4_timer_recovery:
3654
3655 S->peer_receiver_busy = 0;
3656
3657 if (cr == cr_res && pf == 1) {
3658
3659 STOP_T1;
3660 select_t1_value(S);
3661
3662 if (is_good_nr(S,nr)) {
3663
3664 SET_VA(nr);
3665 if (S->vs == S->va) {
3666 START_T3;
3667 SET_RC(0); // My enhancement. See Erratum note in select_t1_value.
3668 enter_new_state (S, state_3_connected, __func__, __LINE__);
3669 }
3670 else {
3671 invoke_retransmission (S, nr);
3672 // my addition.
3673 // Erratum: We sent I frame(s) and want to timeout if no ack comes back.
3674 // We also sent N(R) so no need for extra RR at the end only for that.
3675
3676 STOP_T3;
3677 START_T1;
3678 S->acknowledge_pending = 0;
3679 }
3680 }
3681 else {
3682 nr_error_recovery (S);
3683 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
3684 }
3685 }
3686 else {
3687 if (cr == cr_cmd && pf == 1) {
3688 int f = 1;
3689 enquiry_response (S, frame_type_S_REJ, f);
3690 }
3691
3692 if (is_good_nr(S,nr)) {
3693
3694 SET_VA(nr);
3695
3696 if (S->vs != S->va) {
3697 // Observation: RR/RNR state 4 is identical but it doesn't have invoke_retransmission here.
3698 invoke_retransmission (S, nr);
3699 // my addition.
3700 // Erratum: We sent I frame(s) and want to timeout if no ack comes back.
3701 // We also sent N(R) so no need for extra RR at the end only for that.
3702
3703 STOP_T3;
3704 START_T1;
3705 S->acknowledge_pending = 0;
3706 }
3707
3708 }
3709 else {
3710 nr_error_recovery (S);
3711 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
3712 }
3713 }
3714 break;
3715 }
3716
3717 } /* end rej_frame */
3718
3719
3720 /*------------------------------------------------------------------------------
3721 *
3722 * Name: srej_frame
3723 *
3724 * Purpose: Process SREJ Response.
3725 *
3726 * Inputs: S - Data Link State Machine.
3727 * cr - Is this command or response?
3728 * f - Final bit. When set, it is ack-ing up thru N(R)-1
3729 * nr - N(R) from the frame. Peer has asked for a resend of I frame with this N(S).
3730 * info - Information field, used only for Multi-SREJ
3731 * info_len - Information field length, bytes.
3732 *
3733 * Description: 4.3.2.4. Selective Reject (SREJ) Command and Response
3734 *
3735 * The selective reject, SREJ, frame is used by the receiving TNC to request retransmission of the single I frame
3736 * numbered N(R). If the P/F bit in the SREJ frame is set to "1", then I frames numbered up to N(R)-1 inclusive are
3737 * considered as acknowledged. However, if the P/F bit in the SREJ frame is set to "0", then the N(R) of the SREJ
3738 * frame does not indicate acknowledgement of I frames.
3739 *
3740 * Each SREJ exception condition is cleared (reset) upon receipt of the I frame with an N(S) equal to the N(R)
3741 * of the SREJ frame.
3742 *
3743 * A receiving TNC may transmit one or more SREJ frames, each containing a different N(R) with the P bit set
3744 * to "0", before one or more earlier SREJ exception conditions have been cleared. However, a SREJ is not
3745 * transmitted if an earlier REJ exception condition has not been cleared as indicated in Section 4.5.4. (To do so
3746 * would request retransmission of an I frame that would be retransmitted by the REJ operation.) Likewise, a REJ
3747 * frame is not transmitted if one or more earlier SREJ exception conditions have not been cleared as indicated in
3748 * Section 4.5.4.
3749 *
3750 * I frames transmitted following the I frame indicated by the SREJ frame are not retransmitted as the result of
3751 * receiving a SREJ frame. Additional I frames awaiting initial transmission may be transmitted following the
3752 * retransmission of the specific I frame requested by the SREJ frame.
3753 *
3754 * Erratum: The section above always refers to SREJ "frames." There doesn't seem to be any clue about when
3755 * command vs. response would be used. When we look in the flow charts, we see that we generate only
3756 * responses but the code is there to process command and response slightly differently.
3757 *
3758 * Description: 4.4.4. Selective Reject (SREJ) Recovery
3759 *
3760 * The SREJ command/response initiates more-efficient error recovery by requesting the retransmission of a
3761 * single I frame following the detection of a sequence error. This is an advancement over the earlier versions in
3762 * which the requested I frame was retransmitted togther with all additional I frames subsequently transmitted and
3763 * successfully received.
3764 *
3765 * When a TNC sends one or more SREJ commands, each with the P bit set to "0" or "1", or one or more SREJ
3766 * responses, each with the F bit set to "0", and the "sent SREJ" conditions are not cleared when the TNC is ready
3767 * to issue the next response frame with the F bit set to "1", the TNC sends a SREJ response with the F bit set to "1",
3768 * with the same N(R) as the oldest unresolved SREJ frame.
3769 *
3770 * Because an I or S format frame with the F bit set to "1" can cause checkpoint retransmission, a TNC does not
3771 * send SREJ frames until it receives at least one in-sequence I frame, or it perceives by timeout that the checkpoint
3772 * retransmission will not be initiated at the remote TNC.
3773 *
3774 * With respect to each direction of transmission on the data link, one or more "sent SREJ" exception conditions
3775 * from a TNC to another TNC may be established at a time. A "sent SREJ" exception condition is cleared when
3776 * the requested I frame is received.
3777 *
3778 * The SREJ frame may be repeated when a TNC perceives by timeout that a requested I frame will not be
3779 * received, because either the requested I frame or the SREJ frame was in error or lost.
3780 *
3781 * When appropriate, a TNC receiving one or more SREJ frames initiates retransmission of the individual I
3782 * frames indicated by the N(R) contained in each SREJ frame. After having retransmitted the above frames, new
3783 * I frames are transmitted later if they become available.
3784 *
3785 * When a TNC receives and acts on one or more SREJ commands, each with the P bit set to "0", or an SREJ
3786 * command with the P bit set to "1", or one or more SREJ responses each with the F bit set to "0", it disables any
3787 * action on the next SREJ response frame if that SREJ frame has the F bit set to "1" and has the same N(R) (i.e.,
3788 * the same value and the same numbering cycle) as a previously actioned SREJ frame, and if the resultant
3789 * retransmission was made following the transmission of the P bit set to a "1".
3790 * When the SREJ mechanism is used, the receiving station retains correctly-received I frames and delivers
3791 * them to the higher layer in sequence number order.
3792 *
3793 *
3794 * 6.4.4.2. Selective Reject (SREJ)
3795 *
3796 * When an I frame is received with a correct FCS but its send sequence number N(S) does not match the current
3797 * receiver's receive state variable, the frame is retained. SREJ frames are sent with a receive sequence number
3798 * equal to the value N(R) of the missing frame, and P=1 if an uncleared SREJ condition has not been previously
3799 * established. If an SREJ condition is already pending, an SREJ will be sent with P=0. The received state variable
3800 * and poll bit of the received frame are checked and acted upon, if necessary.
3801 *
3802 * This mode requires frame queueing and frame resequencing at the receiver. The holding of frames can
3803 * consume precious buffer space, especially if the user device has limited memory available and several active
3804 * links are operational.
3805 *
3806 *
3807 * 6.4.4.3. Selective Reject-Reject (SREJ/REJ)
3808 *
3809 * When an I frame is received with a correct FCS but its send sequence number N(S) does not match the current
3810 * receiver's receive state variable, and if N(S) indicates 2 or more frames are missing, a REJ frame is transmitted.
3811 * All subsequently received frames are discarded until the lost frame is correctly received. If only one frame is
3812 * missing, a SREJ frame is sent with a receive sequence number equal to the value N(R) of the missing frame. The
3813 * received state variable and poll bit of the received frame are checked and acted upon. If another frame error
3814 * occurs prior to recovery of the SREJ condition, the receiver saves all frames received after the first errored frame
3815 * and discards frames received after the second errored frame until the first errored frame is recovered. Then, a
3816 * REJ is issued to recover the second errored frame and all subsequent discarded frames.
3817 *
3818 * X.25: States that SREJ is only response. I'm following that and it simplifies matters.
3819 *
3820 * X.25 2.4.6.6.1 & 2.4.6.6.2 make a distinction between F being 0 or 1 besides copying N(R) into V(A).
3821 * They talk about sending a poll under some conditions.
3822 * We don't do that here. It seems to work reliably so leave well enough alone.
3823 *
3824 *------------------------------------------------------------------------------*/
3825
3826 static int resend_for_srej (ax25_dlsm_t *S, int nr, unsigned char *info, int info_len);
3827
srej_frame(ax25_dlsm_t * S,cmdres_t cr,int f,int nr,unsigned char * info,int info_len)3828 static void srej_frame (ax25_dlsm_t *S, cmdres_t cr, int f, int nr, unsigned char *info, int info_len)
3829 {
3830
3831 switch (S->state) {
3832
3833 case state_0_disconnected:
3834
3835 break;
3836
3837 case state_1_awaiting_connection:
3838 case state_5_awaiting_v22_connection:
3839 // Do nothing.
3840
3841 // Erratum: The original spec said stay in same state. (Seems correct.)
3842 // 2006 revision shows state 5 transitioning into 1. I think that is wrong.
3843 // probably a cut-n-paste from state 1 to 5 and that part not updated.
3844 break;
3845
3846 case state_2_awaiting_release:
3847
3848 // Erratum: Flow chart says send DM(F=1) for "I, RR, RNR, REJ, SREJ commands" and P=1.
3849 // It is wrong for two reasons.
3850 // If SREJ was a command, the P flag has a different meaning than the other Supervisory commands.
3851 // It means ack reception of frames up thru N(R)-1; it is not a poll to get a response.
3852
3853 // Based on X.25, I don't think SREJ can be a command.
3854 // It should say, "I, RR, RNR, REJ commands"
3855
3856 // Erratum: We have a disagreement here between original and 2006 version.
3857 // RR, RNR, REJ, SREJ responses would fall under "all other primitives."
3858 // In the original, we simply ignore it and stay in state 2.
3859 // The 2006 version, page 94, says go into "1 awaiting connection" state.
3860 // That makes no sense to me.
3861
3862 break;
3863
3864 case state_3_connected:
3865
3866 S->peer_receiver_busy = 0;
3867
3868 // Erratum: Flow chart has "check need for response here."
3869
3870 // check_need_for_response() does the following:
3871 // - for command & P=1, send RR or RNR.
3872 // - for response & F=1, error A.
3873
3874 // SREJ can only be a response. We don't want to produce an error when F=1.
3875
3876 if (is_good_nr(S,nr)) {
3877
3878 if (f) {
3879 SET_VA(nr);
3880 }
3881 STOP_T1;
3882 START_T3;
3883 select_t1_value(S);
3884
3885
3886 int num_resent = resend_for_srej (S, nr, info, info_len);
3887 if (num_resent) {
3888
3889 // my addition
3890 // Erratum: We sent I frame(s) and want to timeout if no ack comes back.
3891 // We also sent N(R), from V(R), so no need for extra RR at the end only for that.
3892
3893 // We would sometimes end up in a situation where T1 was stopped on
3894 // both ends and everyone would wait for the other guy to timeout and do something.
3895 // My solution was to Start T1 after every place we send an I frame if not already there.
3896
3897 STOP_T3;
3898 START_T1;
3899 S->acknowledge_pending = 0;
3900 }
3901 // keep same state.
3902 }
3903 else {
3904 nr_error_recovery (S);
3905 // Erratum? Flow chart shows state 1 but that would not be appropriate if modulo is 128.
3906 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
3907 }
3908 break;
3909
3910 case state_4_timer_recovery:
3911
3912 if (s_debug_timers) {
3913 text_color_set(DW_COLOR_ERROR);
3914 dw_printf ("state 4 timer recovery, %s %d nr=%d, f=%d\n", __func__, __LINE__, nr, f);
3915 }
3916
3917 S->peer_receiver_busy = 0;
3918
3919 // Erratum: Original Flow chart has "check need for response here."
3920 // The 2006 version correctly removed it.
3921
3922 // check_need_for_response() does the following:
3923 // - for command & P=1, send RR or RNR.
3924 // - for response & F=1, error A.
3925
3926 // SREJ can only be a response. We don't want to produce an error when F=1.
3927
3928
3929 // The flow chart splits into two paths for command/response with a lot of duplication.
3930 // Command path has been omitted because SREJ can only be response.
3931
3932 STOP_T1;
3933 select_t1_value(S);
3934
3935 if (is_good_nr(S,nr)) {
3936
3937 if (f) { // f=1 means ack up thru previous sequence.
3938 // Erratum: 2006 version tests "P". Original has "F."
3939 SET_VA(nr);
3940
3941 if (s_debug_timers) {
3942 text_color_set(DW_COLOR_ERROR);
3943 dw_printf ("state 4 timer recovery, %s %d set v(a)= %d\n", __func__, __LINE__, S->va);
3944 }
3945 }
3946
3947 if (S->vs == S->va) { // ACKs all caught up. Back to state 3.
3948
3949 // Erratum: I think this is unreachable.
3950 // If the other side is asking for I frame with sequence X, it must have
3951 // received X+1 or later. That means my V(S) must be X+2 or greater.
3952 // So, I don't think we can ever have V(S) == V(A) here.
3953 // If we were to remove the 'if' test and true part, case 4 would then
3954 // be exactly the same as state 4. We need to rely on RR to get us
3955 // back to state 3.
3956
3957 START_T3;
3958 SET_RC(0); // My enhancement. See Erratum note in select_t1_value.
3959 enter_new_state (S, state_3_connected, __func__, __LINE__);
3960
3961 // text_color_set(DW_COLOR_ERROR);
3962 // dw_printf ("state 4 timer recovery, go to state 3 \n");
3963 }
3964 else {
3965
3966 // Erratum: Difference between two AX.25 revisions.
3967
3968 #if 1 // This is from the original protocol spec.
3969 // Resend I frame with N(S) equal to the N(R) in the SREJ.
3970
3971 //text_color_set(DW_COLOR_ERROR);
3972 //dw_printf ("state 4 timer recovery, send requested frame(s) \n");
3973
3974 int num_resent = resend_for_srej (S, nr, info, info_len);
3975 if (num_resent) {
3976 // my addition
3977 // Erratum: We sent I frame(s) and want to timeout if no ack comes back.
3978 // We also sent N(R), from V(R), so no need for extra RR at the end only for that.
3979
3980 // We would sometimes end up in a situation where T1 was stopped on
3981 // both ends and everyone would wait for the other guy to timeout and do something.
3982 // My solution was to Start T1 after every place we send an I frame if not already there.
3983
3984 STOP_T3;
3985 START_T1;
3986 S->acknowledge_pending = 0;
3987 }
3988 #else // Erratum! This is from the 2006 revision.
3989 // We should resend only the single requested I frame.
3990 // I think there was a cut-n-paste from the REJ flow chart and this particular place did not get changed.
3991
3992 invoke_retransmission(S);
3993 #endif
3994 }
3995 }
3996 else {
3997 nr_error_recovery (S);
3998 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
3999 }
4000 break;
4001 }
4002
4003 } /* end srej_frame */
4004
4005 /*------------------------------------------------------------------------------
4006 *
4007 * Name: resend_for_srej
4008 *
4009 * Purpose: Resend the I frame(s) specified in SREJ response.
4010 *
4011 * Inputs: S - Data Link State Machine.
4012 * nr - N(R) from the frame. Peer has asked for a resend of I frame with this N(S).
4013 * info - Information field, might contain additional sequence numbers for Multi-SREJ.
4014 * info_len - Information field length, bytes.
4015 *
4016 * Returns: Number of frames sent. Should be at least one.
4017 *
4018 * Description: Simply resend requested frame(s).
4019 * The calling context will worry about the F bit and other state stuff.
4020 *
4021 *------------------------------------------------------------------------------*/
4022
resend_for_srej(ax25_dlsm_t * S,int nr,unsigned char * info,int info_len)4023 static int resend_for_srej (ax25_dlsm_t *S, int nr, unsigned char *info, int info_len)
4024 {
4025 cmdres_t cr = cr_cmd;
4026 int i_frame_nr = S->vr;
4027 int i_frame_ns = nr;
4028 int p = 0;
4029 int num_resent = 0;
4030
4031 // Resend I frame with N(S) equal to the N(R) in the SREJ.
4032 // Additional sequence numbers can be in optional information part.
4033
4034 cdata_t *txdata = S->txdata_by_ns[i_frame_ns];
4035
4036 if (txdata != NULL) {
4037 packet_t pp = ax25_i_frame (S->addrs, S->num_addr, cr, S->modulo, i_frame_nr, i_frame_ns, p, txdata->pid, (unsigned char *)(txdata->data), txdata->len);
4038 // dw_printf ("calling lm_data_request for I frame, %s line %d\n", __func__, __LINE__);
4039 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4040 num_resent++;
4041 }
4042 else {
4043 text_color_set(DW_COLOR_ERROR);
4044 dw_printf ("Stream %d: INTERNAL ERROR for SREJ. I frame for N(S)=%d is not available.\n", S->stream_id, i_frame_ns);
4045 }
4046
4047 // Multi-SREJ if there is an information part.
4048
4049 int j;
4050 for (j = 0; j < info_len; j++) {
4051
4052 // We can have a single sequence number like this:
4053 // xxx00000 (mod 8)
4054 // xxxxxxx0 (mod 128)
4055 // or we can have span (mod 128 only) like this, with the first and last:
4056 // xxxxxxx1
4057 // xxxxxxx1
4058 //
4059 // Note that the sequence number is shifted left by one
4060 // and if the LSB is set, there should be two adjacent bytes
4061 // with it set.
4062
4063 if (S->modulo == 8) {
4064 i_frame_ns = (info[j] >> 5) & 0x07; // no provision for span.
4065 }
4066 else {
4067 i_frame_ns = (info[j] >> 1) & 0x7f; // TODO: test LSB and possible loop here.
4068 }
4069
4070 txdata = S->txdata_by_ns[i_frame_ns];
4071 if (txdata != NULL) {
4072 packet_t pp = ax25_i_frame (S->addrs, S->num_addr, cr, S->modulo, i_frame_nr, i_frame_ns, p, txdata->pid, (unsigned char *)(txdata->data), txdata->len);
4073 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4074 num_resent++;
4075 }
4076 else {
4077 text_color_set(DW_COLOR_ERROR);
4078 dw_printf ("Stream %d: INTERNAL ERROR for Multi-SREJ. I frame for N(S)=%d is not available.\n", S->stream_id, i_frame_ns);
4079 }
4080 }
4081 return (num_resent);
4082
4083 } /* end resend_for_srej */
4084
4085
4086
4087
4088 /*------------------------------------------------------------------------------
4089 *
4090 * Name: sabm_e_frame
4091 *
4092 * Purpose: Process SABM or SABME Frame.
4093 *
4094 * Inputs: S - Data Link State Machine.
4095 *
4096 * extended - True for SABME. False for SABM.
4097 *
4098 * p - Poll bit. TODO: What does it mean in this case?
4099 *
4100 * Description: This is a request, from the other end, to establish a connection.
4101 *
4102 * 4.3.3.1. Set Asynchronous Balanced Mode (SABM) Command
4103 *
4104 * The SABM command places two Terminal Node Comtrollers (TNC) in the asynchronous balanced mode
4105 * (modulo 8). This a balanced mode of operation in which both devices are treated as equals or peers.
4106 *
4107 * Information fields are not allowed in SABM commands. Any outstanding I frames left when the SABM
4108 * command is issued remain unacknowledged.
4109 *
4110 * The TNC confirms reception and acceptance of a SABM command by sending a UA response frame at the
4111 * earliest opportunity. If the TNC is not capable of accepting a SABM command, it responds with a DM frame if
4112 * possible.
4113 *
4114 * 4.3.3.2. Set Asynchronous Balanced Mode Extended (SABME) Command
4115 *
4116 * The SABME command places two TNCs in the asynchronous balanced mode extended (modulo 128). This
4117 * is a balanced mode of operation in which both devices are treated as equals or peers.
4118 * Information fields are not allowed in SABME commands. Any outstanding I frames left when the SABME
4119 * command is issued remains unacknowledged.
4120 *
4121 * The TNC confirms reception and acceptance of a SABME command by sending a UA response frame at the
4122 * earliest opportunity. If the TNC is not capable of accepting a SABME command, it responds with a DM frame.
4123 *
4124 * A TNC that uses a version of AX.25 prior to v2.2 responds with a FRMR. ** (see note below)
4125 *
4126 *
4127 * Note: The KPC-3+, which does not appear to support v2.2, responds with a DM.
4128 * The 2.0 spec, section 2.3.4.3.5, states, "While a DXE is in the disconnected mode, it will respond
4129 * to any command other than a SABM or UI frame with a DM response with the P/F bit set to 1."
4130 * I think it is a bug in the KPC but I can see how someone might implement it that way.
4131 * However, another place says FRMR is sent for any unrecognized frame type. That would seem to take priority.
4132 *
4133 *------------------------------------------------------------------------------*/
4134
sabm_e_frame(ax25_dlsm_t * S,int extended,int p)4135 static void sabm_e_frame (ax25_dlsm_t *S, int extended, int p)
4136 {
4137
4138 switch (S->state) {
4139
4140 case state_0_disconnected:
4141
4142 // Flow chart has decision: "Able to establish?"
4143 // I think this means, are we willing to accept connection requests?
4144 // We are always willing to accept connections.
4145 // Of course, we wouldn't get this far if local callsigns were not "registered."
4146
4147 if (extended) {
4148 set_version_2_2 (S);
4149 }
4150 else {
4151 set_version_2_0 (S);
4152 }
4153
4154 cmdres_t res = cr_res;
4155 int f = p; // I don't understand the purpose of "P" in SABM/SABME
4156 // but we dutifully copy it into "F" for the UA response.
4157 int nopid = 0; // PID is only for I and UI.
4158
4159 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_UA, f, nopid, NULL, 0);
4160 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4161
4162 clear_exception_conditions (S);
4163
4164 SET_VS(0);
4165 SET_VA(0);
4166 SET_VR(0);
4167
4168 text_color_set(DW_COLOR_INFO);
4169 dw_printf ("Stream %d: Connected to %s. (%s)\n", S->stream_id, S->addrs[PEERCALL], extended ? "v2.2" : "v2.0");
4170
4171 // dl connect indication - inform the client app.
4172 int incoming = 1;
4173 server_link_established (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], incoming);
4174
4175 INIT_T1V_SRT;
4176
4177 START_T3;
4178 SET_RC(0); // My enhancement. See Erratum note in select_t1_value.
4179 enter_new_state (S, state_3_connected, __func__, __LINE__);
4180 break;
4181
4182 case state_1_awaiting_connection:
4183
4184 // Don't combine with state 5. They are slightly different.
4185
4186 if (extended) { // SABME - respond with DM, enter state 5.
4187 cmdres_t res = cr_res;
4188 int f = p;
4189 int nopid = 0;
4190
4191 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_DM, f, nopid, NULL, 0);
4192 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4193 enter_new_state (S, state_5_awaiting_v22_connection, __func__, __LINE__);
4194 }
4195 else { // SABM - respond with UA.
4196
4197 // Erratum! 2006 version shows SAMBE twice for state 1.
4198 // First one should be SABM in last page of Figure C4.2
4199 // Original appears to be correct.
4200
4201 cmdres_t res = cr_res;
4202 int f = p;
4203 int nopid = 0;
4204
4205 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_UA, f, nopid, NULL, 0);
4206 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4207 // stay in state 1.
4208 }
4209 break;
4210
4211 case state_5_awaiting_v22_connection:
4212
4213 if (extended) { // SABME - respond with UA
4214 cmdres_t res = cr_res;
4215 int f = p;
4216 int nopid = 0;
4217
4218 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_UA, f, nopid, NULL, 0);
4219 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4220 // stay in state 5
4221 }
4222 else { // SABM, respond with UA, enter state 1
4223 cmdres_t res = cr_res;
4224 int f = p;
4225 int nopid = 0;
4226
4227 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_UA, f, nopid, NULL, 0);
4228 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4229 enter_new_state (S, state_1_awaiting_connection, __func__, __LINE__);
4230 }
4231 break;
4232
4233 case state_2_awaiting_release:
4234
4235 // Erratum! Flow charts don't list SABME for state 2.
4236 // Probably just want to treat it the same as SABM here.
4237
4238 {
4239 cmdres_t res = cr_res;
4240 int f = p;
4241 int nopid = 0;
4242
4243 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_DM, f, nopid, NULL, 0);
4244 lm_data_request (S->chan, TQ_PRIO_0_HI, pp); // expedited
4245 // stay in state 2.
4246 }
4247 break;
4248
4249 case state_3_connected:
4250 case state_4_timer_recovery:
4251
4252 {
4253 cmdres_t res = cr_res;
4254 int f = p;
4255 int nopid = 0;
4256
4257 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_UA, f, nopid, NULL, 0);
4258 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4259
4260 // State 3 & 4 handling are the same except for this one difference.
4261 if (S->state == state_4_timer_recovery) {
4262 if (extended) {
4263 set_version_2_2 (S);
4264 }
4265 else {
4266 set_version_2_0 (S);
4267 }
4268 }
4269
4270 clear_exception_conditions (S);
4271 if (s_debug_protocol_errors) {
4272 text_color_set(DW_COLOR_ERROR);
4273 dw_printf ("Stream %d: AX.25 Protocol Error F: Data Link reset; i.e. SABM(e) received in state %d.\n", S->stream_id, S->state);
4274 }
4275 if (S->vs != S->va) {
4276 discard_i_queue (S);
4277 // dl connect indication
4278 int incoming = 1;
4279 server_link_established (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], incoming);
4280 }
4281 STOP_T1;
4282 START_T3;
4283 SET_VS(0);
4284 SET_VA(0);
4285 SET_VR(0);
4286 SET_RC(0); // My enhancement. See Erratum note in select_t1_value.
4287 enter_new_state (S, state_3_connected, __func__, __LINE__);
4288 }
4289 break;
4290 }
4291
4292 } /* end sabm_e_frame */
4293
4294
4295
4296 /*------------------------------------------------------------------------------
4297 *
4298 * Name: disc_frame
4299 *
4300 * Purpose: Process DISC command.
4301 *
4302 * Inputs: S - Data Link State Machine.
4303 * p - Poll bit.
4304 *
4305 * Description: 4.3.3.3. Disconnect (DISC) Command
4306 *
4307 * The DISC command terminates a link session between two stations. An information field is not permitted in
4308 * a DISC command frame.
4309 *
4310 * Prior to acting on the DISC frame, the receiving TNC confirms acceptance of the DISC by issuing a UA
4311 * response frame at its earliest opportunity. The TNC sending the DISC enters the disconnected state when it
4312 * receives the UA response.
4313 *
4314 * Any unacknowledged I frames left when this command is acted upon remain unacknowledged.
4315 *
4316 *
4317 * 6.3.4. Link Disconnection
4318 *
4319 * While in the information-transfer state, either TNC may indicate a request to disconnect the link by transmitting
4320 * a DISC command frame and starting timer T1.
4321 *
4322 * After receiving a valid DISC command, the TNC sends a UA response frame and enters the disconnected
4323 * state. After receiving a UA or DM response to a sent DISC command, the TNC cancels timer T1 and enters the
4324 * disconnected state.
4325 *
4326 * If a UA or DM response is not correctly received before T1 times out, the DISC frame is sent again and T1 is
4327 * restarted. If this happens N2 times, the TNC enters the disconnected state.
4328 *
4329 *------------------------------------------------------------------------------*/
4330
disc_frame(ax25_dlsm_t * S,int p)4331 static void disc_frame (ax25_dlsm_t *S, int p)
4332 {
4333
4334 switch (S->state) {
4335
4336 case state_0_disconnected:
4337 case state_1_awaiting_connection:
4338 case state_5_awaiting_v22_connection:
4339
4340 {
4341 cmdres_t res = cr_res;
4342 int f = p;
4343 int nopid = 0;
4344
4345 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_DM, f, nopid, NULL, 0);
4346 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4347 }
4348 // keep current state, 0, 1, or 5.
4349 break;
4350
4351 case state_2_awaiting_release:
4352
4353 {
4354 cmdres_t res = cr_res;
4355 int f = p;
4356 int nopid = 0;
4357
4358 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_UA, f, nopid, NULL, 0);
4359 lm_data_request (S->chan, TQ_PRIO_0_HI, pp); // expedited
4360 }
4361 // keep current state, 2.
4362 break;
4363
4364 case state_3_connected:
4365 case state_4_timer_recovery:
4366
4367 {
4368 discard_i_queue (S);
4369
4370 cmdres_t res = cr_res;
4371 int f = p;
4372 int nopid = 0;
4373
4374 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_UA, f, nopid, NULL, 0);
4375 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4376
4377 // dl disconnect *indication*
4378 text_color_set(DW_COLOR_INFO);
4379 dw_printf ("Stream %d: Disconnected from %s.\n", S->stream_id, S->addrs[PEERCALL]);
4380 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 0);
4381
4382 STOP_T1;
4383 STOP_T3;
4384 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
4385 }
4386 break;
4387 }
4388
4389 } /* end disc_frame */
4390
4391
4392
4393 /*------------------------------------------------------------------------------
4394 *
4395 * Name: dm_frame
4396 *
4397 * Purpose: Process DM Response Frame.
4398 *
4399 * Inputs: S - Data Link State Machine.
4400 * f - Final bit.
4401 *
4402 * Description: 4.3.3.1. Set Asynchronous Balanced Mode (SABM) Command
4403 *
4404 * The TNC confirms reception and acceptance of a SABM command by sending a UA response frame at the
4405 * earliest opportunity. If the TNC is not capable of accepting a SABM command, it responds with a DM frame if
4406 * possible.
4407 *
4408 * The TNC confirms reception and acceptance of a SABME command by sending a UA response frame at the
4409 * earliest opportunity. If the TNC is not capable of accepting a SABME command, it responds with a DM frame.
4410 *
4411 * A TNC that uses a version of AX.25 prior to v2.2 responds with a FRMR.
4412 * ( I think the KPC-3+ has a bug - it replys with DM - WB2OSZ )
4413 *
4414 * 4.3.3.5. Disconnected Mode (DM) Response
4415 *
4416 * The disconnected mode response is sent whenever a TNC receives a frame other than a SABM(E) or UI
4417 * frame while in a disconnected mode. The disconnected mode response also indicates that the TNC cannot
4418 * accept a connection at the moment. The DM response does not have an information field.
4419 * Whenever a SABM(E) frame is received and it is determined that a connection is not possible, a DM frame is
4420 * sent. This indicates that the called station cannot accept a connection at that time.
4421 * While a TNC is in the disconnected mode, it responds to any command other than a SABM(E) or UI frame
4422 * with a DM response with the P/F bit set to "1".
4423 *
4424 * 4.3.3.6. Unnumbered Information (UI) Frame
4425 *
4426 * A received UI frame with the P bit set causes a response to be transmitted. This response is a DM frame when
4427 * in the disconnected state, or an RR (or RNR, if appropriate) frame in the information transfer state.
4428 *
4429 * 6.3.1. AX.25 Link Connection Establishment
4430 *
4431 * If the distant TNC receives a SABM command and cannot enter the indicated state, it sends a DM frame.
4432 * When the originating TNC receives a DM response to its SABM(E) frame, it cancels its T1 timer and does
4433 * not enter the information-transfer state.
4434 *
4435 * 6.3.4. Link Disconnection
4436 *
4437 * After receiving a valid DISC command, the TNC sends a UA response frame and enters the disconnected
4438 * state. After receiving a UA or DM response to a sent DISC command, the TNC cancels timer T1 and enters the
4439 * disconnected state.
4440 *
4441 * 6.5. Resetting Procedure
4442 *
4443 * If a DM response is received, the TNC enters the disconnected state and stops timer T1. If timer T1 expires
4444 * before a UA or DM response frame is received, the SABM(E) is retransmitted and timer T1 restarted. If timer T1
4445 * expires N2 times, the TNC enters the disconnected state. Any previously existing link conditions are cleared.
4446 * Other commands or responses received by the TNC before completion of the reset procedure are discarded.
4447 *
4448 * Erratum: The flow chart shows the same behavior for states 1 and 5.
4449 * For state 5, I think we should treat DM the same as FRMR.
4450 *
4451 *------------------------------------------------------------------------------*/
4452
4453
dm_frame(ax25_dlsm_t * S,int f)4454 static void dm_frame (ax25_dlsm_t *S, int f)
4455 {
4456 switch (S->state) {
4457
4458 case state_0_disconnected:
4459 // Do nothing.
4460 break;
4461
4462 case state_1_awaiting_connection:
4463
4464 if (f == 1) {
4465 discard_i_queue (S);
4466 // dl disconnect *indication*
4467 text_color_set(DW_COLOR_INFO);
4468 dw_printf ("Stream %d: Disconnected from %s.\n", S->stream_id, S->addrs[PEERCALL]);
4469 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 0);
4470 STOP_T1;
4471 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
4472 }
4473 else {
4474 // keep current state.
4475 }
4476 break;
4477
4478 case state_2_awaiting_release:
4479
4480 if (f == 1) {
4481
4482 // Erratum! Original flow chart, page 91, shows DL-CONNECT confirm.
4483 // It should clearly be DISconnect rather than Connect.
4484
4485 // 2006 has DISCONNECT *Indication*.
4486 // Should it be indication or confirm? Not sure.
4487
4488 // dl disconnect *confirm*
4489 text_color_set(DW_COLOR_INFO);
4490 dw_printf ("Stream %d: Disconnected from %s.\n", S->stream_id, S->addrs[PEERCALL]);
4491 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 0);
4492 STOP_T1;
4493 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
4494 }
4495 else {
4496 // keep current state.
4497 }
4498 break;
4499
4500 case state_3_connected:
4501 case state_4_timer_recovery:
4502
4503 if (s_debug_protocol_errors) {
4504 text_color_set(DW_COLOR_ERROR);
4505 dw_printf ("Stream %d: AX.25 Protocol Error E: DM received in state %d.\n", S->stream_id, S->state);
4506 }
4507 // dl disconnect *indication*
4508 text_color_set(DW_COLOR_INFO);
4509 dw_printf ("Stream %d: Disconnected from %s.\n", S->stream_id, S->addrs[PEERCALL]);
4510 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 0);
4511 discard_i_queue (S);
4512 STOP_T1;
4513 STOP_T3;
4514 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
4515 break;
4516
4517 case state_5_awaiting_v22_connection:
4518
4519 #if 0
4520 // Erratum: The flow chart says we should do this.
4521 // I'm not saying it is wrong. I just found it necessary to change this
4522 // to work around an apparent bug in a popular hardware TNC.
4523
4524 if (f == 1) {
4525 discard_i_queue (S);
4526 // dl disconnect *indication*
4527 text_color_set(DW_COLOR_INFO);
4528 dw_printf ("Stream %d: Disconnected from %s.\n", S->stream_id, S->addrs[PEERCALL]);
4529 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 0);
4530 STOP_T1;
4531 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
4532 }
4533 else {
4534 // keep current state.
4535 }
4536 #else
4537 // Erratum: This is not in original spec. It's copied from the FRMR case.
4538
4539 // I was expecting FRMR to mean the other end did not understand v2.2.
4540 // Experimentation, with KPC-3+, revealed that we get DM instead.
4541 // One part of the the 2.0 spec sort of indicates this might be intentional.
4542 // But another part more clearly states it should be FRMR.
4543
4544 // At first I thought it was an error in the protocol spec.
4545 // Later, I tend to believe it was just implemented wrong in the KPC-3+.
4546
4547 if (f == 1) {
4548 text_color_set(DW_COLOR_INFO);
4549 dw_printf ("%s doesn't understand AX.25 v2.2. Trying v2.0 ...\n", S->addrs[PEERCALL]);
4550
4551 INIT_T1V_SRT;
4552
4553 // Erratum: page 105. We are in state 5 so I think that means modulo is 128,
4554 // k is probably something > 7, and selective reject is enabled.
4555 // At the end of this we go to state 1.
4556 // It seems to me, that we really want to set version 2.0 in here so we have
4557 // compatible settings.
4558
4559 set_version_2_0 (S);
4560
4561 establish_data_link (S);
4562 S->layer_3_initiated = 1;
4563 enter_new_state (S, state_1_awaiting_connection, __func__, __LINE__);
4564 }
4565 #endif
4566 break;
4567 }
4568
4569 } /* end dm_frame */
4570
4571
4572
4573
4574 /*------------------------------------------------------------------------------
4575 *
4576 * Name: UA_frame
4577 *
4578 * Purpose: Process UA Response Frame.
4579 *
4580 * Inputs: S - Data Link State Machine.
4581 * f - Final bit.
4582 *
4583 * Description: 4.3.3.4. Unnumbered Acknowledge (UA) Response
4584 *
4585 * The UA response frame acknowledges the reception and acceptance of a SABM(E) or DISC command
4586 * frame. A received command is not actually processed until the UA response frame is sent. Information fields are
4587 * not permitted in a UA frame.
4588 *
4589 * 4.4.1. TNC Busy Condition
4590 *
4591 * When a TNC is temporarily unable to receive I frames (e.g., when receive buffers are full), it sends a Receive
4592 * Not Ready (RNR) frame. This informs the sending TNC that the receiving TNC cannot handle any more I
4593 * frames at the moment. This receiving TNC clears this condition by the sending a UA, RR, REJ or SABM(E)
4594 * command frame.
4595 *
4596 * 6.2. Poll/Final (P/F) Bit Procedures
4597 *
4598 * The response frame returned by a TNC depends on the previous command received, as described in the
4599 * following paragraphs.
4600 * The next response frame returned by the TNC to a SABM(E) or DISC command with the P bit set to "1" is a
4601 * UA or DM response with the F bit set to "1".
4602 *
4603 * 6.3.1. AX.25 Link Connection Establishment
4604 *
4605 * To connect to a distant TNC, the originating TNC sends a SABM command frame to the distant TNC and
4606 * starts its T1 timer. If the distant TNC exists and accepts the connect request, it responds with a UA response
4607 * frame and resets all of its internal state variables (V(S), V(A) and V(R)). Reception of the UA response frame by
4608 * the originating TNC causes it to cancel the T1 timer and set its internal state variables to "0".
4609 *
4610 * 6.5. Resetting Procedure
4611 *
4612 * A TNC initiates a reset procedure whenever it receives an unexpected UA response frame, or after receipt of
4613 * a FRMR frame from a TNC using an older version of the protocol.
4614 *
4615 *------------------------------------------------------------------------------*/
4616
ua_frame(ax25_dlsm_t * S,int f)4617 static void ua_frame (ax25_dlsm_t *S, int f)
4618 {
4619 switch (S->state) {
4620
4621 case state_0_disconnected:
4622
4623 // Erratum: flow chart says errors C and D. Neither one really makes sense.
4624 // "Unexpected UA in states 3, 4, or 5." We are in state 0 here.
4625 // "UA received without F=1 when SABM or DISC was sent P=1."
4626
4627 if (s_debug_protocol_errors) {
4628 text_color_set(DW_COLOR_ERROR);
4629 dw_printf ("Stream %d: AX.25 Protocol Error C: Unexpected UA in state %d.\n", S->stream_id, S->state);
4630 }
4631 break;
4632
4633 case state_1_awaiting_connection:
4634 case state_5_awaiting_v22_connection:
4635
4636 if (f == 1) {
4637 if (S->layer_3_initiated) {
4638 text_color_set(DW_COLOR_INFO);
4639 // TODO: add via if apppropriate.
4640 dw_printf ("Stream %d: Connected to %s. (%s)\n", S->stream_id, S->addrs[PEERCALL], S->state == state_5_awaiting_v22_connection ? "v2.2" : "v2.0");
4641 // There is a subtle difference here between connect confirm and indication.
4642 // connect *confirm* means "has been made"
4643 // The AGW API distinguishes between incoming (initiated by other station) and
4644 // outgoing (initiated by me) connections.
4645 int incoming = 0;
4646 server_link_established (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], incoming);
4647 }
4648 else if (S->vs != S->va) {
4649 #if 1
4650 // Erratum: 2006 version has this.
4651
4652 INIT_T1V_SRT;
4653
4654 START_T3; // Erratum: Rather pointless because we immediately stop it below.
4655 // In the original flow chart, that is.
4656 // I think there is an error as explained below.
4657 // In my version this is still pointless because we start T3 later.
4658
4659 #else
4660 // Erratum: Original version has this.
4661 // I think this could be harmful.
4662 // The client app might have been impatient and started sending
4663 // information already. I don't see why we would want to discard it.
4664
4665 discard_i_queue (S);
4666 #endif
4667 text_color_set(DW_COLOR_INFO);
4668 dw_printf ("Stream %d: Connected to %s. (%s)\n", S->stream_id, S->addrs[PEERCALL], S->state == state_5_awaiting_v22_connection ? "v2.2" : "v2.0");
4669
4670 // Erratum: 2006 version says DL-CONNECT *confirm* but original has *indication*.
4671
4672 // connect *indication* means "has been requested".
4673 // *confirm* seems right because we got a reply from the other side.
4674
4675 int incoming = 0;
4676 server_link_established (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], incoming);
4677 }
4678
4679 STOP_T1;
4680 #if 1 // My version.
4681 START_T3;
4682 #else // As shown in flow chart.
4683 STOP_T3; // Erratum? I think this is wrong.
4684 // We are about to enter state 3. When in state 3 either T1 or T3 should be
4685 // running. In state 3, we always see start one / stop the other pairs except where
4686 // we are about to enter a different state.
4687 // Since there is nothing outstanding where we expect a response, T1 would
4688 // not be started.
4689 #endif
4690 SET_VS(0);
4691 SET_VA(0);
4692 SET_VR(0);
4693 select_t1_value (S);
4694
4695 // Erratum: mdl_negotiate_request does not appear in the SDL flow chart.
4696 // It is mentioned here:
4697 //
4698 // C5.3 Internal Operation of the Machine
4699 //
4700 // The Management Data link State Machine handles the negotiation/notification of
4701 // operational parameters. It uses a single command/response exchange to negotiate the
4702 // final values of negotiable parameters.
4703 //
4704 // The station initiating the AX.25 connection will send an XID command after it receives
4705 // the UA frame. If the other station is using a version of AX.25 earlier than 2.2, it will
4706 // respond with an FRMR of the XID command and the default version 2.0 parameters will
4707 // be used. If the other station is using version 2.2 or better, it will respond with an XID
4708 // response.
4709
4710 if (S->state == state_5_awaiting_v22_connection) {
4711 mdl_negotiate_request (S);
4712 }
4713
4714 SET_RC(0); // My enhancement. See Erratum note in select_t1_value.
4715 enter_new_state (S, state_3_connected, __func__, __LINE__);
4716 }
4717 else {
4718 if (s_debug_protocol_errors) {
4719 text_color_set(DW_COLOR_ERROR);
4720 dw_printf ("Stream %d: AX.25 Protocol Error D: UA received without F=1 when SABM or DISC was sent P=1.\n", S->stream_id);
4721 }
4722 // stay in current state, either 1 or 5.
4723 }
4724 break;
4725
4726 case state_2_awaiting_release:
4727
4728 // Erratum: 2006 version is missing yes/no labels on this test.
4729 // DL-ERROR Indication does not mention error D.
4730
4731 if (f == 1) {
4732 text_color_set(DW_COLOR_INFO);
4733 dw_printf ("Stream %d: Disconnected from %s.\n", S->stream_id, S->addrs[PEERCALL]);
4734 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 0);
4735 STOP_T1;
4736 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
4737 }
4738 else {
4739 if (s_debug_protocol_errors) {
4740 text_color_set(DW_COLOR_ERROR);
4741 dw_printf ("Stream %d: AX.25 Protocol Error D: UA received without F=1 when SABM or DISC was sent P=1.\n", S->stream_id);
4742 }
4743 // stay in same state.
4744 }
4745 break;
4746
4747 case state_3_connected:
4748 case state_4_timer_recovery:
4749
4750 if (s_debug_protocol_errors) {
4751 text_color_set(DW_COLOR_ERROR);
4752 dw_printf ("Stream %d: AX.25 Protocol Error C: Unexpected UA in state %d.\n", S->stream_id, S->state);
4753 }
4754 establish_data_link (S);
4755 S->layer_3_initiated = 0;
4756
4757 // Erratum? Flow chart goes to state 1. Wouldn't we want this to be state 5 if modulo is 128?
4758 enter_new_state (S, S->modulo == 128 ? state_5_awaiting_v22_connection : state_1_awaiting_connection, __func__, __LINE__);
4759 break;
4760 }
4761
4762 } /* end ua_frame */
4763
4764
4765
4766 /*------------------------------------------------------------------------------
4767 *
4768 * Name: frmr_frame
4769 *
4770 * Purpose: Process FRMR Response Frame.
4771 *
4772 * Inputs: S - Data Link State Machine.
4773 *
4774 * Description: 4.3.3.2. Set Asynchronous Balanced Mode Extended (SABME) Command
4775 * ...
4776 * The TNC confirms reception and acceptance of a SABME command by sending a UA response frame at the
4777 * earliest opportunity. If the TNC is not capable of accepting a SABME command, it responds with a DM frame.
4778 * A TNC that uses a version of AX.25 prior to v2.2 responds with a FRMR.
4779 *
4780 * 4.3.3.9. FRMR Response Frame
4781 *
4782 * The FRMR response is removed from the standard for the following reasons:
4783 * a) UI frame transmission was not allowed during FRMR recovery;
4784 * b) During FRMR recovery, the link could not be reestablished by the station that sent the FRMR;
4785 * c) The above functions are better handled by simply resetting the link with a SABM(E) + UA exchange;
4786 * d) An implementation that receives and process FRMRs but does not transmit them is compatible with older
4787 * versions of the standard; and
4788 * e) SDL is simplified and removes the need for one state.
4789 * This version of AX.25 operates with previous versions of AX.25. It does not generate a FRMR Response
4790 * frame, but handles error conditions by resetting the link.
4791 *
4792 * 6.3.2. Parameter Negotiation Phase
4793 *
4794 * Parameter negotiation occurs at any time. It is accomplished by sending the XID command frame and
4795 * receiving the XID response frame. Implementations of AX.25 prior to version 2.2 respond to an XID command
4796 * frame with a FRMR response frame. The TNC receiving the FRMR uses a default set of parameters compatible
4797 * with previous versions of AX.25.
4798 *
4799 * 6.5. Resetting Procedure
4800 *
4801 * The link resetting procedure initializes both directions of data flow after a unrecoverable error has occurred.
4802 * This resetting procedure is used only in the information-transfer state of an AX.25 link.
4803 * A TNC initiates a reset procedure whenever it receives an unexpected UA response frame, or after receipt of
4804 * a FRMR frame from a TNC using an older version of the protocol.
4805 *
4806 *------------------------------------------------------------------------------*/
4807
4808
frmr_frame(ax25_dlsm_t * S)4809 static void frmr_frame (ax25_dlsm_t *S)
4810 {
4811 switch (S->state) {
4812
4813 case state_0_disconnected:
4814 case state_1_awaiting_connection:
4815 case state_2_awaiting_release:
4816 // Ignore it. Keep current state.
4817 break;
4818
4819 case state_3_connected:
4820 case state_4_timer_recovery:
4821
4822 if (s_debug_protocol_errors) {
4823 text_color_set(DW_COLOR_ERROR);
4824 dw_printf ("Stream %d: AX.25 Protocol Error K: FRMR not expected in state %d.\n", S->stream_id, S->state);
4825 }
4826
4827 set_version_2_0 (S); // Erratum: FRMR can only be sent by v2.0.
4828 // Need to force v2.0. Should be added to flow chart.
4829 establish_data_link (S);
4830 S->layer_3_initiated = 0;
4831 enter_new_state (S, state_1_awaiting_connection, __func__, __LINE__);
4832 break;
4833
4834 case state_5_awaiting_v22_connection:
4835
4836 text_color_set(DW_COLOR_INFO);
4837 dw_printf ("%s doesn't understand AX.25 v2.2. Trying v2.0 ...\n", S->addrs[PEERCALL]);
4838
4839 INIT_T1V_SRT;
4840
4841 set_version_2_0 (S); // Erratum: Need to force v2.0. This is not in flow chart.
4842
4843 establish_data_link (S);
4844 S->layer_3_initiated = 1; // Erratum? I don't understand the difference here.
4845 // State 1 clears it. State 5 sets it. Why not the same?
4846
4847 enter_new_state (S, state_1_awaiting_connection, __func__, __LINE__);
4848 break;
4849 }
4850
4851 // part of state machine for the XID negotiation.
4852
4853 // I would not expect this to happen.
4854 // To get here:
4855 // We sent SABME. (not SABM)
4856 // Other side responded with UA so it understands v2.2.
4857 // We sent XID command which puts us int the negotiating state.
4858 // Presumably this is in response to the XID and not something else.
4859
4860 // Anyhow, we will fall back to v2.0 parameters.
4861
4862 switch (S->mdl_state) {
4863
4864 case mdl_state_0_ready:
4865 break;
4866
4867 case mdl_state_1_negotiating:
4868
4869 set_version_2_0 (S);
4870 S->mdl_state = mdl_state_0_ready;
4871 break;
4872 }
4873
4874 } /* end frmr_frame */
4875
4876
4877 /*------------------------------------------------------------------------------
4878 *
4879 * Name: ui_frame
4880 *
4881 * Purpose: Process XID frame for negotiating protocol parameters.
4882 *
4883 * Inputs: S - Data Link State Machine.
4884 *
4885 * cr - Is it command or response?
4886 *
4887 * pf - Poll/Final bit.
4888 *
4889 * Description: 4.3.3.6. Unnumbered Information (UI) Frame
4890 *
4891 * The Unnumbered Information frame contains PID and information fields and passes information along the
4892 * link outside the normal information controls. This allows information fields to be exchanged on the link, bypassing
4893 * flow control.
4894 *
4895 * Because these frames cannot be acknowledged, if one such frame is obliterated, it cannot be recovered.
4896 * A received UI frame with the P bit set causes a response to be transmitted. This response is a DM frame when
4897 * in the disconnected state, or an RR (or RNR, if appropriate) frame in the information transfer state.
4898 *
4899 * Reality: The data link state machine was an add-on after APRS and client APIs were already done.
4900 * UI frames don't go thru here for normal operation.
4901 * The only reason we have this function is so that we can send a response to a UI command with P=1.
4902 *
4903 *------------------------------------------------------------------------------*/
4904
ui_frame(ax25_dlsm_t * S,cmdres_t cr,int pf)4905 static void ui_frame (ax25_dlsm_t *S, cmdres_t cr, int pf)
4906 {
4907 if (cr == cr_cmd && pf == 1) {
4908
4909 switch (S->state) {
4910
4911 case state_0_disconnected:
4912 case state_1_awaiting_connection:
4913 case state_2_awaiting_release:
4914 case state_5_awaiting_v22_connection:
4915 {
4916 cmdres_t r = cr_res; // DM response with F taken from P.
4917 int nopid = 0; // PID applies only for I and UI frames.
4918
4919 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, r, frame_type_U_DM, pf, nopid, NULL, 0);
4920 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
4921 }
4922 break;
4923
4924 case state_3_connected:
4925 case state_4_timer_recovery:
4926
4927 enquiry_response (S, frame_type_U_UI, pf);
4928 break;
4929 }
4930 }
4931
4932 } /* end ui_frame */
4933
4934
4935
4936 /*------------------------------------------------------------------------------
4937 *
4938 * Name: xid_frame
4939 *
4940 * Purpose: Process XID frame for negotiating protocol parameters.
4941 *
4942 * Inputs: S - Data Link State Machine.
4943 *
4944 * cr - Is it command or response?
4945 *
4946 * pf - Poll/Final bit.
4947 *
4948 * Description: 4.3.3.7 Exchange Identification (XID) Frame
4949 *
4950 * The Exchange Identification frame causes the addressed station to identify itself, and
4951 * to provide its characteristics to the sending station. An information field is optional within
4952 * the XID frame. A station receiving an XID command returns an XID response unless a UA
4953 * response to a mode setting command is awaiting transmission, or a FRMR condition
4954 * exists.
4955 *
4956 * The XID frame complies with ISO 8885. Only those fields applicable to AX.25 are
4957 * described. All other fields are set to an appropriate value. This implementation is
4958 * compatible with any implementation which follows ISO 8885. Only the general-purpose
4959 * XID information field identifier is required in this version of AX.25.
4960 *
4961 * The information field consists of zero or more information elements. The information
4962 * elements start with a Format Identifier (FI) octet. The second octet is the Group Identifier
4963 * (GI). The third and forth octets form the Group Length (GL). The rest of the information
4964 * field contains parameter fields.
4965 *
4966 * The FI takes the value 82 hex for the general-purpose XID information. The GI takes
4967 * the value 80 hex for the parameter-negotiation identifier. The GL indicates the length of
4968 * the associated parameter field. This length is expressed as a two-octet binary number
4969 * representing the length of the associated parameter field in octets. The high-order bits of
4970 * length value are in the first of the two octets. A group length of zero indicates the lack of
4971 * an associated parameter field and that all parameters assume their default values. The GL
4972 * does not include its own length or the length of the GI.
4973 *
4974 * The parameter field contains a series of Parameter Identifier (PI), Parameter Length
4975 * (PL), and Parameter Value (PV) set structures, in that order. Each PI identifies a
4976 * parameter and is one octet in length. Each PL indicates the length of the associated PV in
4977 * octets, and is one octet in length. Each PV contains the parameter value and is PL octets
4978 * in length. The PL does not include its own length or the length of its associated PI. A PL
4979 * value of zero indicates that the associated PV is absent; the parameter assumes the
4980 * default value. A PI/PL/PV set may be omitted if it is not required to convey information, or
4981 * if present values for the parameter are to be used. The PI/PL/PV fields are placed into the
4982 * information field of the XID frame in ascending order. There is only one entry for each
4983 * PI/PL/PV field used. A parameter field containing an unrecognized PI is ignored. An
4984 * omitted parameter field assumes the currently negotiated value.
4985 *
4986 *------------------------------------------------------------------------------*/
4987
4988
xid_frame(ax25_dlsm_t * S,cmdres_t cr,int pf,unsigned char * info_ptr,int info_len)4989 static void xid_frame (ax25_dlsm_t *S, cmdres_t cr, int pf, unsigned char *info_ptr, int info_len)
4990 {
4991 struct xid_param_s param;
4992 char desc[150];
4993 int ok;
4994 unsigned char xinfo[40];
4995 int xlen;
4996 cmdres_t res = cr_res;
4997 int f = 1;
4998 int nopid = 0;
4999 packet_t pp;
5000
5001
5002 switch (S->mdl_state) {
5003
5004 case mdl_state_0_ready:
5005
5006 if (cr == cr_cmd) {
5007
5008 if (pf == 1) {
5009
5010 // Take parameters sent by other station.
5011 // Generally we take minimum of what he wants and what I can do.
5012 // Adjust my working configuration and send it back.
5013
5014 ok = xid_parse (info_ptr, info_len, ¶m, desc, sizeof(desc));
5015
5016 if (ok) {
5017 negotiation_response (S, ¶m);
5018
5019 xlen = xid_encode (¶m, xinfo, res);
5020
5021 pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_XID, f, nopid, xinfo, xlen);
5022 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5023 }
5024 }
5025 else {
5026 text_color_set(DW_COLOR_ERROR);
5027 dw_printf ("Stream %d: AX.25 Protocol Error MDL-A: XID command without P=1.\n", S->stream_id);
5028 }
5029 }
5030 else {
5031 text_color_set(DW_COLOR_ERROR);
5032 dw_printf ("Stream %d: AX.25 Protocol Error MDL-B: Unexpected XID response.\n", S->stream_id);
5033 }
5034 break;
5035
5036 case mdl_state_1_negotiating:
5037
5038 if (cr == cr_res) {
5039
5040 if (pf == 1) {
5041
5042 // Got expected response. Copy into my working parameters.
5043
5044 ok = xid_parse (info_ptr, info_len, ¶m, desc, sizeof(desc));
5045
5046 if (ok) {
5047 complete_negotiation (S, ¶m);
5048 }
5049
5050 S->mdl_state = mdl_state_0_ready;
5051 STOP_TM201;
5052
5053 //#define TEST_TEST 1
5054
5055 #if TEST_TEST // Send TEST command to see how it responds.
5056 // We currently have no Client API for sending this or reporting result.
5057 {
5058 char info[80] = "The quick brown fox jumps over the lazy dog.";
5059 cmdres_t cmd = cr_cmd;
5060 int p = 0;
5061 int nopid = 0;
5062 packet_t pp;
5063
5064 pp = ax25_u_frame (S->addrs, S->num_addr, cmd, frame_type_U_TEST, p, nopid, (unsigned char *)info, (int)strlen(info));
5065 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5066 }
5067 #endif
5068 }
5069 else {
5070 text_color_set(DW_COLOR_ERROR);
5071 dw_printf ("Stream %d: AX.25 Protocol Error MDL-D: XID response without F=1.\n", S->stream_id);
5072 }
5073 }
5074 else {
5075 // Not expecting to receive a command when I sent one.
5076 // Flow chart says requeue but I just drop it.
5077 // The other end can retry and maybe I will be back to ready state by then.
5078 }
5079 break;
5080 }
5081
5082 } /* end xid_frame */
5083
5084
5085 /*------------------------------------------------------------------------------
5086 *
5087 * Name: test_frame
5088 *
5089 * Purpose: Process TEST command for checking link.
5090 *
5091 * Inputs: S - Data Link State Machine.
5092 *
5093 * cr - Is it command or response?
5094 *
5095 * pf - Poll/Final bit.
5096 *
5097 * Description: 4.3.3.8. Test (TEST) Frame
5098 *
5099 * The Test command causes the addressed station to respond with the TEST response at the first respond
5100 * opportunity; this performs a basic test of the data-link control. An information field is optional with the TEST
5101 * command. If present, the received information field is returned, if possible, by the addressed station, with the
5102 * TEST response. The TEST command has no effect on the mode or sequence variables maintained by the station.
5103 *
5104 * A FRMR condition may be established if the received TEST command information field exceeds the maximum
5105 * defined storage capability of the station. If a FRMR response is not returned for this condition, a TEST response
5106 * without an information field is returned.
5107 *
5108 * The station considers the data-link layer test terminated on receipt of the TEST response, or when a time-out
5109 * period has expired. The results of the TEST command/response exchange are made available for interrogation
5110 * by a higher layer.
5111 *
5112 * Erratum: TEST frame is not mentioned in the SDL flow charts.
5113 * Don't know how P/F is supposed to be used.
5114 * Here, the response sends back what was received in the command.
5115 *
5116 *------------------------------------------------------------------------------*/
5117
5118
test_frame(ax25_dlsm_t * S,cmdres_t cr,int pf,unsigned char * info_ptr,int info_len)5119 static void test_frame (ax25_dlsm_t *S, cmdres_t cr, int pf, unsigned char *info_ptr, int info_len)
5120 {
5121 cmdres_t res = cr_res;
5122 int f = pf;
5123 int nopid = 0;
5124 packet_t pp;
5125
5126 if (cr == cr_cmd) {
5127 pp = ax25_u_frame (S->addrs, S->num_addr, res, frame_type_U_TEST, f, nopid, info_ptr, info_len);
5128 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5129 }
5130
5131 } /* end test_frame */
5132
5133
5134
5135 /*------------------------------------------------------------------------------
5136 *
5137 * Name: dl_timer_expiry
5138 *
5139 * Purpose: Some timer expired. Figure out which one and act accordingly.
5140 *
5141 * Inputs: none.
5142 *
5143 *------------------------------------------------------------------------------*/
5144
dl_timer_expiry(void)5145 void dl_timer_expiry (void)
5146 {
5147 ax25_dlsm_t *p;
5148 double now = dtime_now();
5149
5150 // Examine all of the data link state machines.
5151 // Process only those where timer:
5152 // - is running.
5153 // - is not paused.
5154 // - expiration time has arrived or passed.
5155
5156 for (p = list_head; p != NULL; p = p->next) {
5157 if (p->t1_exp != 0 && p->t1_paused_at == 0 && p->t1_exp <= now) {
5158 p->t1_exp = 0;
5159 p->t1_paused_at = 0;
5160 p->t1_had_expired = 1;
5161 t1_expiry (p);
5162 }
5163 }
5164
5165 for (p = list_head; p != NULL; p = p->next) {
5166 if (p->t3_exp != 0 && p->t3_exp <= now) {
5167 p->t3_exp = 0;
5168 t3_expiry (p);
5169 }
5170 }
5171
5172 for (p = list_head; p != NULL; p = p->next) {
5173 if (p->tm201_exp != 0 && p->tm201_paused_at == 0 && p->tm201_exp <= now) {
5174 p->tm201_exp = 0;
5175 p->tm201_paused_at = 0;
5176 tm201_expiry (p);
5177 }
5178 }
5179
5180 } /* end dl_timer_expiry */
5181
5182
5183 /*------------------------------------------------------------------------------
5184 *
5185 * Name: t1_expiry
5186 *
5187 * Purpose: Handle T1 timer expiration for outstanding I frame or P-bit.
5188 *
5189 * Inputs: S - Data Link State Machine.
5190 *
5191 * Description: 4.4.5.1. T1 Timer Recovery
5192 *
5193 * If a transmission error causes a TNC to fail to receive (or to receive and discard) a single I frame, or the last I
5194 * frame in a sequence of I frames, then the TNC does not detect a send-sequence-number error and consequently
5195 * does not transmit a REJ/SREJ. The TNC that transmitted the unacknowledged I frame(s) following the completion
5196 * of timeout period T1, takes appropriate recovery action to determine when I frame retransmission as described
5197 * in Section 6.4.10 should begin. This condition is cleared by the reception of an acknowledgement for the sent
5198 * frame(s), or by the link being reset.
5199 *
5200 * 6.7.1.1. Acknowledgment Timer T1
5201 *
5202 * T1, the Acknowledgement Timer, ensures that a TNC does not wait indefinitely for a response to a frame it
5203 * sends. This timer cannot be expressed in absolute time; the time required to send frames varies greatly with the
5204 * signaling rate used at Layer 1. T1 should take at least twice the amount of time it would take to send maximum
5205 * length frame to the distant TNC and get the proper response frame back from the distant TNC. This allows time
5206 * for the distant TNC to do some processing before responding.
5207 * If Layer 2 repeaters are used, the value of T1 should be adjusted according to the number of repeaters through
5208 * which the frame is being transferred.
5209 *
5210 *------------------------------------------------------------------------------*/
5211
5212 // Make timer start, stop, expiry a different color to stand out.
5213
5214 #define DW_COLOR_DEBUG_TIMER DW_COLOR_ERROR
5215
5216
t1_expiry(ax25_dlsm_t * S)5217 static void t1_expiry (ax25_dlsm_t *S)
5218 {
5219
5220 if (s_debug_timers) {
5221 double now = dtime_now();
5222
5223 text_color_set(DW_COLOR_DEBUG_TIMER);
5224 dw_printf ("t1_expiry (), [now=%.3f], state=%d, rc=%d\n", now - S->start_time, S->state, S->rc);
5225 }
5226
5227 switch (S->state) {
5228
5229 case state_0_disconnected:
5230
5231 // Ignore it.
5232 break;
5233
5234 case state_1_awaiting_connection:
5235 case state_5_awaiting_v22_connection:
5236
5237 // MAXV22 hack.
5238 // If we already sent the maximum number of SABME, fall back to v2.0 SABM.
5239
5240 if (S->state == state_5_awaiting_v22_connection && S->rc == g_misc_config_p->maxv22) {
5241 set_version_2_0 (S);
5242 enter_new_state (S, state_1_awaiting_connection, __func__, __LINE__);
5243 }
5244
5245 if (S->rc == S->n2_retry) {
5246 discard_i_queue(S);
5247 text_color_set(DW_COLOR_INFO);
5248 dw_printf ("Failed to connect to %s after %d tries.\n", S->addrs[PEERCALL], S->n2_retry);
5249 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 1);
5250 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
5251 }
5252 else {
5253 cmdres_t cmd = cr_cmd;
5254 int p = 1;
5255 int nopid = 0;
5256
5257 packet_t pp;
5258
5259 SET_RC(S->rc+1);
5260 if (S->rc > S->peak_rc_value) S->peak_rc_value = S->rc; // Keep statistics.
5261
5262 pp = ax25_u_frame (S->addrs, S->num_addr, cmd, (S->state == state_5_awaiting_v22_connection) ? frame_type_U_SABME : frame_type_U_SABM, p, nopid, NULL, 0);
5263 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5264 select_t1_value(S);
5265 START_T1;
5266 // Keep same state.
5267 }
5268 break;
5269
5270 case state_2_awaiting_release:
5271
5272 if (S->rc == S->n2_retry) {
5273 text_color_set(DW_COLOR_INFO);
5274 dw_printf ("Stream %d: Disconnected from %s.\n", S->stream_id, S->addrs[PEERCALL]);
5275 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 0);
5276 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
5277 }
5278 else {
5279 cmdres_t cmd = cr_cmd;
5280 int p = 1;
5281 int nopid = 0;
5282
5283 packet_t pp;
5284
5285 SET_RC(S->rc+1);
5286 if (S->rc > S->peak_rc_value) S->peak_rc_value = S->rc;
5287
5288 pp = ax25_u_frame (S->addrs, S->num_addr, cmd, frame_type_U_DISC, p, nopid, NULL, 0);
5289 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5290 select_t1_value(S);
5291 START_T1;
5292 // stay in same state
5293 }
5294 break;
5295
5296 case state_3_connected:
5297
5298 SET_RC(1);
5299 transmit_enquiry (S);
5300 enter_new_state (S, state_4_timer_recovery, __func__, __LINE__);
5301 break;
5302
5303 case state_4_timer_recovery:
5304
5305 if (S->rc == S->n2_retry) {
5306
5307 // Erratum: 2006 version, page 103, is missing yes/no labels on decision blocks.
5308
5309 if (S->va != S->vs) {
5310
5311 if (s_debug_protocol_errors) {
5312 text_color_set(DW_COLOR_ERROR);
5313 dw_printf ("Stream %d: AX.25 Protocol Error I: %d timeouts: unacknowledged sent data.\n", S->stream_id, S->n2_retry);
5314 }
5315 }
5316 else if (S->peer_receiver_busy) {
5317
5318 if (s_debug_protocol_errors) {
5319 text_color_set(DW_COLOR_ERROR);
5320 dw_printf ("Stream %d: AX.25 Protocol Error U: %d timeouts: extended peer busy condition.\n", S->stream_id, S->n2_retry);
5321 }
5322 }
5323 else {
5324
5325 if (s_debug_protocol_errors) {
5326 text_color_set(DW_COLOR_ERROR);
5327 dw_printf ("Stream %d: AX.25 Protocol Error T: %d timeouts: no response to enquiry.\n", S->stream_id, S->n2_retry);
5328 }
5329 }
5330
5331 // Erratum: Flow chart says DL-DISCONNECT "request" in both original and 2006 revision.
5332 // That is clearly wrong because a "request" would come FROM the higher level protocol/client app.
5333 // I think it should be "indication" rather than "confirm" because the peer condition is unknown.
5334
5335 // dl disconnect *indication*
5336 text_color_set(DW_COLOR_INFO);
5337 dw_printf ("Stream %d: Disconnected from %s due to timeouts.\n", S->stream_id, S->addrs[PEERCALL]);
5338 server_link_terminated (S->chan, S->client, S->addrs[PEERCALL], S->addrs[OWNCALL], 1);
5339
5340 discard_i_queue (S);
5341
5342 cmdres_t cr = cr_res; // DM can only be response.
5343 int f = 0; // Erratum: Assuming F=0 because it is not response to P=1
5344 int nopid = 0;
5345
5346 packet_t pp = ax25_u_frame (S->addrs, S->num_addr, cr, frame_type_U_DM, f, nopid, NULL, 0);
5347 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5348
5349 enter_new_state (S, state_0_disconnected, __func__, __LINE__);
5350 }
5351 else {
5352 SET_RC(S->rc+1);
5353 if (S->rc > S->peak_rc_value) S->peak_rc_value = S->rc; // gather statistics.
5354
5355 transmit_enquiry (S);
5356 // Keep same state.
5357 }
5358 break;
5359 }
5360
5361 } /* end t1_expiry */
5362
5363
5364 /*------------------------------------------------------------------------------
5365 *
5366 * Name: t3_expiry
5367 *
5368 * Purpose: Handle T3 timer expiration.
5369 *
5370 * Inputs: S - Data Link State Machine.
5371 *
5372 * Description: TODO: still don't understand this.
5373 *
5374 * 4.4.5.2. Timer T3 Recovery
5375 *
5376 * Timer T3 ensures that the link is still functional during periods of low information transfer. When T1 is not
5377 * running (no outstanding I frames), T3 periodically causes the TNC to poll the other TNC of a link. When T3
5378 * times out, an RR or RNR frame is transmitted as a command with the P bit set, and then T1 is started. When a
5379 * response to this command is received, T1 is stopped and T3 is started. If T1 expires before a response is
5380 * received, then the waiting acknowledgement procedure (Section 6.4.11) is executed.
5381 *
5382 * 6.7.1.3. Inactive Link Timer T3
5383 *
5384 * T3, the Inactive Link Timer, maintains link integrity whenever T1 is not running. It is recommended that
5385 * whenever there are no outstanding unacknowledged I frames or P-bit frames (during the information-transfer
5386 * state), an RR or RNR frame with the P bit set to "1" be sent every T3 time units to query the status of the other
5387 * TNC. The period of T3 is locally defined, and depends greatly on Layer 1 operation. T3 should be greater than
5388 * T1; it may be very large on channels of high integrity.
5389 *
5390 *------------------------------------------------------------------------------*/
5391
t3_expiry(ax25_dlsm_t * S)5392 static void t3_expiry (ax25_dlsm_t *S)
5393 {
5394
5395 if (s_debug_timers) {
5396 double now = dtime_now();
5397
5398 text_color_set(DW_COLOR_DEBUG_TIMER);
5399 dw_printf ("t3_expiry (), [now=%.3f]\n", now - S->start_time);
5400 }
5401
5402 switch (S->state) {
5403
5404 case state_0_disconnected:
5405 case state_1_awaiting_connection:
5406 case state_5_awaiting_v22_connection:
5407 case state_2_awaiting_release:
5408 case state_4_timer_recovery:
5409
5410 break;
5411
5412 case state_3_connected:
5413
5414 // Erratum: Original sets RC to 0, 2006 revision sets RC to 1 which makes more sense.
5415
5416 SET_RC(1);
5417 transmit_enquiry (S);
5418 enter_new_state (S, state_4_timer_recovery, __func__, __LINE__);
5419 break;
5420 }
5421
5422 } /* end t3_expiry */
5423
5424
5425
5426 /*------------------------------------------------------------------------------
5427 *
5428 * Name: tm201_expiry
5429 *
5430 * Purpose: Handle TM201 timer expiration.
5431 *
5432 * Inputs: S - Data Link State Machine.
5433 *
5434 * Description: This is used when waiting for a response to an XID command.
5435 *
5436 *------------------------------------------------------------------------------*/
5437
5438
tm201_expiry(ax25_dlsm_t * S)5439 static void tm201_expiry (ax25_dlsm_t *S)
5440 {
5441
5442 struct xid_param_s param;
5443 unsigned char xinfo[40];
5444 int xlen;
5445 cmdres_t cmd = cr_cmd;
5446 int p = 1;
5447 int nopid = 0;
5448 packet_t pp;
5449
5450
5451 if (s_debug_timers) {
5452 double now = dtime_now();
5453
5454 text_color_set(DW_COLOR_DEBUG_TIMER);
5455 dw_printf ("tm201_expiry (), [now=%.3f], state=%d, rc=%d\n", now - S->start_time, S->state, S->rc);
5456 }
5457
5458 switch (S->mdl_state) {
5459
5460 case mdl_state_0_ready:
5461
5462 // Timer shouldn't be running when in this state.
5463
5464 break;
5465
5466 case mdl_state_1_negotiating:
5467
5468 S->mdl_rc++;
5469 if (S->mdl_rc > S->n2_retry) {
5470 text_color_set(DW_COLOR_ERROR);
5471 dw_printf ("Stream %d: AX.25 Protocol Error MDL-C: Management retry limit exceeded.\n", S->stream_id);
5472 S->mdl_state = mdl_state_0_ready;
5473 }
5474 else {
5475 // No response. Ask again.
5476
5477 initiate_negotiation (S, ¶m);
5478
5479 xlen = xid_encode (¶m, xinfo, cmd);
5480
5481 pp = ax25_u_frame (S->addrs, S->num_addr, cmd, frame_type_U_XID, p, nopid, xinfo, xlen);
5482 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5483
5484 START_TM201;
5485 }
5486 break;
5487 }
5488
5489 } /* end tm201_expiry */
5490
5491
5492 //###################################################################################
5493 //###################################################################################
5494 //
5495 // Subroutines from protocol spec, pages 106 - 109
5496 //
5497 //###################################################################################
5498 //###################################################################################
5499
5500 // FIXME: continue review here.
5501
5502
5503 /*------------------------------------------------------------------------------
5504 *
5505 * Name: nr_error_recovery
5506 *
5507 * Purpose: Try to recover after receiving an expected N(r) value.
5508 *
5509 *------------------------------------------------------------------------------*/
5510
nr_error_recovery(ax25_dlsm_t * S)5511 static void nr_error_recovery (ax25_dlsm_t *S)
5512 {
5513 if (s_debug_protocol_errors) {
5514 text_color_set(DW_COLOR_ERROR);
5515 dw_printf ("Stream %d: AX.25 Protocol Error J: N(r) sequence error.\n", S->stream_id);
5516 }
5517 establish_data_link (S);
5518 S->layer_3_initiated = 0;
5519
5520 } /* end nr_error_recovery */
5521
5522
5523 /*------------------------------------------------------------------------------
5524 *
5525 * Name: establish_data_link
5526 * (Combined with "establish extended data link")
5527 *
5528 * Purpose: Send SABM or SABME to other station.
5529 *
5530 * Inputs: S->
5531 * addrs destination, source, and optional digi addresses.
5532 * num_addr Number of addresses. Should be 2 .. 10.
5533 * modulo Determines if we send SABME or SABM.
5534 *
5535 * Description: Original spec had two different functions that differed
5536 * only by sending SABM or SABME. Here they are combined into one.
5537 *
5538 *------------------------------------------------------------------------------*/
5539
establish_data_link(ax25_dlsm_t * S)5540 static void establish_data_link (ax25_dlsm_t *S)
5541 {
5542 cmdres_t cmd = cr_cmd;
5543 int p = 1;
5544 packet_t pp;
5545 int nopid = 0;
5546
5547 clear_exception_conditions (S);
5548
5549 // Erratum: We have an off-by-one error here.
5550 // Flow chart shows setting RC to 0 and we end up sending SAMB(e) 11 times when N2 (RETRY) is 10.
5551 // It should be 1 rather than 0.
5552
5553 SET_RC(1);
5554 pp = ax25_u_frame (S->addrs, S->num_addr, cmd, (S->modulo == 128) ? frame_type_U_SABME : frame_type_U_SABM, p, nopid, NULL, 0);
5555 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5556 STOP_T3;
5557 START_T1;
5558
5559 } /* end establish_data_link */
5560
5561
5562
5563 /*------------------------------------------------------------------------------
5564 *
5565 * Name: clear_exception_conditions
5566 *
5567 *------------------------------------------------------------------------------*/
5568
clear_exception_conditions(ax25_dlsm_t * S)5569 static void clear_exception_conditions (ax25_dlsm_t *S)
5570 {
5571 S->peer_receiver_busy = 0;
5572 S->reject_exception = 0;
5573 S->own_receiver_busy = 0;
5574 S->acknowledge_pending = 0;
5575
5576 // My enhancement. If we are establishing a new connection, we should discard any saved out of sequence incoming I frames.
5577
5578 int n;
5579
5580 for (n = 0; n < 128; n++) {
5581 if (S->rxdata_by_ns[n] != NULL) {
5582 cdata_delete (S->rxdata_by_ns[n]);
5583 S->rxdata_by_ns[n] = NULL;
5584 }
5585 }
5586
5587 // We retain the transmit I frame queue so we can continue after establishing a new connection.
5588
5589 } /* end clear_exception_conditions */
5590
5591
5592 /*------------------------------------------------------------------------------
5593 *
5594 * Name: transmit_enquiry, page 106
5595 *
5596 * Purpose: This is called only when a timer expires.
5597 *
5598 * T1: We sent I frames and timed out waiting for the ack.
5599 * Poke the other end to determine how much it got so far
5600 * so we know where to continue.
5601 *
5602 * T3: Not activity for substantial amount of time.
5603 * Poke the other end to see if it is still there.
5604 *
5605 *
5606 * Observation: This is the only place where we send RR command with P=1.
5607 *
5608 * Sequence of events:
5609 *
5610 * We send some I frames to the other guy.
5611 * There are outstanding sent I frames for which we did not receive ACK.
5612 *
5613 * Timer 1 expires when we are in state 3: send RR/RNR command P=1 (here). Enter state 4.
5614 * Timer 1 expires when we are in state 4: same until max retry count is exceeded.
5615 *
5616 * Other guy gets RR/RNR command P=1.
5617 * Same action for either state 3 or 4.
5618 * Whether he has outstanding un-ack'ed sent I frames is irrelevent.
5619 * He calls "enquiry response" which sends RR/RNR response F=1.
5620 * (Read about detour 1 below and in enquiry_response.)
5621 *
5622 * I get back RR/RNR response F=1. Still in state 4.
5623 * Of course, N(R) gets copied into V(A).
5624 * Now here is the interesting part.
5625 * If the ACKs are caught up, i.e. V(A) == V(S), stop T1 and enter state 3.
5626 * Otherwise, "invoke retransmission" to resend everything after N(R).
5627 *
5628 *
5629 * Detour 1: You were probably thinking, "Suppose SREJ is enabled and the other guy
5630 * had a record of the SREJ frames sent which were not answered by filled in
5631 * I frames. Why not send the SREJ again instead of backing up and resending
5632 * stuff which already got there OK?"
5633 *
5634 * The code to handle incoming SREJ in state 4 is there but stop T1 is in the
5635 * wrong place as mentioned above.
5636 *
5637 *------------------------------------------------------------------------------*/
5638
transmit_enquiry(ax25_dlsm_t * S)5639 static void transmit_enquiry (ax25_dlsm_t *S)
5640 {
5641 int p = 1;
5642 int nr = S->vr;
5643 cmdres_t cmd = cr_cmd;
5644 packet_t pp;
5645
5646 if (s_debug_retry) {
5647 text_color_set(DW_COLOR_ERROR);
5648 dw_printf ("\n****** TRANSMIT ENQUIRY RR/RNR cmd P=1 ****** state=%d, rc=%d\n\n", S->state, S->rc);
5649 }
5650
5651 // This is the ONLY place that we send RR/RNR *command* with P=1.
5652 // Everywhere else should be response.
5653 // I don't think we ever use RR/RNR command P=0 but need to check on that.
5654
5655 pp = ax25_s_frame (S->addrs, S->num_addr, cmd, S->own_receiver_busy ? frame_type_S_RNR : frame_type_S_RR, S->modulo, nr, p, NULL, 0);
5656
5657 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5658
5659 S->acknowledge_pending = 0;
5660 START_T1;
5661
5662 } /* end transmit_enquiry */
5663
5664
5665
5666 /*------------------------------------------------------------------------------
5667 *
5668 * Name: enquiry_response
5669 *
5670 * Inputs: frame_type - Type of frame received or frame_not_AX25 for LM seize confirm.
5671 * I think that this function is being called from too many
5672 * different contexts where it really needs to react differently.
5673 * So pass in more information about where we are coming from.
5674 *
5675 * F - Always specified as parameter in the references.
5676 *
5677 * Description: This is called for:
5678 * - UI command with P=1 then F=1.
5679 * - LM seize confirm with ack pending then F=0. (TODO: not clear on this yet.)
5680 * TODO: I think we want to ensure that this function is called ONLY
5681 * for RR/RNR/I command with P=1. LM Seize confirm can do its own thing and
5682 * not get involved in this complication.
5683 * - check_need_for_response(), command & P=1, then F=1
5684 * - RR/RNR/REJ command & P=1, then F=1
5685 *
5686 * In all cases, we see that F has been specified, usually 1 because it is
5687 * a response to a command with P=1.
5688 * Specifying F would imply response when the flow chart says RR/RNR command.
5689 * The documentation says:
5690 *
5691 * 6.2. Poll/Final (P/F) Bit Procedures
5692 *
5693 * The next response frame returned to an I frame with the P bit set to "1", received during the information
5694 * transfer state, is an RR, RNR or REJ response with the F bit set to "1".
5695 *
5696 * The next response frame returned to a supervisory command frame with the P bit set to "1", received during
5697 * the information transfer state, is an RR, RNR or REJ response frame with the F bit set to "1".
5698 *
5699 * Erattum! The flow chart says RR/RNR *command* but I'm confident it should be response.
5700 *
5701 * Erratum: Ax.25 spec has nothing here for SREJ. See X.25 2.4.6.11 for explanation.
5702 *
5703 *------------------------------------------------------------------------------*/
5704
enquiry_response(ax25_dlsm_t * S,ax25_frame_type_t frame_type,int f)5705 static void enquiry_response (ax25_dlsm_t *S, ax25_frame_type_t frame_type, int f)
5706 {
5707 cmdres_t cr = cr_res; // Response, not command as seen in flow chart.
5708 int nr = S->vr;
5709 packet_t pp;
5710
5711
5712 if (s_debug_retry) {
5713 text_color_set(DW_COLOR_ERROR);
5714 dw_printf ("\n****** ENQUIRY RESPONSE F=%d ******\n\n", f);
5715 }
5716
5717 #if 1 // Detour 1
5718
5719 // My addition, Based on X.25 2.4.6.11.
5720 // Only for RR, RNR, I.
5721 // See sequence of events in transmit_enquiry comments.
5722
5723 if (f == 1 && (frame_type == frame_type_S_RR || frame_type == frame_type_S_RNR || frame_type == frame_type_I)) {
5724
5725 if (S->own_receiver_busy) {
5726
5727 // I'm busy.
5728
5729 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_RNR, S->modulo, nr, f, NULL, 0);
5730 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5731
5732 S->acknowledge_pending = 0; // because we sent N(R) from V(R).
5733 }
5734
5735 else if (S->srej_enable == srej_single || S->srej_enable == srej_multi) {
5736
5737
5738 // SREJ is enabled. This is based on X.25 2.4.6.11.
5739
5740 if (S->modulo != 128) {
5741 text_color_set(DW_COLOR_ERROR);
5742 dw_printf ("INTERNAL ERROR: enquiry response should not be sending SREJ for modulo 8.\n");
5743 }
5744
5745 // Suppose we received I frames with N(S) of 0, 3, 7.
5746 // V(R) is still 1 because 0 is the last one received with contiguous N(S) values.
5747 // 3 and 7 have been saved into S->rxdata_by_ns.
5748 // We have outstanding requests to resend 1, 2, 4, 5, 6.
5749 // Either those requests or the replies got lost.
5750 // The other end timed out and asked us what is happening by sending RR/RNR command P=1.
5751
5752 // First see if we have any out of sequence frames in the receive buffer.
5753
5754 int last;
5755 last = AX25MODULO(S->vr - 1, S->modulo, __FILE__, __func__, __LINE__);
5756 while (last != S->vr && S->rxdata_by_ns[last] == NULL) {
5757 last = AX25MODULO(last - 1, S->modulo, __FILE__, __func__, __LINE__);
5758 }
5759
5760 if (last != S->vr) {
5761
5762 // Ask for missing frames to be sent again. X.25 2.4.6.11 b) & 2.3.5.2.2
5763
5764 int resend[128];
5765 int count = 0;
5766 int j;
5767 int allow_f1 = 1;
5768
5769 j = S->vr;
5770 while (j != last) {
5771 if (S->rxdata_by_ns[j] == NULL) {
5772 resend[count++] = j;
5773 }
5774 j = AX25MODULO(j + 1, S->modulo, __FILE__, __func__, __LINE__);
5775 }
5776
5777 send_srej_frames (S, resend, count, allow_f1);
5778 }
5779 else {
5780
5781 // Not waiting for fill in of missing frames. X.25 2.4.6.11 c)
5782
5783 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_RR, S->modulo, nr, f, NULL, 0);
5784 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5785
5786 S->acknowledge_pending = 0;
5787 }
5788
5789 } else {
5790
5791 // SREJ not enabled.
5792 // One might get the idea that it would make sense send REJ here if the reject exception is set.
5793 // However, I can't seem to find that buried in X.25 2.4.5.9.
5794 // And when we look at what happens when RR response, F=1 is received in state 4, it is
5795 // effectively REJ when N(R) is not the same as V(S).
5796
5797 if (s_debug_retry) {
5798 text_color_set(DW_COLOR_ERROR);
5799 dw_printf ("\n****** ENQUIRY RESPONSE srej not enbled, sending RR resp F=%d ******\n\n", f);
5800 }
5801
5802 pp = ax25_s_frame (S->addrs, S->num_addr, cr, frame_type_S_RR, S->modulo, nr, f, NULL, 0);
5803 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5804
5805 S->acknowledge_pending = 0;
5806 }
5807
5808 } // end of RR,RNR,I cmd with P=1
5809
5810 else {
5811
5812 // For cases other than (RR, RNR, I) command, P=1.
5813
5814 pp = ax25_s_frame (S->addrs, S->num_addr, cr, S->own_receiver_busy ? frame_type_S_RNR : frame_type_S_RR, S->modulo, nr, f, NULL, 0);
5815 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5816
5817 S->acknowledge_pending = 0;
5818 }
5819
5820 #else
5821
5822 // As found in AX.25 spec.
5823 // Erratum: This is woefully inadequate when SREJ is enabled.
5824 // Erratum: Flow chart says RR/RNR command but I'm confident it should be response.
5825
5826 pp = ax25_s_frame (S->addrs, S->num_addr, cr, S->own_receiver_busy ? frame_type_S_RNR : frame_type_S_RR, S->modulo, nr, f, NULL, 0);
5827 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5828
5829 S->acknowledge_pending = 0;
5830
5831 # endif
5832
5833 } /* end enquiry_response */
5834
5835
5836
5837
5838 /*------------------------------------------------------------------------------
5839 *
5840 * Name: invoke_retransmission
5841 *
5842 * Inputs: nr_input - Resend starting with this.
5843 * Continue will all up to and including current V(S) value.
5844 *
5845 * Description: Resend one or more frames that have already been sent.
5846 * Should always send at least one.
5847 *
5848 * This is probably the result of getting REJ asking for a resend.
5849 *
5850 * Context: I would expect the caller to clear 'acknowledge_pending' after calling this
5851 * because we sent N(R), from V(R), to ack what was received from other guy.
5852 * I would also expect Stop T3 & Start T1 at the same place.
5853 *
5854 *------------------------------------------------------------------------------*/
5855
invoke_retransmission(ax25_dlsm_t * S,int nr_input)5856 static void invoke_retransmission (ax25_dlsm_t *S, int nr_input)
5857 {
5858
5859 // Original flow chart showed saving V(S) into temp variable x,
5860 // using V(S) as loop control variable, and finally restoring it
5861 // to original value before returning.
5862 // Here we just a local variable instead of messing with it.
5863 // This should be equivalent but safer.
5864
5865 int local_vs;
5866 int sent_count = 0;
5867
5868 if (s_debug_misc) {
5869 text_color_set(DW_COLOR_ERROR);
5870 dw_printf ("invoke_retransmission(): starting with %d, state=%d, rc=%d, \n", nr_input, S->state, S->rc);
5871 }
5872
5873 // I don't think we should be here if SREJ is enabled.
5874 // TODO: Figure out why this happens occasionally.
5875
5876 // if (S->srej_enable != srej_none) {
5877 // text_color_set(DW_COLOR_ERROR);
5878 // dw_printf ("Internal Error, Did not expect to be here when SREJ enabled. %s %s %d\n", __FILE__, __func__, __LINE__);
5879 // }
5880
5881 if (S->txdata_by_ns[nr_input] == NULL) {
5882 text_color_set(DW_COLOR_ERROR);
5883 dw_printf ("Internal Error, Can't resend starting with N(S) = %d. It is not available. %s %s %d\n", nr_input, __FILE__, __func__, __LINE__);
5884 return;
5885 }
5886
5887
5888 local_vs = nr_input;
5889 do {
5890
5891 if (S->txdata_by_ns[local_vs] != NULL) {
5892
5893 cmdres_t cr = cr_cmd;
5894 int ns = local_vs;
5895 int nr = S->vr;
5896 int p = 0;
5897
5898 if (s_debug_misc) {
5899 text_color_set(DW_COLOR_INFO);
5900 dw_printf ("invoke_retransmission(): Resending N(S) = %d\n", ns);
5901 }
5902
5903 packet_t pp = ax25_i_frame (S->addrs, S->num_addr, cr, S->modulo, nr, ns, p,
5904 S->txdata_by_ns[ns]->pid, (unsigned char *)(S->txdata_by_ns[ns]->data), S->txdata_by_ns[ns]->len);
5905
5906 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
5907 // Keep it around in case we need to send again.
5908
5909 sent_count++;
5910 }
5911 else {
5912 text_color_set(DW_COLOR_ERROR);
5913 dw_printf ("Internal Error, state=%d, need to retransmit N(S) = %d for REJ but it is not available. %s %s %d\n", S->state, local_vs, __FILE__, __func__, __LINE__);
5914 }
5915 local_vs = AX25MODULO(local_vs + 1, S->modulo, __FILE__, __func__, __LINE__);
5916
5917 } while (local_vs != S->vs);
5918
5919 if (sent_count == 0) {
5920 text_color_set(DW_COLOR_ERROR);
5921 dw_printf ("Internal Error, Nothing to retransmit. N(R)=%d, %s %s %d\n", nr_input, __FILE__, __func__, __LINE__);
5922 }
5923
5924 } /* end invoke_retransmission */
5925
5926
5927
5928 /*------------------------------------------------------------------------------
5929 *
5930 * Name: check_i_frame_ackd
5931 *
5932 * Purpose:
5933 *
5934 * Inputs: nr - N(R) from I or S frame, acknowledging receipt thru N(R)-1.
5935 * i.e. The next one expected by the peer is N(R).
5936 *
5937 * Outputs: S->va - updated from nr.
5938 *
5939 * Description: This is called for:
5940 * - 'I' frame received and N(R) is in expected range, states 3 & 4.
5941 * - RR/RNR command with p=1 received and N(R) is in expected range, state 3 only.
5942 *
5943 *------------------------------------------------------------------------------*/
5944
check_i_frame_ackd(ax25_dlsm_t * S,int nr)5945 static void check_i_frame_ackd (ax25_dlsm_t *S, int nr)
5946 {
5947 if (S->peer_receiver_busy) {
5948 SET_VA(nr);
5949
5950 // Erratum? This looks odd to me.
5951 // It doesn't seem right that we would have T3 and T1 running at the same time.
5952 // Normally we stop one when starting the other.
5953 // Should this be Stop T3 instead?
5954
5955 START_T3;
5956 if ( ! IS_T1_RUNNING) {
5957 START_T1;
5958 }
5959 }
5960 else if (nr == S->vs) {
5961 SET_VA(nr);
5962 STOP_T1;
5963 START_T3;
5964 select_t1_value (S);
5965 }
5966 else if (nr != S->va) {
5967
5968 if (s_debug_misc) {
5969 text_color_set(DW_COLOR_DEBUG);
5970 dw_printf ("check_i_frame_ackd n(r)=%d, v(a)=%d, Set v(a) to new value %d\n", nr, S->va, nr);
5971 }
5972
5973 SET_VA(nr);
5974 START_T1; // Erratum? Flow chart says "restart" rather than "start."
5975 // Is this intentional, what is the difference?
5976 }
5977
5978 } /* check_i_frame_ackd */
5979
5980
5981
5982 /*------------------------------------------------------------------------------
5983 *
5984 * Name: check_need_for_response
5985 *
5986 * Inputs: frame_type - frame_type_S_RR, etc.
5987 *
5988 * cr - Is it a command or response?
5989 *
5990 * pf - P/F from the frame.
5991 *
5992 * Description: This is called for RR, RNR, and REJ frames.
5993 * If it is a command with P=1, we reply with RR or RNR with F=1.
5994 *
5995 *------------------------------------------------------------------------------*/
5996
check_need_for_response(ax25_dlsm_t * S,ax25_frame_type_t frame_type,cmdres_t cr,int pf)5997 static void check_need_for_response (ax25_dlsm_t *S, ax25_frame_type_t frame_type, cmdres_t cr, int pf)
5998 {
5999 if (cr == cr_cmd && pf == 1) {
6000 int f = 1;
6001 enquiry_response (S, frame_type, f);
6002 }
6003 else if (cr == cr_res && pf == 1) {
6004 if (s_debug_protocol_errors) {
6005 text_color_set(DW_COLOR_ERROR);
6006 dw_printf ("Stream %d: AX.25 Protocol Error A: F=1 received but P=1 not outstanding.\n", S->stream_id);
6007 }
6008 }
6009
6010 } /* end check_need_for_response */
6011
6012
6013
6014 /*------------------------------------------------------------------------------
6015 *
6016 * Name: ui_check
6017 *
6018 * Description: I don't think we need this because UI frames are processed
6019 * without going thru the data link state machine.
6020 *
6021 *------------------------------------------------------------------------------*/
6022
6023 /*------------------------------------------------------------------------------
6024 *
6025 * Name: select_t1_value
6026 *
6027 * Purpose: Dynamically adjust the T1 timeout value, commonly a fixed time known as FRACK.
6028 *
6029 * Inputs: S->rc Retry counter.
6030 *
6031 * S->srt Smoothed roundtrip time in seconds.
6032 *
6033 * S->t1_remaining_when_last_stopped
6034 * Seconds left on T1 when it is stopped.
6035 *
6036 * Outputs: S->srt New smoothed roundtrip time.
6037 *
6038 * S->t1v How long to wait for an acknowlegement before resending.
6039 * Value used when starting timer T1, in seconds.
6040 * Here it is dynamically adjusted.
6041 *
6042 * Description: How long should we wait for an ACK before sending again or giving up?
6043 * some implementations have a fixed length time. This is usually the FRACK parameter,
6044 * typically 3 seconds (D710A) or 4 seconds (KPC-3+).
6045 *
6046 * This should be increased for each digipeater in the path.
6047 * Here it is dynamically adjusted by taking the average time it takes to get a response
6048 * and then we double it.
6049 *
6050 * Rambling: It seems like a good idea to adapt to channel conditions, such as digipeater delays,
6051 * but it is fraught with peril if you are not careful.
6052 *
6053 * For example, if we accept an incoming connection and only receive some I frames and
6054 * send no I frames, T1 never gets started. In my earlier attempt, 't1_remaining_when_last_stopped'
6055 * had the initial value of 0 lacking any reason to set it differently. The calculation here
6056 * then kept pushing t1v up up up. After receiving 20 I frames and sending none,
6057 * t1v was over 300 seconds!!!
6058 *
6059 * We need some way to indicate that 't1_remaining_when_last_stopped' is not valid and
6060 * not to use it. Rather than adding a new variable, it is set to a negative value
6061 * initially to mean it has not been set yet. That solves one problem.
6062 *
6063 * T1 is paused whenever the channel is busy, either transmitting or receiving,
6064 * so the measured time could turn out to be a tiny fraction of a second, much less than
6065 * the frame transmission time.
6066 * If this gets too low, an unusually long random delay, before the sender's transmission,
6067 * could exceed this. I put in a lower limit for t1v, currently 1 second.
6068 *
6069 * What happens if we get multiple timeouts because we don't get a response?
6070 * For example, when we try to connect to a station which is not there, a KPC-3+ will give
6071 * up and report failure after 10 tries x 4 sec = 40 seconds.
6072 *
6073 * The algorithm in the AX.25 protocol spec shows increasing timeout values.
6074 * It might seem like a good idea but either it was not thought out very well
6075 * or I am not understanding it. If it is doubled each time, it gets awful large
6076 * very quickly. If we try to connect to a station which is not there,
6077 * we want to know within a minute, not an hour later.
6078 *
6079 * Keeping with the spirit of increasing the time but keeping it sane,
6080 * I increase the time linearly by a fraction of a second.
6081 *
6082 *------------------------------------------------------------------------------*/
6083
6084
select_t1_value(ax25_dlsm_t * S)6085 static void select_t1_value (ax25_dlsm_t *S)
6086 {
6087 float old_srt = S->srt;
6088
6089
6090 // Erratum: I don't think this test for RC == 0 is valid.
6091 // We would need to set RC to 0 whenever we enter state 3 and we don't do that.
6092 // I think a more appropriate test would be to check if we are in state 3.
6093 // When things are going smoothly, it makes sense to fine tune timeout based on smoothed round trip time.
6094 // When in some other state, we might want to slowly increase the time to minimize collisions.
6095 // Maybe the solution is to set RC=0 when we enter state 3.
6096
6097 // TODO: come back and revisit this.
6098
6099 if (S->rc == 0) {
6100
6101 if (S->t1_remaining_when_last_stopped >= 0) { // Negative means invalid, don't use it.
6102
6103 // This is an IIR low pass filter.
6104 // Algebraically equivalent to version in AX.25 protocol spec but I think the
6105 // original intent is clearer by having 1/8 appear only once.
6106
6107 S->srt = 7./8. * S->srt + 1./8. * ( S->t1v - S->t1_remaining_when_last_stopped );
6108 }
6109
6110 // We pause T1 when the channel is busy.
6111 // This includes both receiving someone else and us transmitting.
6112 // This can result in the round trip time going down to almost nothing.
6113 // My enhancement is to prevent srt from going below one second so
6114 // t1v should never be less than 2 seconds.
6115 // When t1v was allowed to go down to 1, we got occastional timeouts
6116 // even under ideal conditions, probably due to random CSMA delay time.
6117
6118 if (S->srt < 1) {
6119
6120 S->srt = 1;
6121
6122 // Add another 2 seconds for each digipeater in path.
6123
6124 if (S->num_addr > 2) {
6125 S->srt += 2 * (S->num_addr - 2);
6126 }
6127 }
6128
6129 S->t1v = S->srt * 2;
6130 }
6131 else {
6132
6133 if (S->t1_had_expired) {
6134
6135 // This goes up exponentially if implemented as documented!
6136 // For example, if we were trying to connect to a station which is not there, we
6137 // would retry after 3, the 8, 16, 32, ... and not time out for over an hour.
6138 // That's ridiculous. Let's try increasing it by a quarter second each time.
6139 // We now give up after about a minute.
6140
6141 // NO! S->t1v = powf(2, S->rc+1) * S->srt;
6142
6143 S->t1v = S->rc * 0.25 + S->srt * 2;
6144 }
6145 }
6146
6147 if (s_debug_timers) {
6148 text_color_set(DW_COLOR_DEBUG);
6149 dw_printf ("Stream %d: select_t1_value, rc = %d, t1 remaining = %.3f, old srt = %.3f, new srt = %.3f, new t1v = %.3f\n",
6150 S->stream_id, S->rc, S->t1_remaining_when_last_stopped, old_srt, S->srt, S->t1v);
6151 }
6152
6153
6154 if (S->t1v < 0.99 || S->t1v > 30) {
6155 text_color_set(DW_COLOR_ERROR);
6156 dw_printf ("INTERNAL ERROR? Stream %d: select_t1_value, rc = %d, t1 remaining = %.3f, old srt = %.3f, new srt = %.3f, Extreme new t1v = %.3f\n",
6157 S->stream_id, S->rc, S->t1_remaining_when_last_stopped, old_srt, S->srt, S->t1v);
6158 }
6159
6160 } /* end select_t1_value */
6161
6162
6163 /*------------------------------------------------------------------------------
6164 *
6165 * Name: set_version_2_0
6166 *
6167 * Erratum: Flow chart refers to T2 which doesn't appear anywhere else.
6168 *
6169 *------------------------------------------------------------------------------*/
6170
set_version_2_0(ax25_dlsm_t * S)6171 static void set_version_2_0 (ax25_dlsm_t *S)
6172 {
6173 S->srej_enable = srej_none;
6174 S->modulo = 8;
6175 S->n1_paclen = g_misc_config_p->paclen;
6176 S->k_maxframe = g_misc_config_p->maxframe_basic;
6177 S->n2_retry = g_misc_config_p->retry;
6178
6179 } /* end set_version_2_0 */
6180
6181
6182 /*------------------------------------------------------------------------------
6183 *
6184 * Name: set_version_2_2
6185 *
6186 *------------------------------------------------------------------------------*/
6187
set_version_2_2(ax25_dlsm_t * S)6188 static void set_version_2_2 (ax25_dlsm_t *S)
6189 {
6190 S->srej_enable = srej_single; // Start with single.
6191 // Can be increased to multi with XID exchange.
6192 S->modulo = 128;
6193 S->n1_paclen = g_misc_config_p->paclen;
6194 S->k_maxframe = g_misc_config_p->maxframe_extended;
6195 S->n2_retry = g_misc_config_p->retry;
6196
6197 } /* end set_version_2_2 */
6198
6199
6200
6201
6202 /*------------------------------------------------------------------------------
6203 *
6204 * Name: is_good_nr
6205 *
6206 * Purpose: Evaluate condition "V(a) <= N(r) <= V(s)" which appears in flow charts
6207 * for incoming I, RR, RNR, REJ, and SREJ frames.
6208 *
6209 * Inputs: S - state machine. Contains V(a) and V(s).
6210 *
6211 * nr - N(r) found in the incoming frame.
6212 *
6213 * Description: This determines whether the Received Sequence Number, N(R), is in
6214 * the expected range for normal processing or if we have an error
6215 * condition that needs recovery.
6216 *
6217 * This gets tricky due to the wrap around of sequence numbers.
6218 *
6219 * 4.2.4.4. Received Sequence Number N(R)
6220 *
6221 * The received sequence number exists in both I and S frames.
6222 * Prior to sending an I or S frame, this variable is updated to equal that
6223 * of the received state variable, thus implicitly acknowledging the proper
6224 * reception of all frames up to and including N(R)-1.
6225 *
6226 * Pattern noticed: Anytime we have "is_good_nr" returning true, we should always
6227 * - set V(A) from N(R) or
6228 * - call "check_i_frame_ackd" which does the same and some timer stuff.
6229 *
6230 *------------------------------------------------------------------------------*/
6231
6232
is_good_nr(ax25_dlsm_t * S,int nr)6233 static int is_good_nr (ax25_dlsm_t *S, int nr)
6234 {
6235 int adjusted_va, adjusted_nr, adjusted_vs;
6236 int result;
6237
6238 /* Adjust all values relative to V(a) before comparing so we won't have wrap around. */
6239
6240 #define adjust_by_va(x) (AX25MODULO((x) - S->va, S->modulo, __FILE__, __func__, __LINE__))
6241
6242 adjusted_va = adjust_by_va(S->va); // A clever compiler would know it is zero.
6243 adjusted_nr = adjust_by_va(nr);
6244 adjusted_vs = adjust_by_va(S->vs);
6245
6246 result = adjusted_va <= adjusted_nr && adjusted_nr <= adjusted_vs;
6247
6248 if (s_debug_misc) {
6249 text_color_set(DW_COLOR_DEBUG);
6250 dw_printf ("is_good_nr, V(a) %d <= nr %d <= V(s) %d, returns %d\n", S->va, nr, S->vs, result);
6251 }
6252
6253 return (result);
6254
6255 } /* end is_good_nr */
6256
6257
6258
6259 /*------------------------------------------------------------------------------
6260 *
6261 * Name: i_frame_pop_off_queue
6262 *
6263 * Purpose: Transmit an I frame if we have one in the queue and conditions are right.
6264 * This appears two slightly different ways in the flow charts:
6265 * "frame pop off queue"
6266 * "I frame pops off queue"
6267 *
6268 * Inputs: i_frame_queue - Remove items from here.
6269 * peer_receiver_busy - If other end not busy.
6270 * V(s) - and we haven't reached window size.
6271 * V(a)
6272 * k
6273 *
6274 * Outputs: v(s) is incremented for each processed.
6275 * acknowledge_pending = 0
6276 *
6277 *------------------------------------------------------------------------------*/
6278
i_frame_pop_off_queue(ax25_dlsm_t * S)6279 static void i_frame_pop_off_queue (ax25_dlsm_t *S)
6280 {
6281
6282
6283 if (s_debug_misc) {
6284 //text_color_set(DW_COLOR_DEBUG);
6285 //dw_printf ("i_frame_pop_off_queue () state=%d\n", S->state);
6286 }
6287
6288 // TODO: Were we expecting something in the queue?
6289 // or is empty an expected situation?
6290
6291 if (S->i_frame_queue == NULL) {
6292
6293 if (s_debug_misc) {
6294 // TODO: add different switch for I frame queue.
6295 //text_color_set(DW_COLOR_DEBUG);
6296 //dw_printf ("i_frame_pop_off_queue () queue is empty get out, line %d\n", __LINE__);
6297 }
6298
6299 // I Frame queue is empty.
6300 // Nothing to see here, folks. Move along.
6301 return;
6302 }
6303
6304 switch (S->state) {
6305
6306 case state_1_awaiting_connection:
6307 case state_5_awaiting_v22_connection:
6308
6309 if (s_debug_misc) {
6310 //text_color_set(DW_COLOR_DEBUG);
6311 //dw_printf ("i_frame_pop_off_queue () line %d\n", __LINE__);
6312 }
6313
6314 // This seems to say remove the I Frame from the queue and discard it if "layer 3 initiated" is set.
6315
6316 // For the case of removing it from the queue and putting it back in we just leave it there.
6317
6318 // Erratum? The flow chart seems to be backwards.
6319 // It would seem like we want to keep it if we are further along in the connection process.
6320 // I don't understand the intention here, and can't make a compelling argument on why it
6321 // is backwards, so it is implemented as documented.
6322
6323 if (S->layer_3_initiated) {
6324 cdata_t *txdata;
6325
6326 if (s_debug_misc) {
6327 //text_color_set(DW_COLOR_DEBUG);
6328 //dw_printf ("i_frame_pop_off_queue () discarding due to L3 init. line %d\n", __LINE__);
6329 }
6330 txdata = S->i_frame_queue; // Remove from head of list.
6331 S->i_frame_queue = txdata->next;
6332 cdata_delete (txdata);
6333 }
6334 break;
6335
6336 case state_3_connected:
6337 case state_4_timer_recovery:
6338
6339 if (s_debug_misc) {
6340 //text_color_set(DW_COLOR_DEBUG);
6341 //dw_printf ("i_frame_pop_off_queue () state %d, line %d\n", S->state, __LINE__);
6342 }
6343
6344 while ( ( ! S->peer_receiver_busy ) &&
6345 S->i_frame_queue != NULL &&
6346 WITHIN_WINDOW_SIZE(S) ) {
6347
6348 cdata_t *txdata;
6349
6350 txdata = S->i_frame_queue; // Remove from head of list.
6351 S->i_frame_queue = txdata->next;
6352 txdata->next = NULL;
6353
6354 cmdres_t cr = cr_cmd;
6355 int ns = S->vs;
6356 int nr = S->vr;
6357 int p = 0;
6358
6359 if (s_debug_misc || s_debug_radio) {
6360 //dw_printf ("i_frame_pop_off_queue () ns=%d, queue for transmit \"", ns);
6361 //ax25_safe_print (txdata->data, txdata->len, 1);
6362 //dw_printf ("\"\n");
6363 }
6364 packet_t pp = ax25_i_frame (S->addrs, S->num_addr, cr, S->modulo, nr, ns, p, txdata->pid, (unsigned char *)(txdata->data), txdata->len);
6365
6366 if (s_debug_misc) {
6367 //text_color_set(DW_COLOR_DEBUG);
6368 //dw_printf ("calling lm_data_request for I frame, %s line %d\n", __func__, __LINE__);
6369 }
6370
6371 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
6372
6373 // Stash in sent array in case it gets lost and needs to be sent again.
6374
6375 if (S->txdata_by_ns[ns] != NULL) {
6376 cdata_delete (S->txdata_by_ns[ns]);
6377 }
6378 S->txdata_by_ns[ns] = txdata;
6379
6380 SET_VS(AX25MODULO(S->vs + 1, S->modulo, __FILE__, __func__, __LINE__)); // increment sequence of last sent.
6381
6382 S->acknowledge_pending = 0;
6383
6384 // Erratum: I think we always want to restart T1 when an I frame is sent.
6385 // Otherwise we could time out too soon.
6386 #if 1
6387 STOP_T3;
6388 START_T1;
6389 #else
6390 if ( ! IS_T1_RUNNING) {
6391 STOP_T3;
6392 START_T1;
6393 }
6394 #endif
6395 }
6396 break;
6397
6398 case state_0_disconnected:
6399 case state_2_awaiting_release:
6400
6401 // Do nothing.
6402 break;
6403 }
6404
6405 } /* end i_frame_pop_off_queue */
6406
6407
6408
6409
6410 /*------------------------------------------------------------------------------
6411 *
6412 * Name: discard_i_queue
6413 *
6414 * Purpose: Discard any data chunks waiting to be sent.
6415 *
6416 *------------------------------------------------------------------------------*/
6417
6418
discard_i_queue(ax25_dlsm_t * S)6419 static void discard_i_queue (ax25_dlsm_t *S)
6420 {
6421 cdata_t *t;
6422
6423 while (S->i_frame_queue != NULL) {
6424
6425 t = S->i_frame_queue;
6426 S->i_frame_queue = S->i_frame_queue->next;
6427 cdata_delete (t);
6428 }
6429
6430 } /* end discard_i_queue */
6431
6432
6433
6434 /*------------------------------------------------------------------------------
6435 *
6436 * Name: enter_new_state
6437 *
6438 * Purpose: Switch to new state.
6439 *
6440 * Description: Use a function, rather than setting variable directly, so we have
6441 * one common point for debug output and possibly other things we
6442 * might want to do at a state change.
6443 *
6444 *------------------------------------------------------------------------------*/
6445
6446 // TODO: requeuing???
6447
enter_new_state(ax25_dlsm_t * S,enum dlsm_state_e new_state,const char * from_func,int from_line)6448 static void enter_new_state (ax25_dlsm_t *S, enum dlsm_state_e new_state, const char *from_func, int from_line)
6449 {
6450
6451 if (s_debug_variables) {
6452 text_color_set(DW_COLOR_ERROR);
6453 dw_printf ("\n");
6454 dw_printf (">>> NEW STATE = %d, previously %d, called from %s %d <<<\n", new_state, S->state, from_func, from_line);
6455 dw_printf ("\n");
6456 }
6457
6458 assert (new_state >= 0 && new_state <= 5);
6459
6460
6461 if (( new_state == state_3_connected || new_state == state_4_timer_recovery) &&
6462 S->state != state_3_connected && S->state != state_4_timer_recovery ) {
6463
6464 ptt_set (OCTYPE_CON, S->chan, 1); // Turn on connected indicator if configured.
6465 }
6466 else if (( new_state != state_3_connected && new_state != state_4_timer_recovery) &&
6467 ( S->state == state_3_connected || S->state == state_4_timer_recovery ) ) {
6468
6469 ptt_set (OCTYPE_CON, S->chan, 0); // Turn off connected indicator if configured.
6470 // Ideally we should look at any other link state machines
6471 // for this channel and leave the indicator on if any
6472 // are connected. I'm not that worried about it.
6473 }
6474
6475 S->state = new_state;
6476
6477 } /* end enter_new_state */
6478
6479
6480
6481 /*------------------------------------------------------------------------------
6482 *
6483 * Name: mdl_negotiate_request
6484 *
6485 * Purpose: After receiving UA, in response to SABME, this starts up the XID exchange.
6486 *
6487 * Description: Send XID command.
6488 * Start timer TM201 so we can retry if timeout waiting for response.
6489 * Enter MDL negotiating state.
6490 *
6491 *------------------------------------------------------------------------------*/
6492
mdl_negotiate_request(ax25_dlsm_t * S)6493 static void mdl_negotiate_request (ax25_dlsm_t *S)
6494 {
6495 struct xid_param_s param;
6496 unsigned char xinfo[40];
6497 int xlen;
6498 cmdres_t cmd = cr_cmd;
6499 int p = 1;
6500 int nopid = 0;
6501 packet_t pp;
6502 int n;
6503
6504 // At least one known [partial] v2.2 implementation understands SABME but not XID.
6505 // Rather than wasting time, sending XID repeatedly until giving up, we have a workaround.
6506 // The configuration file can contain a list of stations known not to respond to XID.
6507 // Obviously this applies only to v2.2 because XID was not part of v2.0.
6508
6509 for (n = 0; n < g_misc_config_p->noxid_count; n++) {
6510 if (strcmp(S->addrs[PEERCALL],g_misc_config_p->noxid_addrs[n]) == 0) {
6511 return;
6512 }
6513 }
6514
6515 switch (S->mdl_state) {
6516
6517 case mdl_state_0_ready:
6518
6519 initiate_negotiation (S, ¶m);
6520
6521 xlen = xid_encode (¶m, xinfo, cmd);
6522
6523 pp = ax25_u_frame (S->addrs, S->num_addr, cmd, frame_type_U_XID, p, nopid, xinfo, xlen);
6524 lm_data_request (S->chan, TQ_PRIO_1_LO, pp);
6525
6526 S->mdl_rc = 0;
6527 START_TM201;
6528 S->mdl_state = mdl_state_1_negotiating;
6529
6530 break;
6531
6532 case mdl_state_1_negotiating:
6533
6534 // SDL says "requeue" but I don't understand how it would be useful or how to do it.
6535 break;
6536 }
6537
6538 } /* end mdl_negotiate_request */
6539
6540
6541 /*------------------------------------------------------------------------------
6542 *
6543 * Name: initiate_negotiation
6544 *
6545 * Purpose: Used when preparing the XID *command*.
6546 *
6547 * Description: Prepare set of parameters to request from the other station.
6548 *
6549 *------------------------------------------------------------------------------*/
6550
initiate_negotiation(ax25_dlsm_t * S,struct xid_param_s * param)6551 static void initiate_negotiation (ax25_dlsm_t *S, struct xid_param_s *param)
6552 {
6553 param->full_duplex = 0;
6554 switch (S->srej_enable) {
6555 case srej_single:
6556 case srej_multi:
6557 param->srej = srej_multi; // see if other end reconizes it.
6558 break;
6559 case srej_none:
6560 default:
6561 param->srej = srej_none;
6562 break;
6563 }
6564
6565 param->modulo = S->modulo;
6566 param->i_field_length_rx = S->n1_paclen; // Hmmmm. Should we ask for what the user
6567 // specified for PACLEN or offer the maximum
6568 // that we can handle, AX25_N1_PACLEN_MAX?
6569 param->window_size_rx = S->k_maxframe;
6570 param->ack_timer = (int)(g_misc_config_p->frack * 1000);
6571 param->retries = S->n2_retry;
6572 }
6573
6574
6575 /*------------------------------------------------------------------------------
6576 *
6577 * Name: negotiation_response
6578 *
6579 * Purpose: Used when receiving the XID command and preparing the XID response.
6580 *
6581 * Description: Take what other station has asked for and reduce if we have lesser capabilities.
6582 * For example if other end wants 8k information part we reduce it to 2k.
6583 * Ack time and retries are the opposite, we take the maximum.
6584 *
6585 * Question: If the other send leaves anything undefined should we leave it
6586 * undefined or fill in what we would like before sending it back?
6587 *
6588 * The original version of the protocol spec left this open.
6589 * The 2006 revision, in red, says we should fill in defaults for anything
6590 * not specified. This makes sense. We send back a complete set of parameters
6591 * so both ends should agree.
6592 *
6593 *------------------------------------------------------------------------------*/
6594
negotiation_response(ax25_dlsm_t * S,struct xid_param_s * param)6595 static void negotiation_response (ax25_dlsm_t *S, struct xid_param_s *param)
6596 {
6597
6598 // TODO: Integrate with new full duplex capability in v1.5.
6599
6600 param->full_duplex = 0;
6601
6602 // Other end might want 8.
6603 // Seems unlikely. If it implements XID it should have modulo 128.
6604
6605 if (param->modulo == modulo_unknown) {
6606 param->modulo = 8; // Not specified. Set default.
6607 }
6608 else {
6609 param->modulo = MIN(param->modulo, 128);
6610 }
6611
6612 // We can do REJ or SREJ but won't combine them.
6613 // Erratum: 2006 version, section, 4.3.3.7 says default selective reject - reject.
6614 // We can't do that.
6615
6616 if (param->srej == srej_not_specified) {
6617 param->srej = (param->modulo == 128) ? srej_single : srej_none; // not specified, set default
6618 }
6619
6620 // We can currently do up to 2k.
6621 // Take minimum of that and what other guy asks for.
6622
6623 if (param->i_field_length_rx == G_UNKNOWN) {
6624 param->i_field_length_rx = 256; // Not specified, take default.
6625 }
6626 else {
6627 param->i_field_length_rx = MIN(param->i_field_length_rx, AX25_N1_PACLEN_MAX);
6628 }
6629
6630 // In theory extended mode can have window size of 127 but
6631 // I'm limiting it to 63 for the reason mentioned in the SREJ logic.
6632
6633 if (param->window_size_rx == G_UNKNOWN) {
6634 param->window_size_rx = (param->modulo == 128) ? 32 : 4; // not specified, set default.
6635 }
6636 else {
6637 if (param->modulo == 128)
6638 param->window_size_rx = MIN(param->window_size_rx, AX25_K_MAXFRAME_EXTENDED_MAX);
6639 else
6640 param->window_size_rx = MIN(param->window_size_rx, AX25_K_MAXFRAME_BASIC_MAX);
6641 }
6642
6643 // Erratum: Unclear. Is the Acknowledgement Timer before or after compensating for digipeaters
6644 // in the path? e.g. Typically TNCs use the FRACK parameter for this and it often defaults to 3.
6645 // However, the actual timeout value might be something like FRACK*(2*m+1) where m is the number of
6646 // digipeaters in the path. I'm assuming this is the FRACK value and any additional time, for
6647 // digipeaters will be added in locally at each end on top of this exchanged value.
6648
6649 if (param->ack_timer == G_UNKNOWN) {
6650 param->ack_timer = 3000; // not specified, set default.
6651 }
6652 else {
6653 param->ack_timer = MAX(param->ack_timer, (int)(g_misc_config_p->frack * 1000));
6654 }
6655
6656 if (param->retries == G_UNKNOWN) {
6657 param->retries = 10; // not specified, set default.
6658 }
6659 else {
6660 param->retries = MAX(param->retries, S->n2_retry);
6661 }
6662
6663 // IMPORTANT: Take values we have agreed upon and put into my running configuration.
6664
6665 complete_negotiation(S, param);
6666 }
6667
6668
6669 /*------------------------------------------------------------------------------
6670 *
6671 * Name: complete_negotiation
6672 *
6673 * Purpose: Used when preparing or receiving the XID *response*.
6674 *
6675 * Description: Take set of parameters which we have agreed upon and apply
6676 * to the running configuration.
6677 *
6678 * TODO: Should do some checking here in case other station
6679 * sends something crazy.
6680 *
6681 *------------------------------------------------------------------------------*/
6682
complete_negotiation(ax25_dlsm_t * S,struct xid_param_s * param)6683 static void complete_negotiation (ax25_dlsm_t *S, struct xid_param_s *param)
6684 {
6685 if (param->srej != srej_not_specified) {
6686 S->srej_enable = param->srej;
6687 }
6688
6689 if (param->modulo != modulo_unknown) {
6690 // Disaster if aren't agreeing on this.
6691 S->modulo = param->modulo;
6692 }
6693
6694 if (param->i_field_length_rx != G_UNKNOWN) {
6695 S->n1_paclen = param->i_field_length_rx;
6696 }
6697
6698 if (param->window_size_rx != G_UNKNOWN) {
6699 S->k_maxframe = param->window_size_rx;
6700 }
6701
6702 if (param->ack_timer != G_UNKNOWN) {
6703 S->t1v = param->ack_timer * 0.001;
6704 }
6705
6706 if (param->retries != G_UNKNOWN) {
6707 S->n2_retry = param->retries;
6708 }
6709 }
6710
6711
6712
6713
6714
6715 //###################################################################################
6716 //###################################################################################
6717 //
6718 // Timers.
6719 //
6720 // Start.
6721 // Stop.
6722 // Pause (when channel busy) & resume.
6723 // Is it running?
6724 // Did it expire before being stopped?
6725 // When will next one expire?
6726 //
6727 //###################################################################################
6728 //###################################################################################
6729
6730
start_t1(ax25_dlsm_t * S,const char * from_func,int from_line)6731 static void start_t1 (ax25_dlsm_t *S, const char *from_func, int from_line)
6732 {
6733 double now = dtime_now();
6734
6735 if (s_debug_timers) {
6736 text_color_set(DW_COLOR_DEBUG_TIMER);
6737 dw_printf ("Start T1 for t1v = %.3f sec, rc = %d, [now=%.3f] from %s %d\n", S->t1v, S->rc, now - S->start_time, from_func, from_line);
6738 }
6739
6740 S->t1_exp = now + S->t1v;
6741 if (S->radio_channel_busy) {
6742 S->t1_paused_at = now;
6743 }
6744 else {
6745 S->t1_paused_at = 0;
6746 }
6747 S->t1_had_expired = 0;
6748
6749 } /* end start_t1 */
6750
6751
stop_t1(ax25_dlsm_t * S,const char * from_func,int from_line)6752 static void stop_t1 (ax25_dlsm_t *S, const char *from_func, int from_line)
6753 {
6754 double now = dtime_now();
6755
6756 RESUME_T1; // adjust expire time if paused.
6757
6758 if (S->t1_exp == 0.0) {
6759 // Was already stopped.
6760 }
6761 else {
6762 S->t1_remaining_when_last_stopped = S->t1_exp - now;
6763 if (S->t1_remaining_when_last_stopped < 0) S->t1_remaining_when_last_stopped = 0;
6764 }
6765
6766 // Normally this would be at the top but we don't know time remaining at that point.
6767
6768 if (s_debug_timers) {
6769 text_color_set(DW_COLOR_DEBUG_TIMER);
6770 if (S->t1_exp == 0.0) {
6771 dw_printf ("Stop T1. Wasn't running, [now=%.3f] from %s %d\n", now - S->start_time, from_func, from_line);
6772 }
6773 else {
6774 dw_printf ("Stop T1, %.3f remaining, [now=%.3f] from %s %d\n", S->t1_remaining_when_last_stopped, now - S->start_time, from_func, from_line);
6775 }
6776 }
6777
6778 S->t1_exp = 0.0; // now stopped.
6779 S->t1_had_expired = 0; // remember that it did not expire.
6780
6781 } /* end stop_t1 */
6782
6783
is_t1_running(ax25_dlsm_t * S,const char * from_func,int from_line)6784 static int is_t1_running (ax25_dlsm_t *S, const char *from_func, int from_line)
6785 {
6786 int result = S->t1_exp != 0.0;
6787
6788 if (s_debug_timers) {
6789 text_color_set(DW_COLOR_DEBUG);
6790 dw_printf ("is_t1_running? returns %d\n", result);
6791 }
6792
6793 return (result);
6794
6795 } /* end is_t1_running */
6796
6797
pause_t1(ax25_dlsm_t * S,const char * from_func,int from_line)6798 static void pause_t1 (ax25_dlsm_t *S, const char *from_func, int from_line)
6799 {
6800
6801 if (S->t1_exp == 0.0) {
6802 // Stopped so there is nothing to do.
6803 }
6804 else if (S->t1_paused_at == 0.0) {
6805 // Running and not paused.
6806
6807 double now = dtime_now();
6808
6809 S->t1_paused_at = now;
6810
6811 if (s_debug_timers) {
6812 text_color_set(DW_COLOR_DEBUG);
6813 dw_printf ("Paused T1 with %.3f still remaining, [now=%.3f] from %s %d\n", S->t1_exp - now, now - S->start_time, from_func, from_line);
6814 }
6815 }
6816 else {
6817 if (s_debug_timers) {
6818 text_color_set(DW_COLOR_DEBUG);
6819 dw_printf ("T1 error: Didn't expect pause when already paused.\n");
6820 }
6821 }
6822
6823 } /* end pause_t1 */
6824
6825
resume_t1(ax25_dlsm_t * S,const char * from_func,int from_line)6826 static void resume_t1 (ax25_dlsm_t *S, const char *from_func, int from_line)
6827 {
6828 if (S->t1_exp == 0.0) {
6829 // Stopped so there is nothing to do.
6830 }
6831 else if (S->t1_paused_at == 0.0) {
6832 // Running but not paused.
6833 }
6834 else {
6835 double now = dtime_now();
6836 double paused_for_sec = now - S->t1_paused_at;
6837
6838 S->t1_exp += paused_for_sec;
6839 S->t1_paused_at = 0.0;
6840
6841 if (s_debug_timers) {
6842 text_color_set(DW_COLOR_DEBUG);
6843 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);
6844 }
6845 }
6846
6847 } /* end resume_t1 */
6848
6849
6850
6851
6852 // T3 is a lot simpler.
6853 // Here we are talking about minutes of inactivity with the peer
6854 // rather than expecting a response within seconds where timing is more critical.
6855 // We don't need to capture remaining time when stopped.
6856 // I don't think there is a need to pause it due to the large time frame.
6857
6858
start_t3(ax25_dlsm_t * S,const char * from_func,int from_line)6859 static void start_t3 (ax25_dlsm_t *S, const char *from_func, int from_line)
6860 {
6861 double now = dtime_now();
6862
6863 if (s_debug_timers) {
6864 text_color_set(DW_COLOR_DEBUG_TIMER);
6865 dw_printf ("Start T3 for %.3f sec, [now=%.3f] from %s %d\n", T3_DEFAULT, now - S->start_time, from_func, from_line);
6866 }
6867
6868 S->t3_exp = now + T3_DEFAULT;
6869 }
6870
stop_t3(ax25_dlsm_t * S,const char * from_func,int from_line)6871 static void stop_t3 (ax25_dlsm_t *S, const char *from_func, int from_line)
6872 {
6873 if (s_debug_timers) {
6874 double now = dtime_now();
6875
6876 text_color_set(DW_COLOR_DEBUG_TIMER);
6877 if (S->t3_exp == 0.0) {
6878 dw_printf ("Stop T3. Wasn't running.\n");
6879 }
6880 else {
6881 dw_printf ("Stop T3, %.3f remaining, [now=%.3f] from %s %d\n", S->t3_exp - now, now - S->start_time, from_func, from_line);
6882 }
6883 }
6884 S->t3_exp = 0.0;
6885 }
6886
6887
6888
6889 // TM201 is similar to T1.
6890 // It needs to be paused whent the channel is busy.
6891 // Simpler because we don't need to keep track of time remaining when stopped.
6892
6893
6894
start_tm201(ax25_dlsm_t * S,const char * from_func,int from_line)6895 static void start_tm201 (ax25_dlsm_t *S, const char *from_func, int from_line)
6896 {
6897 double now = dtime_now();
6898
6899 if (s_debug_timers) {
6900 text_color_set(DW_COLOR_DEBUG_TIMER);
6901 dw_printf ("Start TM201 for t1v = %.3f sec, rc = %d, [now=%.3f] from %s %d\n", S->t1v, S->rc, now - S->start_time, from_func, from_line);
6902 }
6903
6904 S->tm201_exp = now + S->t1v;
6905 if (S->radio_channel_busy) {
6906 S->tm201_paused_at = now;
6907 }
6908 else {
6909 S->tm201_paused_at = 0;
6910 }
6911
6912 } /* end start_tm201 */
6913
6914
stop_tm201(ax25_dlsm_t * S,const char * from_func,int from_line)6915 static void stop_tm201 (ax25_dlsm_t *S, const char *from_func, int from_line)
6916 {
6917 double now = dtime_now();
6918
6919 if (s_debug_timers) {
6920 text_color_set(DW_COLOR_DEBUG_TIMER);
6921 dw_printf ("Stop TM201. [now=%.3f] from %s %d\n", now - S->start_time, from_func, from_line);
6922 }
6923
6924 S->tm201_exp = 0.0; // now stopped.
6925
6926 } /* end stop_tm201 */
6927
6928
6929
pause_tm201(ax25_dlsm_t * S,const char * from_func,int from_line)6930 static void pause_tm201 (ax25_dlsm_t *S, const char *from_func, int from_line)
6931 {
6932
6933 if (S->tm201_exp == 0.0) {
6934 // Stopped so there is nothing to do.
6935 }
6936 else if (S->tm201_paused_at == 0.0) {
6937 // Running and not paused.
6938
6939 double now = dtime_now();
6940
6941 S->tm201_paused_at = now;
6942
6943 if (s_debug_timers) {
6944 text_color_set(DW_COLOR_DEBUG);
6945 dw_printf ("Paused TM201 with %.3f still remaining, [now=%.3f] from %s %d\n", S->tm201_exp - now, now - S->start_time, from_func, from_line);
6946 }
6947 }
6948 else {
6949 if (s_debug_timers) {
6950 text_color_set(DW_COLOR_DEBUG);
6951 dw_printf ("TM201 error: Didn't expect pause when already paused.\n");
6952 }
6953 }
6954
6955 } /* end pause_tm201 */
6956
6957
resume_tm201(ax25_dlsm_t * S,const char * from_func,int from_line)6958 static void resume_tm201 (ax25_dlsm_t *S, const char *from_func, int from_line)
6959 {
6960 if (S->tm201_exp == 0.0) {
6961 // Stopped so there is nothing to do.
6962 }
6963 else if (S->tm201_paused_at == 0.0) {
6964 // Running but not paused.
6965 }
6966 else {
6967 double now = dtime_now();
6968 double paused_for_sec = now - S->tm201_paused_at;
6969
6970 S->tm201_exp += paused_for_sec;
6971 S->tm201_paused_at = 0.0;
6972
6973 if (s_debug_timers) {
6974 text_color_set(DW_COLOR_DEBUG);
6975 dw_printf ("Resumed TM201 after pausing for %.3f sec, %.3f still remaining, [now=%.3f]\n", paused_for_sec, S->tm201_exp - now, now - S->start_time);
6976 }
6977 }
6978
6979 } /* end resume_tm201 */
6980
6981
6982
6983
6984
ax25_link_get_next_timer_expiry(void)6985 double ax25_link_get_next_timer_expiry (void)
6986 {
6987 double tnext = 0;
6988 ax25_dlsm_t *p;
6989
6990 for (p = list_head; p != NULL; p = p->next) {
6991
6992 // Consider if running and not paused.
6993
6994 if (p->t1_exp != 0 && p->t1_paused_at == 0) {
6995 if (tnext == 0) {
6996 tnext = p->t1_exp;
6997 }
6998 else if (p->t1_exp < tnext) {
6999 tnext = p->t1_exp;
7000 }
7001 }
7002
7003 if (p->t3_exp != 0) {
7004 if (tnext == 0) {
7005 tnext = p->t3_exp;
7006 }
7007 else if (p->t3_exp < tnext) {
7008 tnext = p->t3_exp;
7009 }
7010 }
7011
7012 if (p->tm201_exp != 0 && p->tm201_paused_at == 0) {
7013 if (tnext == 0) {
7014 tnext = p->tm201_exp;
7015 }
7016 else if (p->tm201_exp < tnext) {
7017 tnext = p->tm201_exp;
7018 }
7019 }
7020
7021 }
7022
7023 if (s_debug_timers > 1) {
7024 text_color_set(DW_COLOR_DEBUG);
7025 if (tnext == 0.0) {
7026 dw_printf ("ax25_link_get_next_timer_expiry returns none.\n");
7027 }
7028 else {
7029 dw_printf ("ax25_link_get_next_timer_expiry returns %.3f sec from now.\n",
7030 tnext - dtime_now());
7031 }
7032 }
7033
7034 return (tnext);
7035
7036 } /* end ax25_link_get_next_timer_expiry */
7037
7038
7039 /* end ax25_link.c */
7040