Bug Summary

File:src/sprt.c
Warning:line 639, column 13
Value stored to 'something_was_sent' is never read

Annotated Source Code

1/*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * sprt.c - An implementation of the SPRT protocol defined in V.150.1
5 * Annex B, less the packet exchange part
6 *
7 * Written by Steve Underwood <steveu@coppice.org>
8 *
9 * Copyright (C) 2022 Steve Underwood
10 *
11 * All rights reserved.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2, as
15 * published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#if defined(HAVE_CONFIG_H1)
28#include "config.h"
29#endif
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <sys/types.h>
34#include <inttypes.h>
35#include <memory.h>
36#if defined(HAVE_STDBOOL_H1)
37#include <stdbool.h>
38#else
39#include <spandsp/stdbool.h>
40#endif
41
42#define SPANDSP_FULLY_DEFINE_SPRT_STATE_T
43
44#include "spandsp/telephony.h"
45#include "spandsp/alloc.h"
46#include "spandsp/unaligned.h"
47#include "spandsp/logging.h"
48#include "spandsp/async.h"
49#include "spandsp/sprt.h"
50
51#include "spandsp/private/logging.h"
52#include "spandsp/private/sprt.h"
53
54/* V.150.1 consists of
55 V.150.1 (01/03)
56 The main spec
57 V.150.1 (2003) Corrigendum 1 (07/03)
58 This was merged into the spec, and so is irrelevant
59 V.150.1 (2003) Corrigendum 2 (03/04)
60 Fixes Table 15, Annex E.1, Annex E.1.4, E.1.5, E.2.3
61 V.150.1 (2003) Amendment 1 (01/05)
62 Additions to Table 12 for VBD and ToIP
63 V.150.1 (2003) Amendment 2 (05/06)
64 These are mostly ToIP and VBD changes.
65 Additions/changes to 2, 3.2, 10, 15.3, 15.4, Table 16, 15.4.1,
66 15.4.5, 15.4.11.8, 15.4.11.9, 15.4.11.10, 17, 18, 19, C.2.5,
67 C.2.6, C.3, C.5.2, C.5.3, C.5.5, Annex D, Appendix IV
68*/
69
70static struct
71{
72 uint16_t min_payload_bytes;
73 uint16_t max_payload_bytes;
74 uint16_t min_window_size;
75 uint16_t max_window_size;
76} channel_parm_limits[SPRT_CHANNELS4] =
77{
78 {
79 SPRT_MIN_TC0_PAYLOAD_BYTES140,
80 SPRT_MAX_TC0_PAYLOAD_BYTES256,
81 1,
82 1
83 },
84 {
85 SPRT_MIN_TC1_PAYLOAD_BYTES132,
86 SPRT_MAX_TC1_PAYLOAD_BYTES256,
87 SPRT_MIN_TC1_WINDOWS_SIZE32,
88 SPRT_MAX_TC1_WINDOWS_SIZE96
89 },
90 {
91 SPRT_MIN_TC2_PAYLOAD_BYTES132,
92 SPRT_MAX_TC2_PAYLOAD_BYTES256,
93 SPRT_MIN_TC2_WINDOWS_SIZE8,
94 SPRT_MAX_TC2_WINDOWS_SIZE32
95 },
96 {
97 SPRT_MIN_TC3_PAYLOAD_BYTES140,
98 SPRT_MAX_TC3_PAYLOAD_BYTES256,
99 1,
100 1
101 }
102};
103
104static channel_parms_t default_channel_parms[SPRT_CHANNELS4] =
105{
106 {
107 SPRT_DEFAULT_TC0_PAYLOAD_BYTES140,
108 1,
109 -1,
110 -1,
111 -1
112 },
113 {
114 SPRT_DEFAULT_TC1_PAYLOAD_BYTES132,
115 SPRT_DEFAULT_TC1_WINDOWS_SIZE32,
116 SPRT_DEFAULT_TIMER_TC1_TA0190000,
117 SPRT_DEFAULT_TIMER_TC1_TA02130000,
118 SPRT_DEFAULT_TIMER_TC1_TR03500000
119 },
120 {
121 SPRT_DEFAULT_TC2_PAYLOAD_BYTES132,
122 SPRT_DEFAULT_TC2_WINDOWS_SIZE8,
123 SPRT_DEFAULT_TIMER_TC2_TA0190000,
124 SPRT_DEFAULT_TIMER_TC2_TA02500000,
125 SPRT_DEFAULT_TIMER_TC2_TR03500000
126 },
127 {
128 SPRT_DEFAULT_TC3_PAYLOAD_BYTES140,
129 1,
130 -1,
131 -1,
132 -1
133 }
134};
135
136SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * sprt_transmission_channel_to_str(int channel)
137{
138 const char *res;
139
140 res = "unknown";
141 switch (channel)
142 {
143 case SPRT_TCID_UNRELIABLE_UNSEQUENCED:
144 res = "unreliable unsequenced";
145 break;
146 case SPRT_TCID_RELIABLE_SEQUENCED:
147 res = "reliable sequenced";
148 break;
149 case SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED:
150 res = "expedited reliable sequenced";
151 break;
152 case SPRT_TCID_UNRELIABLE_SEQUENCED:
153 res = "unreliable sequenced";
154 break;
155 }
156 /*endswitch*/
157 return res;
158}
159/*- End of function --------------------------------------------------------*/
160
161static int update_timer(sprt_state_t *s)
162{
163 span_timestamp_t shortest;
164 uint8_t first;
165 int i;
166 int shortest_is;
167
168 if (s->tx.immediate_timer)
169 {
170 shortest = 1;
171 shortest_is = 4;
172 }
173 else
174 {
175 /* Find the earliest expiring of the active timers, and set the timeout to that. */
176 shortest = ~0;
177 shortest_is = 0;
178 /* There's a single ACK holdoff timer */
179 if (s->tx.ta01_timer != 0 && s->tx.ta01_timer < shortest)
180 {
181 shortest = s->tx.ta01_timer;
182 shortest_is = 1;
183 }
184 /*endif*/
185 for (i = SPRT_TCID_MIN_RELIABLE; i <= SPRT_TCID_MAX_RELIABLE; i++)
186 {
187 /* There's a keepalive timer for each reliable channel. These are only active
188 after the channel is used for the first time, and stay active until shutdown. */
189 if (s->tx.chan[i].ta02_timer != 0 && s->tx.chan[i].ta02_timer < shortest)
190 {
191 shortest = s->tx.chan[i].ta02_timer;
192 shortest_is = 2 + 10*i;
193 }
194 /*endif*/
195 /* There are per slot timers for all the buffer slots for a reliable channel, but they are
196 sorted, so we already know which is the sortest one. */
197 if ((first = s->tx.chan[i].first_in_time) != TR03_QUEUE_FREE_SLOT_TAG0xFFU)
198 {
199 if (s->tx.chan[i].tr03_timer[first] != 0 && s->tx.chan[i].tr03_timer[first] < shortest)
200 {
201 shortest = s->tx.chan[i].tr03_timer[first];
202 shortest_is = 3 + 10*i;
203 }
204 /*endif*/
205 }
206 /*endif*/
207 }
208 /*endfor*/
209 /* If we haven't shrunk shortest from maximum, we have no timer to set, so we stop the timer,
210 if its set. */
211 if (shortest == ~0)
212 shortest = 0;
213 /*endif*/
214 }
215 /*endif*/
216 span_log(&s->logging, SPAN_LOG_FLOW, "Update timer to %lu (%d)\n", shortest, shortest_is);
217 s->latest_timer = shortest;
218 if (s->timer_handler)
219 s->timer_handler(s->timer_user_data, s->latest_timer);
220 /*endif*/
221 return 0;
222}
223/*- End of function --------------------------------------------------------*/
224
225static void delete_timer_queue_entry(sprt_state_t *s, int channel, int slot)
226{
227 if (s->tx.chan[channel].first_in_time == TR03_QUEUE_FREE_SLOT_TAG0xFFU || slot == TR03_QUEUE_FREE_SLOT_TAG0xFFU)
228 return;
229 /*endif*/
230
231 if (s->tx.chan[channel].first_in_time == slot)
232 {
233 /* Delete from the head of the list */
234 s->tx.chan[channel].first_in_time = s->tx.chan[channel].next_in_time[slot];
235 }
236 else
237 {
238 s->tx.chan[channel].next_in_time[s->tx.chan[channel].prev_in_time[slot]] = s->tx.chan[channel].next_in_time[slot];
239 }
240 /*endif*/
241
242 if (s->tx.chan[channel].last_in_time == slot)
243 {
244 /* Delete from the end of the list */
245 s->tx.chan[channel].last_in_time = s->tx.chan[channel].prev_in_time[slot];
246 }
247 else
248 {
249 s->tx.chan[channel].prev_in_time[s->tx.chan[channel].next_in_time[slot]] = s->tx.chan[channel].prev_in_time[slot];
250 }
251 /*endif*/
252
253 s->tx.chan[channel].prev_in_time[slot] = TR03_QUEUE_FREE_SLOT_TAG0xFFU;
254 s->tx.chan[channel].next_in_time[slot] = TR03_QUEUE_FREE_SLOT_TAG0xFFU;
255}
256/*- End of function --------------------------------------------------------*/
257
258static void add_timer_queue_last_entry(sprt_state_t *s, int channel, int slot)
259{
260 if (s->tx.chan[channel].last_in_time == TR03_QUEUE_FREE_SLOT_TAG0xFFU)
261 {
262 /* The list is empty, so link both ways */
263 s->tx.chan[channel].first_in_time = slot;
264 }
265 else
266 {
267 s->tx.chan[channel].next_in_time[s->tx.chan[channel].last_in_time] = slot;
268 }
269 /*endif*/
270 s->tx.chan[channel].prev_in_time[slot] = s->tx.chan[channel].last_in_time;
271 s->tx.chan[channel].next_in_time[slot] = TR03_QUEUE_FREE_SLOT_TAG0xFFU;
272 s->tx.chan[channel].last_in_time = slot;
273}
274/*- End of function --------------------------------------------------------*/
275
276static int build_and_send_packet(sprt_state_t *s,
277 int channel,
278 uint16_t seq_no,
279 const uint8_t payload[],
280 int payload_len)
281{
282 int i;
283 int len;
284 int noa;
285 uint8_t pkt[SPRT_MAX_PACKET_BYTES(12 + 256)];
286
287 pkt[0] = s->tx.subsession_id;
288 pkt[1] = s->tx.payload_type;
289 put_net_unaligned_uint16(&pkt[2], (channel << 14) | (seq_no & SPRT_SEQ_NO_MASK0x3FFF));
290 /* The header is of variable length, depending how many of the zero to three acknowledgement
291 slots are in use */
292 len = 6;
293 noa = 0;
294 if (s->tx.ack_queue_ptr > 0)
295 {
296 for (i = 0; i < s->tx.ack_queue_ptr; i++)
297 {
298 put_net_unaligned_uint16(&pkt[len], s->tx.ack_queue[i]);
299 len += 2;
300 noa++;
301 }
302 /*endfor*/
303 s->tx.ack_queue_ptr = 0;
304 s->tx.ta01_timer = 0;
305 span_log(&s->logging, SPAN_LOG_FLOW, "TA01 cancelled\n");
306 }
307 /*endif*/
308 /* The base sequence number only varies for the reliable channels. It is always zero
309 for the unrelaible channels. */
310 put_net_unaligned_uint16(&pkt[4], (noa << 14) | s->rx.chan[channel].base_sequence_no);
311 /* If this is purely an acknowledgement packet, there will be no actual message */
312 if (payload_len > 0)
313 {
314 memcpy(&pkt[len], payload, payload_len);
315 len += payload_len;
316 }
317 /*endif*/
318 span_log_buf(&s->logging, SPAN_LOG_FLOW, "Tx", pkt, len);
319 if (s->tx_packet_handler)
320 s->tx_packet_handler(s->tx_user_data, pkt, len);
321 /*endif*/
322 update_timer(s);
323 return len;
324}
325/*- End of function --------------------------------------------------------*/
326
327static int queue_acknowledgement(sprt_state_t *s, int channel, uint16_t sequence_no)
328{
329 uint16_t entry;
330 bool_Bool found;
331 int i;
332
333 if (s->tx.ack_queue_ptr >= 3)
334 {
335 /* The ack queue is already full. This should never happen. It is an internal error
336 in this software. */
337 span_log(&s->logging, SPAN_LOG_ERROR, "ACK queue overflow\n");
338 /* I guess push out the queued ACKs at this point is better than the alternatives */
339 build_and_send_packet(s, channel, 0, NULL((void*)0), 0);
340 }
341 /*endif*/
342 entry = (channel << 14) | sequence_no;
343 /* See if we have already queued a response for this sequence number. If the other end
344 likes to send its packets in repeating bursts this may happen. */
345 found = false0;
346 for (i = 0; i < s->tx.ack_queue_ptr; i++)
347 {
348 if (s->tx.ack_queue[i] == entry)
349 {
350 found = true1;
351 break;
352 }
353 /*endif*/
354 }
355 /*endfor*/
356 if (!found)
357 {
358 s->tx.ack_queue[s->tx.ack_queue_ptr] = entry;
359 s->tx.ack_queue_ptr++;
360 if (s->tx.ack_queue_ptr == 1)
361 {
362 /* We now have something in the queue. We need to start the timer that will push out
363 a partially filled acknowledgement queue if nothing else triggers transmission. */
364 if (s->timer_handler)
365 s->tx.ta01_timer = s->timer_handler(s->timer_user_data, ~0) + s->tx.ta01_timeout;
366 /*endif*/
367 span_log(&s->logging, SPAN_LOG_FLOW, "TA01 set to %lu\n", s->tx.ta01_timer);
368 update_timer(s);
369 }
370 else if (s->tx.ack_queue_ptr >= 3)
371 {
372 /* The ACK queue is now full, so push an ACK only packet to clear it. */
373 build_and_send_packet(s, channel, 0, NULL((void*)0), 0);
374 }
375 /*endif*/
376 }
377 /*endif*/
378 return 0;
379}
380/*- End of function --------------------------------------------------------*/
381
382static bool_Bool retransmit_the_unacknowledged(sprt_state_t *s, int channel, span_timestamp_t now)
383{
384 uint8_t first;
385 sprt_chan_t *chan;
386 bool_Bool something_was_sent;
387 int diff;
388 uint16_t seq_no;
389
390 something_was_sent = false0;
391 if (channel >= SPRT_TCID_MIN_RELIABLE && channel <= SPRT_TCID_MAX_RELIABLE)
392 {
393 chan = &s->tx.chan[channel];
394 while ((first = chan->first_in_time) != TR03_QUEUE_FREE_SLOT_TAG0xFFU
395 &&
396 chan->tr03_timer[first] <= now)
397 {
398 diff = chan->buff_in_ptr - first;
399 if (diff < 0)
400 diff += chan->window_size;
401 /*endif*/
402 seq_no = chan->queuing_sequence_no - diff;
403 if (chan->buff_len[first] != SPRT_LEN_SLOT_FREE0xFFFF)
404 {
405 build_and_send_packet(s,
406 channel,
407 seq_no,
408 &chan->buff[first*chan->max_payload_bytes],
409 chan->buff_len[first]);
410 something_was_sent = true1;
411 }
412 else
413 {
414 span_log(&s->logging, SPAN_LOG_ERROR, "Empty slot scheduled %d %d\n", first, chan->buff_len[first]);
415 }
416 /*endif*/
417 delete_timer_queue_entry(s, channel, first);
418 chan->remaining_tries[first]--;
419 if (chan->remaining_tries[first] <= 0)
420 {
421 /* TODO: take action on too many retries */
422 if (s->status_handler)
423 s->status_handler(s->status_user_data, SPRT_STATUS_EXCESS_RETRIES);
424 /*endif*/
425 }
426 else
427 {
428 /* Update the timestamp, and requeue the packet */
429 chan->tr03_timer[first] += chan->tr03_timeout;
430 add_timer_queue_last_entry(s, channel, first);
431 }
432 /*endif*/
433 }
434 /*endif*/
435 }
436 /*endif*/
437 return something_was_sent;
438}
439/*- End of function --------------------------------------------------------*/
440
441static void process_acknowledgements(sprt_state_t *s, int noa, int tcn[3], int sqn[3])
442{
443 int i;
444 int slot;
445 int ptr;
446 int diff;
447 int channel;
448 sprt_chan_t *chan;
449
450 /* Process the set of 1 to 3 acknowledgements from a received SPRT packet */
451 if (noa > 0)
452 span_log(&s->logging, SPAN_LOG_FLOW, "Received %d acknowledgements\n", noa);
453 /*endif*/
454 for (i = 0; i < noa; i++)
455 {
456 channel = tcn[i];
457 span_log(&s->logging, SPAN_LOG_FLOW, "ACK received for channel %s, seq no %d\n", sprt_transmission_channel_to_str(tcn[i]), sqn[i]);
458 chan = &s->tx.chan[channel];
459 switch (channel)
460 {
461 case SPRT_TCID_RELIABLE_SEQUENCED:
462 case SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED:
463 diff = (chan->queuing_sequence_no - sqn[i]) & SPRT_SEQ_NO_MASK0x3FFF;
464 if (diff < chan->window_size)
465 {
466 /* Find this sequence no in the buffer */
467 slot = chan->buff_in_ptr - diff;
468 if (slot < 0)
469 slot += chan->window_size;
470 /*endif*/
471 if (chan->buff_len[slot] != SPRT_LEN_SLOT_FREE0xFFFF)
472 {
473 /* This packet is no longer needed. We can clear the buffer slot. */
474 span_log(&s->logging, SPAN_LOG_FLOW, "Slot OK %d/%d contains %d [%d, %d]\n", channel, slot, sqn[i], chan->queuing_sequence_no, chan->buff_in_ptr);
475 chan->buff_len[slot] = SPRT_LEN_SLOT_FREE0xFFFF;
476 /* TODO: We are deleting the resend timer here, without updating the next timeout. This
477 should be harmless. However, the spurious timeouts it may result in seems messy. */
478 chan->tr03_timer[slot] = 0;
479 span_log(&s->logging, SPAN_LOG_FLOW, "TR03(%d)[%d] cancelled\n", channel, slot);
480 delete_timer_queue_entry(s, channel, slot);
481 ptr = chan->buff_acked_out_ptr;
482 if (slot == ptr)
483 {
484 /* This is the next packet in sequence to be delivered. So, we can now drop it, and
485 anything following which may have already been ACKed, until we reach something
486 which has not been ACKed, or we have emptied the buffer. */
487 do
488 {
489 if (++ptr >= chan->window_size)
490 ptr = 0;
491 /*endif*/
492 }
493 while (ptr != chan->buff_in_ptr && chan->buff_len[ptr] == SPRT_LEN_SLOT_FREE0xFFFF);
494 chan->buff_acked_out_ptr = ptr;
495 }
496 /*endif*/
497 }
498 else
499 {
500 /* This slot might be free, because we received an ACK already (e.g. if we got a late ACK
501 after sending a retransmission, and now we have the ACK from the retransmission). This
502 can be ignored.
503 The slot might have a new sequence number in it, and we are getting a late ACK for the
504 sequence number it contained before. It should be best to ignore this too. */
505 span_log(&s->logging, SPAN_LOG_FLOW, "Slot BAD %d/%d does not contain %d [%d, %d]\n", channel, slot, sqn[i], chan->queuing_sequence_no, chan->buff_in_ptr);
506 }
507 /*endif*/
508 }
509 else
510 {
511 /* This slot might be free, because we received an ACK already (e.g. if we got a late ACK
512 after sending a retransmission, and now we have the ACK from the retransmission). This
513 can be ignored.
514 The slot might have a new sequence number in it, and we are getting a late ACK for the
515 sequence number it contained before. It should be best to ignore this too. */
516 span_log(&s->logging, SPAN_LOG_FLOW, "Slot BAD %d This is an ack for something outside the current window - %d %d\n", channel, chan->queuing_sequence_no, sqn[i]);
517 }
518 /*endif*/
519 break;
520 case SPRT_TCID_UNRELIABLE_UNSEQUENCED:
521 case SPRT_TCID_UNRELIABLE_SEQUENCED:
522 /* Getting here means we have an acknowledgement for an unreliable packet. This should never happen. The received packet has a problem. */
523 span_log(&s->logging,
524 SPAN_LOG_FLOW,
525 "Acknowledgement received for unreliable channel %s\n",
526 sprt_transmission_channel_to_str(channel));
527 break;
528 }
529 /*endswitch*/
530 }
531 /*endfor*/
532}
533/*- End of function --------------------------------------------------------*/
534
535static int sprt_deliver(sprt_state_t *s)
536{
537 int channel;
538 int iptr;
539 sprt_chan_t *chan;
540
541 for (channel = SPRT_TCID_MIN_RELIABLE; channel <= SPRT_TCID_MAX_RELIABLE; channel++)
542 {
543 chan = &s->rx.chan[channel];
544 iptr = chan->buff_in_ptr;
545 while (chan->buff_len[iptr] != SPRT_LEN_SLOT_FREE0xFFFF)
546 {
547 /* We need to check for busy before delivering each packet, in case the app applied
548 flow control between packets. */
549 if (chan->busy)
550 break;
551 /*endif*/
552 /* Deliver the body of the message */
553 if (s->rx_delivery_handler)
554 s->rx_delivery_handler(s->rx_user_data, channel, chan->base_sequence_no, &chan->buff[iptr*chan->max_payload_bytes], chan->buff_len[iptr]);
555 /*endif*/
556 chan->base_sequence_no = (chan->base_sequence_no + 1) & SPRT_SEQ_NO_MASK0x3FFF;
557 chan->buff_len[iptr] = SPRT_LEN_SLOT_FREE0xFFFF;
558 if (++iptr >= chan->window_size)
559 iptr = 0;
560 /*endif*/
561 }
562 /*endwhile*/
563 /* Only change the pointer now we have really finished. */
564 chan->buff_in_ptr = iptr;
565 }
566 /*endfor*/
567 return 0;
568}
569/*- End of function --------------------------------------------------------*/
570
571SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_timer_expired(sprt_state_t *s, span_timestamp_t now)
572{
573 int i;
574 bool_Bool something_was_sent_for_channel;
575 bool_Bool something_was_sent;
576
577 span_log(&s->logging, SPAN_LOG_FLOW, "Timer expired at %lu\n", now);
578
579 if (now < s->latest_timer)
580 {
581 span_log(&s->logging, SPAN_LOG_FLOW, "Timer returned %luus early\n", s->latest_timer - now);
582 /* Request the same timeout point again. */
583 if (s->timer_handler)
584 s->timer_handler(s->timer_user_data, s->latest_timer);
585 /*endif*/
586 return 0;
587 }
588 /*endif*/
589
590 something_was_sent = false0;
591
592 if (s->tx.immediate_timer)
593 {
594 s->tx.immediate_timer = false0;
595 sprt_deliver(s);
596 }
597 /*endif*/
598
599 for (i = SPRT_TCID_MIN_RELIABLE; i <= SPRT_TCID_MAX_RELIABLE; i++)
600 {
601 something_was_sent_for_channel = retransmit_the_unacknowledged(s, i, now);
602 /* There's a keepalive timer for each reliable channel. We only need to send a keepalive if we
603 didn't just send a retransmit for this channel. */
604 if (s->tx.chan[i].ta02_timer != 0)
605 {
606 if (s->tx.chan[i].ta02_timer <= now && !something_was_sent_for_channel)
607 {
608 /* Send a keepalive packet for this channel. */
609 span_log(&s->logging, SPAN_LOG_FLOW, "Keepalive only packet sent\n");
610 build_and_send_packet(s, i, 0, NULL((void*)0), 0);
611 something_was_sent_for_channel = true1;
612 }
613 /*endif*/
614 if (something_was_sent_for_channel)
615 {
616 s->tx.chan[i].ta02_timer = now + s->tx.chan[i].ta02_timeout;
617 span_log(&s->logging, SPAN_LOG_FLOW, "TA02(%d) set to %lu\n", i, s->tx.chan[i].ta02_timer);
618 }
619 /*endif*/
620 }
621 /*endif*/
622 if (something_was_sent_for_channel)
623 something_was_sent = true1;
624 /*endif*/
625 }
626 /*endfor*/
627
628 /* There's a single ACK holdoff timer, which applies to all channels. */
629 /* We only need to push ACKs if we haven't yet pushed out a packet for any channel during this
630 timer expired processing. */
631 if (!something_was_sent && s->tx.ta01_timer != 0 && s->tx.ta01_timer <= now)
632 {
633 /* Push any outstanding ACKs and we are done. We don't need to start a new timing operation. */
634 if (s->tx.ack_queue_ptr > 0)
635 {
636 /* Push an ACK only packet */
637 span_log(&s->logging, SPAN_LOG_FLOW, "ACK only packet sent\n");
638 build_and_send_packet(s, SPRT_TCID_UNRELIABLE_UNSEQUENCED, 0, NULL((void*)0), 0);
639 something_was_sent = true1;
Value stored to 'something_was_sent' is never read
640 }
641 /*endif*/
642 }
643 /*endif*/
644 update_timer(s);
645 return 0;
646}
647/*- End of function --------------------------------------------------------*/
648
649static void sprt_rx_reinit(sprt_state_t *s)
650{
651 /* TODO */
652}
653/*- End of function --------------------------------------------------------*/
654
655SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_rx_packet(sprt_state_t *s, const uint8_t pkt[], int len)
656{
657 int i;
658 int header_extension_bit;
659 int reserved_bit;
660 uint8_t subsession_id;
661 uint8_t payload_type;
662 int channel;
663 uint16_t base_sequence_no;
664 uint16_t sequence_no;
665 int noa;
666 int tcn[3];
667 int sqn[3];
668 int header_len;
669 int payload_len;
670 int iptr;
671 int diff;
672 sprt_chan_t *chan;
673
674 span_log_buf(&s->logging, SPAN_LOG_FLOW, "Rx", pkt, len);
675 /* An SPRT packet has 3 essential components: A base sequence number, some ACKs and a payload.
676 - A packet with no ACKs or payload is a keepalive. Its there to report the continued existance
677 of the far end, and to report the far end's base sequence number for a reliable channel.
678 - A packet with ACKs and no payload performs the above, and also ACKs one or more reliable
679 packets in the other direction.
680 - A packet with a payload does all of the above, with some data as well. There might be zero
681 things to ACK. */
682 if (len < 6)
683 {
684 span_log(&s->logging, SPAN_LOG_FLOW, "Rx packet too short\n");
685 return -1;
686 }
687 /*endif*/
688 header_extension_bit = (pkt[0] >> 7) & 1;
689 reserved_bit = (pkt[1] >> 7) & 1;
690 subsession_id = pkt[0] & 0x7F;
691 payload_type = pkt[1] & 0x7F;
692
693 if (header_extension_bit != 0 || reserved_bit != 0)
694 {
695 /* This doesn't look like an SPRT packet */
696 span_log(&s->logging, SPAN_LOG_FLOW, "Rx packet header does not look like SPRT\n");
697 return -1;
698 }
699 /*endif*/
700 if (payload_type != s->rx.payload_type)
701 {
702 /* This is not the payload type we are looking for */
703 span_log(&s->logging, SPAN_LOG_FLOW, "Rx payload type %d, expected %d\n", payload_type, s->rx.payload_type);
704 return -1;
705 }
706 /*endif*/
707 if (s->rx.subsession_id == 0xFF)
708 {
709 /* This is the first subsession ID we have seen, so accept it going forwards as the
710 subsession ID to be expected for future packets. The spec says the IDs start at zero,
711 so if both sides started up together the subsession ID on both sides should probably be
712 in sync, but is this guaranteed? Should the subsession ID we send match the one we
713 receive? */
714 s->rx.subsession_id = subsession_id;
715 }
716 else
717 {
718 if (subsession_id != s->rx.subsession_id)
719 {
720 /* This doesn't look good. We have a new subsession ID. The payload type field check out
721 OK. What other integrity checks can we make, to check we are seeing sane packets from
722 a new subsession ID, rather than garbage? */
723 span_log(&s->logging, SPAN_LOG_FLOW, "Rx subsession ID %d, expected %d\n", subsession_id, s->rx.subsession_id);
724 if (s->status_handler)
725 s->status_handler(s->status_user_data, SPRT_STATUS_SUBSESSION_CHANGED);
726 /*endif*/
727 sprt_rx_reinit(s);
728 return -1;
729 }
730 /*endif*/
731 }
732 /*endif*/
733 /* The packet's framework looks OK, so let's process its contents */
734 channel = (pkt[2] >> 6) & 3;
735 sequence_no = get_net_unaligned_uint16(&pkt[2]) & SPRT_SEQ_NO_MASK0x3FFF;
736 noa = (pkt[4] >> 6) & 3;
737 chan = &s->rx.chan[channel];
738
739 /* Deal with the keepalive and base sequence no reporting aspects of the packet */
740 base_sequence_no = get_net_unaligned_uint16(&pkt[4]) & SPRT_SEQ_NO_MASK0x3FFF;
741 if (s->tx.chan[channel].busy)
742 {
743 if (s->tx.chan[channel].base_sequence_no != base_sequence_no)
744 span_log(&s->logging, SPAN_LOG_FLOW, "BSN for channel %d changed from %u to %u\n", channel, s->tx.chan[channel].base_sequence_no, base_sequence_no);
745 /*endif*/
746 }
747 /*endif*/
748 s->tx.chan[channel].base_sequence_no = base_sequence_no;
749 /* TODO: record the time the channel was last seen. */
750
751 /* Deal with the ACKs that might be present in the packet */
752 header_len = 6;
753 if (noa > 0)
754 {
755 /* There are some ACKs to process. */
756 if (len < 6 + 2*noa)
757 {
758 span_log(&s->logging, SPAN_LOG_FLOW, "Rx packet too short\n");
759 return -1;
760 }
761 /*endif*/
762 for (i = 0; i < noa; i++)
763 {
764 tcn[i] = (pkt[header_len] >> 6) & 3;
765 sqn[i] = get_net_unaligned_uint16(&pkt[header_len]) & SPRT_SEQ_NO_MASK0x3FFF;
766 header_len += 2;
767 }
768 /*endfor*/
769 process_acknowledgements(s, noa, tcn, sqn);
770 }
771 /*endif*/
772 payload_len = len - header_len;
773 span_log(&s->logging, SPAN_LOG_FLOW, "Rx ch %d seq %d noa %d len %d\n", channel, sequence_no, noa, payload_len);
774 /* Deal with the payload, if any, in the packet */
775 /* V.150.1 says SPRT_TCID_UNRELIABLE_UNSEQUENCED should be used for ACK only packets, but in the real
776 world you should expect any of the transport channel IDs. These ACK only packets have the sequence
777 number set to zero, regardless of where the sequence number for that channel currently stands.
778 (figure B.3/V.150.1) */
779 if (payload_len > 0)
780 {
781 /* There is a payload to process */
782 if (payload_len > chan->max_payload_bytes)
783 {
784 span_log(&s->logging, SPAN_LOG_ERROR, "Payload too long %d (%d)\n", payload_len, chan->max_payload_bytes);
785 }
786 else
787 {
788 switch (channel)
789 {
790 case SPRT_TCID_RELIABLE_SEQUENCED:
791 /* Used for data */
792 case SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED:
793 /* Used for control/signalling data */
794 if (sequence_no == chan->base_sequence_no)
795 {
796 iptr = chan->buff_in_ptr;
797 queue_acknowledgement(s, channel, sequence_no);
798 if (chan->busy)
799 {
800 /* We can't deliver this right now, so we need to store it at the head of the buffer */
801 memcpy(&chan->buff[iptr*chan->max_payload_bytes], pkt + header_len, payload_len);
802 chan->buff_len[iptr] = payload_len;
803 }
804 else
805 {
806 /* This is exactly the next packet in sequence, so deliver it. */
807 if (s->rx_delivery_handler)
808 s->rx_delivery_handler(s->rx_user_data, channel, sequence_no, pkt + header_len, payload_len);
809 /*endif*/
810 chan->base_sequence_no = (chan->base_sequence_no + 1) & SPRT_SEQ_NO_MASK0x3FFF;
811 chan->buff_len[iptr] = SPRT_LEN_SLOT_FREE0xFFFF;
812 if (++iptr >= chan->window_size)
813 iptr = 0;
814 /*endif*/
815 /* See if there are any contiguously following packets in the buffer, which can be delivered immediately. */
816 while (chan->buff_len[iptr] != SPRT_LEN_SLOT_FREE0xFFFF)
817 {
818 /* We need to check for busy before delivering each packet, in case the app applied
819 flow control between packets. */
820 if (chan->busy)
821 break;
822 /*endif*/
823 /* Deliver the body of the message */
824 if (s->rx_delivery_handler)
825 s->rx_delivery_handler(s->rx_user_data, channel, chan->base_sequence_no, &chan->buff[iptr*chan->max_payload_bytes], chan->buff_len[iptr]);
826 /*endif*/
827 chan->base_sequence_no = (chan->base_sequence_no + 1) & SPRT_SEQ_NO_MASK0x3FFF;
828 chan->buff_len[iptr] = SPRT_LEN_SLOT_FREE0xFFFF;
829 if (++iptr >= chan->window_size)
830 iptr = 0;
831 /*endif*/
832 }
833 /*endwhile*/
834 /* Only change the pointer now we have really finished. */
835 chan->buff_in_ptr = iptr;
836 }
837 /*endif*/
838 }
839 else
840 {
841 /* This packet is out of sequence, so there may have been some packets lost somewhere. If the
842 packet is older than the last delivered one it must be a repeat. If its beyond the last
843 delievered packet it might be inside or outside the window. We store it if its within the
844 window, so we can deliver it later, when we have the missing intermediate packets. If its
845 later than the window we have to drop it, as we have nowhere to store it. */
846 /* TODO: we probably shouldn't ACK a packet we drop because its beyond the window. */
847 diff = (sequence_no - chan->base_sequence_no) & SPRT_SEQ_NO_MASK0x3FFF;
848 if (diff < chan->window_size)
849 {
850 queue_acknowledgement(s, channel, sequence_no);
851 iptr = chan->buff_in_ptr + diff;
852 if (iptr >= chan->window_size)
853 iptr -= chan->window_size;
854 /*endif*/
855 memcpy(&chan->buff[iptr*chan->max_payload_bytes], pkt + header_len, payload_len);
856 chan->buff_len[iptr] = payload_len;
857 }
858 else if (diff > 2*SPRT_MAX_WINDOWS_SIZE96)
859 {
860 /* This is an older packet, or something far in the future. We should acknowledge it, as
861 its probably a repeat for a packet where the far end missed the previous ACK we sent. */
862 queue_acknowledgement(s, channel, sequence_no);
863 if (s->status_handler)
864 s->status_handler(s->status_user_data, SPRT_STATUS_OUT_OF_SEQUENCE);
865 /*endif*/
866 }
867 else
868 {
869 /* This is a little too far into the future of packets (i.e. just beyond the window).
870 We should not acknowledge it, as the far end will think we have delivered the packet. */
871 }
872 /*endif*/
873 }
874 /*endif*/
875 chan->active = true1;
876 break;
877 case SPRT_TCID_UNRELIABLE_UNSEQUENCED:
878 /* Used for ack only */
879 /* The payload length should always be zero, although it isn't if we are here. Is this
880 erroneous? Its not quite clear from the spec. */
881 case SPRT_TCID_UNRELIABLE_SEQUENCED:
882 /* Used for sequenced data that does not require reliable delivery */
883 /* We might have missed one or more packets, so this may or may not be the next packet in sequence. We have
884 no way to fix this, so just deliver the payload. */
885 /* TODO: This might be a repeat of the last packet, if the sender tries to achieve redundancy by multiple sends.
886 should try to avoid delivering the same packet multiple times. */
887 /* Deliver the payload of the message */
888 if (s->rx_delivery_handler)
889 s->rx_delivery_handler(s->rx_user_data, channel, sequence_no, pkt + header_len, payload_len);
890 /*endif*/
891 chan->active = true1;
892 break;
893 }
894 /*endswitch*/
895 }
896 /*endif*/
897 }
898 /*endif*/
899 return 0;
900}
901/*- End of function --------------------------------------------------------*/
902
903SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_tx(sprt_state_t *s, int channel, const uint8_t payload[], int len)
904{
905 int real_len;
906 int iptr;
907 int optr;
908 uint16_t seq_no;
909 sprt_chan_t *chan;
910
911 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
912 return -1;
913 /*endif*/
914 chan = &s->tx.chan[channel];
915 /* Is the length in range for this particular channel? */
916 if (len <= 0 || len > chan->max_payload_bytes)
917 return -1;
918 /*endif*/
919 switch (channel)
920 {
921 case SPRT_TCID_RELIABLE_SEQUENCED:
922 case SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED:
923 /* We need to queue this message, and set the retry timer for it, so we can handle ACKs and retransmissions. We also need to send it now. */
924 /* Snapshot the values (although only optr should be changeable during this processing) */
925 iptr = chan->buff_in_ptr;
926 optr = chan->buff_acked_out_ptr;
927 if ((real_len = optr - iptr - 1) < 0)
928 real_len += chan->window_size;
929 /*endif*/
930 if (real_len < 1)
931 {
932 /* Queue full */
933 return -1;
934 }
935 /*endif*/
936 memcpy(&chan->buff[iptr*chan->max_payload_bytes], payload, len);
937 chan->buff_len[iptr] = len;
938 seq_no = chan->queuing_sequence_no;
939 chan->queuing_sequence_no = (chan->queuing_sequence_no + 1) & SPRT_SEQ_NO_MASK0x3FFF;
940 if (s->timer_handler)
941 chan->tr03_timer[iptr] = s->timer_handler(s->timer_user_data, ~0) + chan->tr03_timeout;
942 /*endif*/
943 span_log(&s->logging, SPAN_LOG_FLOW, "TR03(%d)[%d] set to %lu\n", channel, iptr, chan->tr03_timer[iptr]);
944 chan->remaining_tries[iptr] = chan->max_tries;
945 add_timer_queue_last_entry(s, channel, iptr);
946 if (++iptr >= chan->window_size)
947 iptr = 0;
948 /*endif*/
949 /* Only change the pointer now we have really finished. */
950 chan->buff_in_ptr = iptr;
951 /* If this is the first activity on this channel, we get the TA02 timer started for
952 this channel. If the channel is already active we will adjust the timout. */
953 if (s->timer_handler)
954 chan->ta02_timer = s->timer_handler(s->timer_user_data, ~0) + chan->ta02_timeout;
955 /*endif*/
956 span_log(&s->logging, SPAN_LOG_FLOW, "TA02(%d) set to %lu\n", channel, chan->ta02_timer);
957 /* Now send the first copy */
958 build_and_send_packet(s, channel, seq_no, payload, len);
959 break;
960 case SPRT_TCID_UNRELIABLE_UNSEQUENCED:
961 /* It is not clear from the spec if this channel should ever carry data. Table B.1 says
962 the channel is "Used for acknowledgements only", and yet Table B.2 defines a parameter
963 SPRT_TC0_PAYLOAD_BYTES which is non-zero. */
964 /* There is no reason to buffer this. Send it straight out. */
965 build_and_send_packet(s, channel, 0, payload, len);
966 break;
967 case SPRT_TCID_UNRELIABLE_SEQUENCED:
968 /* There is no reason to buffer this. Send it straight out. */
969 build_and_send_packet(s, channel, chan->queuing_sequence_no, payload, len);
970 chan->queuing_sequence_no = (chan->queuing_sequence_no + 1) & SPRT_SEQ_NO_MASK0x3FFF;
971 break;
972 }
973 /*endswitch*/
974 return 0;
975}
976/*- End of function --------------------------------------------------------*/
977
978SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_set_local_tc_windows_size(sprt_state_t *s, int channel, int size)
979{
980 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
981 return -1;
982 /*endif*/
983 if (size < channel_parm_limits[channel].min_window_size
984 ||
985 size > channel_parm_limits[channel].max_window_size)
986 {
987 return -1;
988 }
989 /*endif*/
990 s->rx.chan[channel].window_size = size;
991 return 0;
992}
993/*- End of function --------------------------------------------------------*/
994
995SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_get_local_tc_windows_size(sprt_state_t *s, int channel)
996{
997 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
998 return -1;
999 /*endif*/
1000 return s->rx.chan[channel].window_size;
1001}
1002/*- End of function --------------------------------------------------------*/
1003
1004SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_set_local_tc_payload_bytes(sprt_state_t *s, int channel, int max_len)
1005{
1006 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
1007 return -1;
1008 /*endif*/
1009 if (max_len < channel_parm_limits[channel].min_payload_bytes
1010 ||
1011 max_len > channel_parm_limits[channel].max_payload_bytes)
1012 {
1013 return -1;
1014 }
1015 /*endif*/
1016 s->rx.chan[channel].max_payload_bytes = max_len;
1017 return 0;
1018}
1019/*- End of function --------------------------------------------------------*/
1020
1021SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_get_local_tc_payload_bytes(sprt_state_t *s, int channel)
1022{
1023 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
1024 return -1;
1025 /*endif*/
1026 return s->rx.chan[channel].max_payload_bytes;
1027}
1028/*- End of function --------------------------------------------------------*/
1029
1030SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_set_local_tc_max_tries(sprt_state_t *s, int channel, int max_tries)
1031{
1032 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
1033 return -1;
1034 /*endif*/
1035 if (max_tries < SPRT_MIN_MAX_TRIES1
1036 ||
1037 max_tries > SPRT_MAX_MAX_TRIES20)
1038 {
1039 return -1;
1040 }
1041 /*endif*/
1042 s->tx.chan[channel].max_tries = max_tries;
1043 return 0;
1044}
1045/*- End of function --------------------------------------------------------*/
1046
1047SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_get_local_tc_max_tries(sprt_state_t *s, int channel)
1048{
1049 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
1050 return -1;
1051 /*endif*/
1052 return s->tx.chan[channel].max_tries;
1053}
1054/*- End of function --------------------------------------------------------*/
1055
1056SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_set_far_tc_windows_size(sprt_state_t *s, int channel, int size)
1057{
1058 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
1059 return -1;
1060 /*endif*/
1061 if (size < channel_parm_limits[channel].min_window_size
1062 ||
1063 size > channel_parm_limits[channel].max_window_size)
1064 {
1065 return -1;
1066 }
1067 /*endif*/
1068 s->tx.chan[channel].window_size = size;
1069 return 0;
1070}
1071/*- End of function --------------------------------------------------------*/
1072
1073SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_get_far_tc_windows_size(sprt_state_t *s, int channel)
1074{
1075 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
1076 return -1;
1077 /*endif*/
1078 return s->tx.chan[channel].window_size;
1079}
1080/*- End of function --------------------------------------------------------*/
1081
1082SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_set_far_tc_payload_bytes(sprt_state_t *s, int channel, int max_len)
1083{
1084 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
1085 return -1;
1086 /*endif*/
1087 if (max_len < channel_parm_limits[channel].min_payload_bytes
1088 ||
1089 max_len > channel_parm_limits[channel].max_payload_bytes)
1090 {
1091 return -1;
1092 }
1093 /*endif*/
1094 s->tx.chan[channel].max_payload_bytes = max_len;
1095 return 0;
1096}
1097/*- End of function --------------------------------------------------------*/
1098
1099SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_get_far_tc_payload_bytes(sprt_state_t *s, int channel)
1100{
1101 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
1102 return -1;
1103 /*endif*/
1104 return s->tx.chan[channel].max_payload_bytes;
1105}
1106/*- End of function --------------------------------------------------------*/
1107
1108SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_set_tc_timeout(sprt_state_t *s, int channel, int timer, int timeout)
1109{
1110 switch (timer)
1111 {
1112 case SPRT_TIMER_TA01:
1113 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
1114 return -1;
1115 /*endif*/
1116 s->tx.ta01_timeout = timeout;
1117 break;
1118 case SPRT_TIMER_TA02:
1119 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
1120 return -1;
1121 /*endif*/
1122 s->tx.chan[channel].ta02_timeout = timeout;
1123 break;
1124 case SPRT_TIMER_TR03:
1125 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
1126 return -1;
1127 /*endif*/
1128 s->tx.chan[channel].tr03_timeout = timeout;
1129 break;
1130 default:
1131 return -1;
1132 }
1133 /*endswitch*/
1134 return 0;
1135}
1136/*- End of function --------------------------------------------------------*/
1137
1138SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_get_tc_timeout(sprt_state_t *s, int channel, int timer)
1139{
1140 int timeout;
1141
1142 switch (timer)
1143 {
1144 case SPRT_TIMER_TA01:
1145 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
1146 return -1;
1147 /*endif*/
1148 timeout = s->tx.ta01_timeout;
1149 break;
1150 case SPRT_TIMER_TA02:
1151 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
1152 return -1;
1153 /*endif*/
1154 timeout = s->tx.chan[channel].ta02_timeout;
1155 break;
1156 case SPRT_TIMER_TR03:
1157 if (channel < SPRT_TCID_MIN_RELIABLE || channel > SPRT_TCID_MAX_RELIABLE)
1158 return -1;
1159 /*endif*/
1160 timeout = s->tx.chan[channel].tr03_timeout;
1161 break;
1162 default:
1163 return -1;
1164 }
1165 /*endswitch*/
1166 return timeout;
1167}
1168/*- End of function --------------------------------------------------------*/
1169
1170SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_set_local_busy(sprt_state_t *s, int channel, bool_Bool busy)
1171{
1172 bool_Bool previous_busy;
1173
1174 previous_busy = false0;
1175 if (channel >= SPRT_TCID_MIN_RELIABLE && channel <= SPRT_TCID_MAX_RELIABLE)
1176 {
1177 previous_busy = s->rx.chan[channel].busy;
1178 s->rx.chan[channel].busy = busy;
1179 /* We may want to schedule an immediate callback to push out some packets
1180 which are ready for delivery, if we are removing the busy condition. */
1181 if (previous_busy && !busy)
1182 {
1183 s->tx.immediate_timer = true1;
1184 update_timer(s);
1185 }
1186 /*endif*/
1187 }
1188 /*endif*/
1189 return previous_busy;
1190}
1191/*- End of function --------------------------------------------------------*/
1192
1193SPAN_DECLARE(bool)__attribute__((visibility("default"))) _Bool sprt_get_far_busy_status(sprt_state_t *s, int channel)
1194{
1195 return s->tx.chan[channel].busy;
1196}
1197/*- End of function --------------------------------------------------------*/
1198
1199SPAN_DECLARE(logging_state_t *)__attribute__((visibility("default"))) logging_state_t * sprt_get_logging_state(sprt_state_t *s)
1200{
1201 return &s->logging;
1202}
1203/*- End of function --------------------------------------------------------*/
1204
1205SPAN_DECLARE(sprt_state_t *)__attribute__((visibility("default"))) sprt_state_t * sprt_init(sprt_state_t *s,
1206 uint8_t subsession_id,
1207 uint8_t rx_payload_type,
1208 uint8_t tx_payload_type,
1209 channel_parms_t parms[SPRT_CHANNELS4],
1210 sprt_tx_packet_handler_t tx_packet_handler,
1211 void *tx_user_data,
1212 sprt_rx_delivery_handler_t rx_delivery_handler,
1213 void *rx_user_data,
1214 sprt_timer_handler_t timer_handler,
1215 void *timer_user_data,
1216 span_modem_status_func_t status_handler,
1217 void *status_user_data)
1218{
1219 int i;
1220 int j;
1221
1222 if (rx_delivery_handler == NULL((void*)0) || tx_packet_handler == NULL((void*)0) || timer_handler == NULL((void*)0) || status_handler == NULL((void*)0))
1223 return NULL((void*)0);
1224 /*endif*/
1225 if (parms == NULL((void*)0))
1226 {
1227 parms = default_channel_parms;
1228 }
1229 else
1230 {
1231 for (i = SPRT_TCID_MIN; i <= SPRT_TCID_MAX; i++)
1232 {
1233 if (parms[i].payload_bytes < channel_parm_limits[i].min_payload_bytes
1234 ||
1235 parms[i].payload_bytes > channel_parm_limits[i].max_payload_bytes)
1236 {
1237 return NULL((void*)0);
1238 }
1239 /*endif*/
1240 if (parms[i].window_size < channel_parm_limits[i].min_window_size
1241 ||
1242 parms[i].window_size > channel_parm_limits[i].max_window_size)
1243 {
1244 return NULL((void*)0);
1245 }
1246 /*endif*/
1247 }
1248 /*endfor*/
1249 }
1250 /*endif*/
1251 if (s == NULL((void*)0))
1252 {
1253 if ((s = (sprt_state_t *) span_alloc(sizeof(*s))) == NULL((void*)0))
1254 return NULL((void*)0);
1255 /*endif*/
1256 }
1257 /*endif*/
1258 memset(s, 0, sizeof(*s));
1259
1260 span_log_init(&s->logging, SPAN_LOG_NONE, NULL((void*)0));
1261 span_log_set_protocol(&s->logging, "SPRT");
1262
1263 /* Set up all the pointers to buffers */
1264 s->tx.chan[SPRT_TCID_RELIABLE_SEQUENCED].buff = s->tc1_tx_buff;
1265 s->tx.chan[SPRT_TCID_RELIABLE_SEQUENCED].buff_len = s->tc1_tx_buff_len;
1266 s->tx.chan[SPRT_TCID_RELIABLE_SEQUENCED].tr03_timer = s->tc1_tx_tr03_timer;
1267 s->tx.chan[SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED].buff = s->tc2_tx_buff;
1268 s->tx.chan[SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED].buff_len = s->tc2_tx_buff_len;
1269 s->tx.chan[SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED].tr03_timer = s->tc2_tx_tr03_timer;
1270
1271 s->rx.chan[SPRT_TCID_RELIABLE_SEQUENCED].buff = s->tc1_rx_buff;
1272 s->rx.chan[SPRT_TCID_RELIABLE_SEQUENCED].buff_len = s->tc1_rx_buff_len;
1273 s->rx.chan[SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED].buff = s->tc2_rx_buff;
1274 s->rx.chan[SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED].buff_len = s->tc2_rx_buff_len;
1275
1276 s->rx.subsession_id = 0xFF;
1277 s->tx.subsession_id = subsession_id;
1278 s->rx.payload_type = rx_payload_type;
1279 s->tx.payload_type = tx_payload_type;
1280
1281 s->tx.ta01_timeout = default_channel_parms[SPRT_TCID_RELIABLE_SEQUENCED].timer_ta01;
1282 for (i = SPRT_TCID_MIN; i <= SPRT_TCID_MAX; i++)
1283 {
1284 s->rx.chan[i].max_payload_bytes = default_channel_parms[i].payload_bytes;
1285 s->rx.chan[i].window_size = default_channel_parms[i].window_size;
1286 s->rx.chan[i].ta02_timeout = default_channel_parms[i].timer_ta02;
1287 s->rx.chan[i].tr03_timeout = default_channel_parms[i].timer_tr03;
1288
1289 s->tx.chan[i].max_payload_bytes = default_channel_parms[i].payload_bytes;
1290 s->tx.chan[i].window_size = default_channel_parms[i].window_size;
1291 s->tx.chan[i].ta02_timeout = default_channel_parms[i].timer_ta02;
1292 s->tx.chan[i].tr03_timeout = default_channel_parms[i].timer_tr03;
1293
1294 s->tx.chan[i].max_tries = SPRT_DEFAULT_MAX_TRIES10;
1295
1296 s->rx.chan[i].base_sequence_no = 0;
1297 }
1298 /*endfor*/
1299
1300 for (i = SPRT_TCID_MIN_RELIABLE; i <= SPRT_TCID_MAX_RELIABLE; i++)
1301 {
1302 /* Initialise the sorted TR03 timeout queues */
1303 s->tx.chan[i].first_in_time = TR03_QUEUE_FREE_SLOT_TAG0xFFU;
1304 s->tx.chan[i].last_in_time = TR03_QUEUE_FREE_SLOT_TAG0xFFU;
1305
1306 for (j = 0; j < channel_parm_limits[i].max_window_size; j++)
1307 {
1308 s->rx.chan[i].buff_len[j] = SPRT_LEN_SLOT_FREE0xFFFF;
1309 s->tx.chan[i].buff_len[j] = SPRT_LEN_SLOT_FREE0xFFFF;
1310 s->tx.chan[i].prev_in_time[j] = TR03_QUEUE_FREE_SLOT_TAG0xFFU;
1311 s->tx.chan[i].next_in_time[j] = TR03_QUEUE_FREE_SLOT_TAG0xFFU;
1312 }
1313 /*endfor*/
1314 }
1315 /*endfor*/
1316
1317 s->rx_delivery_handler = rx_delivery_handler;
1318 s->tx_user_data = tx_user_data;
1319 s->tx_packet_handler = tx_packet_handler;
1320 s->rx_user_data = rx_user_data;
1321 s->timer_handler = timer_handler;
1322 s->timer_user_data = timer_user_data;
1323 s->status_handler = status_handler;
1324 s->status_user_data = status_user_data;
1325
1326 return s;
1327}
1328/*- End of function --------------------------------------------------------*/
1329
1330SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_release(sprt_state_t *s)
1331{
1332 return 0;
1333}
1334/*- End of function --------------------------------------------------------*/
1335
1336SPAN_DECLARE(int)__attribute__((visibility("default"))) int sprt_free(sprt_state_t *s)
1337{
1338 int ret;
1339
1340 ret = sprt_release(s);
1341 span_free(s);
1342 return ret;
1343}
1344/*- End of function --------------------------------------------------------*/
1345/*- End of file ------------------------------------------------------------*/