Bug Summary

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