Bug Summary

File:v150_1_sse.c
Warning:line 713, column 9
Value stored to 'f' is never read

Annotated Source Code

1/*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * v150_1_sse.c - An implementation of the SSE protocol defined in V.150.1
5 * Annex C, 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#include "spandsp/telephony.h"
43#include "spandsp/alloc.h"
44#include "spandsp/unaligned.h"
45#include "spandsp/logging.h"
46#include "spandsp/async.h"
47#include "spandsp/v150_1_sse.h"
48
49#include "spandsp/private/logging.h"
50#include "spandsp/private/v150_1_sse.h"
51
52static int v150_1_sse_tx_modem_relay_packet(v150_1_sse_state_t *s, int x, int ric, int ricinfo);
53static int v150_1_sse_tx_fax_relay_packet(v150_1_sse_state_t *s, int x, int ric, int ricinfo);
54
55SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_sse_media_state_to_str(int state)
56{
57 const char *res;
58
59 res = "unknown";
60 switch (state)
61 {
62 case V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO:
63 res = "Initial audio";
64 break;
65 case V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA:
66 res = "Voice band data";
67 break;
68 case V150_1_SSE_MEDIA_STATE_MODEM_RELAY:
69 res = "Modem relay";
70 break;
71 case V150_1_SSE_MEDIA_STATE_FAX_RELAY:
72 res = "Fax relay";
73 break;
74 case V150_1_SSE_MEDIA_STATE_TEXT_RELAY:
75 res = "Text relay";
76 break;
77 case V150_1_SSE_MEDIA_STATE_TEXT_PROBE:
78 res = "Text probe";
79 break;
80 }
81 /*endswitch*/
82 return res;
83}
84/*- End of function --------------------------------------------------------*/
85
86SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_sse_ric_to_str(int ric)
87{
88 const char *res;
89
90 res = "unknown";
91 switch (ric)
92 {
93 case V150_1_SSE_RIC_V8_CM:
94 res = "V.8 CM";
95 break;
96 case V150_1_SSE_RIC_V8_JM:
97 res = "V.8 JM";
98 break;
99 case V150_1_SSE_RIC_V32BIS_AA:
100 res = "V.32/V.32bis AA";
101 break;
102 case V150_1_SSE_RIC_V32BIS_AC:
103 res = "V.32/V.32bis AC";
104 break;
105 case V150_1_SSE_RIC_V22BIS_USB1:
106 res = "V.22bis USB1";
107 break;
108 case V150_1_SSE_RIC_V22BIS_SB1:
109 res = "V.22bis SB1";
110 break;
111 case V150_1_SSE_RIC_V22BIS_S1:
112 res = "V.22bis S1";
113 break;
114 case V150_1_SSE_RIC_V21_CH2:
115 res = "V.21 Ch2";
116 break;
117 case V150_1_SSE_RIC_V21_CH1:
118 res = "V.21 Ch1";
119 break;
120 case V150_1_SSE_RIC_V23_HIGH_CHANNEL:
121 res = "V.23 high channel";
122 break;
123 case V150_1_SSE_RIC_V23_LOW_CHANNEL:
124 res = "V.23 low channel";
125 break;
126 case V150_1_SSE_RIC_TONE_2225HZ:
127 res = "2225Hz tone";
128 break;
129 case V150_1_SSE_RIC_V21_CH2_HDLC_FLAGS:
130 res = "V.21 Ch2 HDLC flags";
131 break;
132 case V150_1_SSE_RIC_INDETERMINATE_SIGNAL:
133 res = "Indeterminate signal";
134 break;
135 case V150_1_SSE_RIC_SILENCE:
136 res = "Silence";
137 break;
138 case V150_1_SSE_RIC_CNG:
139 res = "CNG";
140 break;
141 case V150_1_SSE_RIC_VOICE:
142 res = "Voice";
143 break;
144 case V150_1_SSE_RIC_TIMEOUT:
145 res = "Time-out";
146 break;
147 case V150_1_SSE_RIC_P_STATE_TRANSITION:
148 res = "P' state transition";
149 break;
150 case V150_1_SSE_RIC_CLEARDOWN:
151 res = "Cleardown";
152 break;
153 case V150_1_SSE_RIC_ANS_CED:
154 res = "CED";
155 break;
156 case V150_1_SSE_RIC_ANSAM:
157 res = "ANSam";
158 break;
159 case V150_1_SSE_RIC_ANS_PR:
160 res = "/ANS";
161 break;
162 case V150_1_SSE_RIC_ANSAM_PR:
163 res = "/ANSam";
164 break;
165 case V150_1_SSE_RIC_V92_QC1A:
166 res = "V.92 QC1a";
167 break;
168 case V150_1_SSE_RIC_V92_QC1D:
169 res = "V.92 QC1d";
170 break;
171 case V150_1_SSE_RIC_V92_QC2A:
172 res = "V.92 QC2a";
173 break;
174 case V150_1_SSE_RIC_V92_QC2D:
175 res = "V.92 QC2d";
176 break;
177 case V150_1_SSE_RIC_V8BIS_CRE:
178 res = "V.8bis Cre";
179 break;
180 case V150_1_SSE_RIC_V8BIS_CRD:
181 res = "V.8bis CRd";
182 break;
183 case V150_1_SSE_RIC_TIA825A_45_45BPS:
184 res = "TIA825A 45.45BPS";
185 break;
186 case V150_1_SSE_RIC_TIA825A_50BPS:
187 res = "TIA825A 50BPS";
188 break;
189 case V150_1_SSE_RIC_EDT:
190 res = "EDT";
191 break;
192 case V150_1_SSE_RIC_BELL103:
193 res = "Bell 103";
194 break;
195 case V150_1_SSE_RIC_V21_TEXT_TELEPHONE:
196 res = "Text telephone";
197 break;
198 case V150_1_SSE_RIC_V23_MINITEL:
199 res = "V.23 Minitel";
200 break;
201 case V150_1_SSE_RIC_V18_TEXT_TELEPHONE:
202 res = "Text telephone";
203 break;
204 case V150_1_SSE_RIC_V18_DTMF_TEXT_RELAY:
205 res = "Text relay";
206 break;
207 case V150_1_SSE_RIC_CTM:
208 res = "CTM";
209 break;
210 }
211 /*endswitch*/
212 return res;
213}
214/*- End of function --------------------------------------------------------*/
215
216SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_sse_timeout_reason_to_str(int ric)
217{
218 const char *res;
219
220 res = "unknown";
221 switch (ric)
222 {
223 case V150_1_SSE_RIC_INFO_TIMEOUT_NULL:
224 res = "NULL";
225 break;
226 case V150_1_SSE_RIC_INFO_TIMEOUT_CALL_DISCRIMINATION_TIMEOUT:
227 res = "Call discrimination timeout";
228 break;
229 case V150_1_SSE_RIC_INFO_TIMEOUT_IP_TLP:
230 res = "IP-TLP";
231 break;
232 case V150_1_SSE_RIC_INFO_TIMEOUT_SSE_EXPLICIT_ACK_TIMEOUT:
233 res = "TSSE explicit acknowledgement timeout";
234 break;
235 }
236 /*endswitch*/
237 return res;
238}
239/*- End of function --------------------------------------------------------*/
240
241SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_sse_cleardown_reason_to_str(int ric)
242{
243 const char *res;
244
245 res = "unknown";
246 switch (ric)
247 {
248 case V150_1_SSE_RIC_INFO_CLEARDOWN_UNKNOWN:
249 res = "Unknown/unspecified";
250 break;
251 case V150_1_SSE_RIC_INFO_CLEARDOWN_PHYSICAL_LAYER_RELEASE:
252 res = "Physical Layer Release"; // (i.e. data pump release)";
253 break;
254 case V150_1_SSE_RIC_INFO_CLEARDOWN_LINK_LAYER_DISCONNECT:
255 res = "Link Layer Disconnect"; // (i.e. receiving a V.42 DISC frame)";
256 break;
257 case V150_1_SSE_RIC_INFO_CLEARDOWN_COMPRESSION_DISCONNECT:
258 res = "Data compression disconnect";
259 break;
260 case V150_1_SSE_RIC_INFO_CLEARDOWN_ABORT:
261 res = "Abort"; // (i.e. termination due to Abort procedure as specified in SDL)";
262 break;
263 case V150_1_SSE_RIC_INFO_CLEARDOWN_ON_HOOK:
264 res = "On-hook"; // (i.e. when gateway receives On-hook signal from an end-point device)";
265 break;
266 case V150_1_SSE_RIC_INFO_CLEARDOWN_NETWORK_LAYER_TERMINATION:
267 res = "Network layer termination";
268 break;
269 case V150_1_SSE_RIC_INFO_CLEARDOWN_ADMINISTRATIVE:
270 res = "Administrative"; // (i.e., operator action at gateway)";
271 break;
272 }
273 /*endswitch*/
274 return res;
275}
276/*- End of function --------------------------------------------------------*/
277
278static int update_timer(v150_1_sse_state_t *s)
279{
280 span_timestamp_t shortest;
281 int shortest_is;
282
283 if (s->immediate_timer)
284 {
285 shortest = 1;
286 shortest_is = 4;
287 }
288 else
289 {
290 /* Find the earliest expiring of the active timers, and set the timeout to that. */
291 shortest = ~0;
292 shortest_is = 0;
293
294 if (s->timer_t0 < shortest)
295 {
296 shortest = s->timer_t0;
297 shortest_is = 0;
298 }
299 /*endif*/
300 if (s->timer_t0 < shortest)
301 {
302 shortest = s->timer_t1;
303 shortest_is = 1;
304 }
305 /*endif*/
306 /* If we haven't shrunk shortest from maximum, we have no timer to set, so we stop the timer,
307 if its set. */
308 if (shortest == ~0)
309 shortest = 0;
310 /*endif*/
311 }
312 /*endif*/
313 span_log(&s->logging, SPAN_LOG_FLOW, "Update timer to %lu (%d)\n", shortest, shortest_is);
314 if (s->timer_handler)
315 s->timer_handler(s->timer_user_data, shortest);
316 /*endif*/
317 return 0;
318}
319/*- End of function --------------------------------------------------------*/
320
321static int v150_1_sse_rx_initial_audio_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
322{
323 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO)
324 {
325 /* Even if we don't support audio, C.5.3.2 says we need to make this our local state */
326 s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
327 s->rmt_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
328 }
329 else
330 {
331 }
332 /*endif*/
333 return 0;
334}
335/*- End of function --------------------------------------------------------*/
336
337static int v150_1_sse_rx_voice_band_data_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
338{
339 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA)
340 {
341 /* Whether we change to VBD or plain audio is our choice. C.5.3.2. */
342 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
343 s->lcl_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
344 s->rmt_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
345 }
346 else
347 {
348 }
349 /*endif*/
350 return 0;
351}
352/*- End of function --------------------------------------------------------*/
353
354static int v150_1_sse_rx_modem_relay_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
355{
356 int res;
357 int ric;
358 int ric_info;
359
360 res = 0;
361 ric = pkt[1];
362 ric_info = get_net_unaligned_uint16(pkt + 2);
363 span_log(&s->logging,
364 SPAN_LOG_FLOW,
365 "SSE force response %d, reason %s - %d\n",
366 (pkt[0] >> 1) & 0x01,
367 v150_1_sse_ric_to_str(ric),
368 ric_info);
369 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_MODEM_RELAY)
370 {
371 /* Whether we change to modem relay, VBD or plain audio is our choice. C.5.3.2. */
372 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
373 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
374 s->lcl_mode = V150_1_SSE_MEDIA_STATE_MODEM_RELAY;
375 s->rmt_mode = V150_1_SSE_MEDIA_STATE_MODEM_RELAY;
376 }
377 else
378 {
379 }
380 /*endif*/
381 switch (ric)
382 {
383 case V150_1_SSE_RIC_V8_CM:
384 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.8 detection\n");
385 /* We need to respond with a P' */
386 span_log(&s->logging, SPAN_LOG_FLOW, "Sending an SSE %s\n", v150_1_sse_ric_to_str(ric));
387 v150_1_sse_tx_modem_relay_packet(s, 0, V150_1_SSE_RIC_P_STATE_TRANSITION, 0);
388 if (s->status_handler)
389 res = s->status_handler(s->status_user_data, 42);
390 /*endif*/
391 break;
392 case V150_1_SSE_RIC_V8_JM:
393 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.8 detection\n");
394 break;
395 case V150_1_SSE_RIC_V32BIS_AA:
396 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.32bis detection\n");
397 /* We need to respond with a P' */
398 span_log(&s->logging, SPAN_LOG_FLOW, "Sending an SSE P'\n");
399 v150_1_sse_tx_modem_relay_packet(s, 0, V150_1_SSE_RIC_P_STATE_TRANSITION, 0);
400 if (s->status_handler)
401 res = s->status_handler(s->status_user_data, 42);
402 /*endif*/
403 break;
404 case V150_1_SSE_RIC_V32BIS_AC:
405 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.32bis detection\n");
406 break;
407 case V150_1_SSE_RIC_V22BIS_USB1:
408 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
409 break;
410 case V150_1_SSE_RIC_V22BIS_SB1:
411 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
412 break;
413 case V150_1_SSE_RIC_V22BIS_S1:
414 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
415 break;
416 case V150_1_SSE_RIC_V21_CH2:
417 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 detection\n");
418 break;
419 case V150_1_SSE_RIC_V21_CH1:
420 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 detection\n");
421 break;
422 case V150_1_SSE_RIC_V23_HIGH_CHANNEL:
423 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 detection\n");
424 break;
425 case V150_1_SSE_RIC_V23_LOW_CHANNEL:
426 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 detection\n");
427 break;
428 case V150_1_SSE_RIC_TONE_2225HZ:
429 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on 2225Hz tone detection\n");
430 break;
431 case V150_1_SSE_RIC_V21_CH2_HDLC_FLAGS:
432 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 flags detection\n");
433 break;
434 case V150_1_SSE_RIC_INDETERMINATE_SIGNAL:
435 break;
436 case V150_1_SSE_RIC_SILENCE:
437 break;
438 case V150_1_SSE_RIC_CNG:
439 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on CNG detection\n");
440 break;
441 case V150_1_SSE_RIC_VOICE:
442 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on voice detection\n");
443 break;
444 case V150_1_SSE_RIC_TIMEOUT:
445 span_log(&s->logging, SPAN_LOG_FLOW, "Timeout %d - %s\n", (ric_info >> 8), v150_1_sse_timeout_reason_to_str(ric_info >> 8));
446 break;
447 case V150_1_SSE_RIC_P_STATE_TRANSITION:
448 span_log(&s->logging, SPAN_LOG_FLOW, "P' received\n");
449 break;
450 case V150_1_SSE_RIC_CLEARDOWN:
451 span_log(&s->logging, SPAN_LOG_FLOW, "Cleardown %d - %s\n", (ric_info >> 8), v150_1_sse_cleardown_reason_to_str(ric_info >> 8));
452 break;
453 case V150_1_SSE_RIC_ANS_CED:
454 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on ANS/CED detection\n");
455 break;
456 case V150_1_SSE_RIC_ANSAM:
457 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on ANSam detection\n");
458 break;
459 case V150_1_SSE_RIC_ANS_PR:
460 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on /ANS detection\n");
461 break;
462 case V150_1_SSE_RIC_ANSAM_PR:
463 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on /ANSam detection\n");
464 break;
465 case V150_1_SSE_RIC_V92_QC1A:
466 break;
467 case V150_1_SSE_RIC_V92_QC1D:
468 break;
469 case V150_1_SSE_RIC_V92_QC2A:
470 break;
471 case V150_1_SSE_RIC_V92_QC2D:
472 break;
473 case V150_1_SSE_RIC_V8BIS_CRE:
474 break;
475 case V150_1_SSE_RIC_V8BIS_CRD:
476 break;
477 case V150_1_SSE_RIC_TIA825A_45_45BPS:
478 break;
479 case V150_1_SSE_RIC_TIA825A_50BPS:
480 break;
481 case V150_1_SSE_RIC_EDT:
482 break;
483 case V150_1_SSE_RIC_BELL103:
484 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on Bell103 detection\n");
485 break;
486 case V150_1_SSE_RIC_V21_TEXT_TELEPHONE:
487 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 text telephone detection\n");
488 break;
489 case V150_1_SSE_RIC_V23_MINITEL:
490 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 minitel detection\n");
491 break;
492 case V150_1_SSE_RIC_V18_TEXT_TELEPHONE:
493 break;
494 case V150_1_SSE_RIC_V18_DTMF_TEXT_RELAY:
495 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on DTMF text relay detection\n");
496 break;
497 case V150_1_SSE_RIC_CTM:
498 break;
499 }
500 /*endswitch*/
501 return res;
502}
503/*- End of function --------------------------------------------------------*/
504
505static int v150_1_sse_rx_fax_relay_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
506{
507 int res;
508 int ric;
509 int ric_info;
510
511 res = 0;
512 ric = pkt[1];
513 ric_info = get_net_unaligned_uint16(pkt + 2);
514 span_log(&s->logging,
515 SPAN_LOG_FLOW,
516 "SSE force %d, reason %s - %d\n",
517 (pkt[0] >> 1) & 0x01,
518 v150_1_sse_ric_to_str(ric),
519 ric_info);
520 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_FAX_RELAY)
521 {
522 /* Whether we change to FAX relay, VBD or plain audio is our choice. C.5.3.2. */
523 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
524 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
525 s->lcl_mode = V150_1_SSE_MEDIA_STATE_FAX_RELAY;
526 s->rmt_mode = V150_1_SSE_MEDIA_STATE_FAX_RELAY;
527 }
528 else
529 {
530 }
531 /*endif*/
532 switch (ric)
533 {
534 case V150_1_SSE_RIC_V8_CM:
535 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.8 detection\n");
536 /* We need to respond with a P' */
537 v150_1_sse_tx_fax_relay_packet(s, 0, V150_1_SSE_RIC_P_STATE_TRANSITION, 0);
538 if (s->status_handler)
539 res = s->status_handler(s->status_user_data, 42);
540 /*endif*/
541 break;
542 case V150_1_SSE_RIC_V8_JM:
543 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.8 detection\n");
544 break;
545 case V150_1_SSE_RIC_V32BIS_AA:
546 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.32bis detection\n");
547 /* We need to respond with a P' */
548 v150_1_sse_tx_fax_relay_packet(s, 0, V150_1_SSE_RIC_P_STATE_TRANSITION, 0);
549 if (s->status_handler)
550 res = s->status_handler(s->status_user_data, 42);
551 /*endif*/
552 break;
553 case V150_1_SSE_RIC_V32BIS_AC:
554 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.32bis detection\n");
555 break;
556 case V150_1_SSE_RIC_V22BIS_USB1:
557 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
558 break;
559 case V150_1_SSE_RIC_V22BIS_SB1:
560 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
561 break;
562 case V150_1_SSE_RIC_V22BIS_S1:
563 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
564 break;
565 case V150_1_SSE_RIC_V21_CH2:
566 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 detection\n");
567 break;
568 case V150_1_SSE_RIC_V21_CH1:
569 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 detection\n");
570 break;
571 case V150_1_SSE_RIC_V23_HIGH_CHANNEL:
572 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 detection\n");
573 break;
574 case V150_1_SSE_RIC_V23_LOW_CHANNEL:
575 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 detection\n");
576 break;
577 case V150_1_SSE_RIC_TONE_2225HZ:
578 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on 2225Hz tone detection\n");
579 break;
580 case V150_1_SSE_RIC_V21_CH2_HDLC_FLAGS:
581 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 flags detection\n");
582 break;
583 case V150_1_SSE_RIC_INDETERMINATE_SIGNAL:
584 break;
585 case V150_1_SSE_RIC_SILENCE:
586 break;
587 case V150_1_SSE_RIC_CNG:
588 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on CNG detection\n");
589 break;
590 case V150_1_SSE_RIC_VOICE:
591 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on voice detection\n");
592 break;
593 case V150_1_SSE_RIC_TIMEOUT:
594 span_log(&s->logging, SPAN_LOG_FLOW, "Timeout %d - %s\n", (ric_info >> 8), v150_1_sse_timeout_reason_to_str(ric_info >> 8));
595 break;
596 case V150_1_SSE_RIC_P_STATE_TRANSITION:
597 span_log(&s->logging, SPAN_LOG_FLOW, "P' received\n");
598 break;
599 case V150_1_SSE_RIC_CLEARDOWN:
600 span_log(&s->logging, SPAN_LOG_FLOW, "Cleardown %d - %s\n", (ric_info >> 8), v150_1_sse_cleardown_reason_to_str(ric_info >> 8));
601 break;
602 case V150_1_SSE_RIC_ANS_CED:
603 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on ANS/CED detection\n");
604 break;
605 case V150_1_SSE_RIC_ANSAM:
606 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on ANSam detection\n");
607 break;
608 case V150_1_SSE_RIC_ANS_PR:
609 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on /ANS detection\n");
610 break;
611 case V150_1_SSE_RIC_ANSAM_PR:
612 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on /ANSam detection\n");
613 break;
614 case V150_1_SSE_RIC_V92_QC1A:
615 break;
616 case V150_1_SSE_RIC_V92_QC1D:
617 break;
618 case V150_1_SSE_RIC_V92_QC2A:
619 break;
620 case V150_1_SSE_RIC_V92_QC2D:
621 break;
622 case V150_1_SSE_RIC_V8BIS_CRE:
623 break;
624 case V150_1_SSE_RIC_V8BIS_CRD:
625 break;
626 case V150_1_SSE_RIC_TIA825A_45_45BPS:
627 break;
628 case V150_1_SSE_RIC_TIA825A_50BPS:
629 break;
630 case V150_1_SSE_RIC_EDT:
631 break;
632 case V150_1_SSE_RIC_BELL103:
633 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on Bell103 detection\n");
634 break;
635 case V150_1_SSE_RIC_V21_TEXT_TELEPHONE:
636 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 text telephone detection\n");
637 break;
638 case V150_1_SSE_RIC_V23_MINITEL:
639 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 minitel detection\n");
640 break;
641 case V150_1_SSE_RIC_V18_TEXT_TELEPHONE:
642 break;
643 case V150_1_SSE_RIC_V18_DTMF_TEXT_RELAY:
644 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on DTMF text relay detection\n");
645 break;
646 case V150_1_SSE_RIC_CTM:
647 break;
648 }
649 /*endswitch*/
650 return res;
651}
652/*- End of function --------------------------------------------------------*/
653
654static int v150_1_sse_rx_text_relay_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
655{
656 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_TEXT_RELAY)
657 {
658 /* Whether we change to text relay, VBD or plain audio is our choice. C.5.3.2. */
659 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
660 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
661 s->lcl_mode = V150_1_SSE_MEDIA_STATE_TEXT_RELAY;
662 s->rmt_mode = V150_1_SSE_MEDIA_STATE_TEXT_RELAY;
663 }
664 else
665 {
666 }
667 /*endif*/
668 return 0;
669}
670/*- End of function --------------------------------------------------------*/
671
672static int v150_1_sse_rx_text_probe_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
673{
674 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_TEXT_RELAY)
675 {
676 s->lcl_mode = V150_1_SSE_MEDIA_STATE_TEXT_RELAY;
677 s->rmt_mode = V150_1_SSE_MEDIA_STATE_TEXT_RELAY;
678 }
679 else
680 {
681 }
682 /*endif*/
683 return 0;
684}
685/*- End of function --------------------------------------------------------*/
686
687SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_sse_rx_packet(v150_1_sse_state_t *s,
688 uint16_t seq_no,
689 uint32_t timestamp,
690 const uint8_t pkt[],
691 int len)
692{
693 int event;
694 int res;
695 int f;
696 int x;
697 int ext_len;
698
699 span_log(&s->logging, SPAN_LOG_FLOW, "SSE rx message - %d bytes\n", len);
700 if (len < 4)
701 return -1;
702 /*endif*/
703
704 res = 0;
705 if (s->previous_rx_timestamp != timestamp)
706 {
707 /* V.150.1 C.4.1 says act on the first received copy of an SSE message. Expect
708 the sequence number to increase, but the timestamp should remain the same for
709 redundant repeats. */
710 s->previous_rx_timestamp = timestamp;
711
712 event = (pkt[0] >> 2) & 0x3F;
713 f = (pkt[0] >> 1) & 0x01;
Value stored to 'f' is never read
714 x = pkt[0] & 0x01;
715 span_log(&s->logging, SPAN_LOG_FLOW, "SSE event %s\n", v150_1_sse_media_state_to_str(event));
716 if (x)
717 {
718 if (len >= 6)
719 {
720 /* Deal with the extension */
721 ext_len = get_net_unaligned_uint16(&pkt[4]) & 0x7FF;
722 if (ext_len >= 1)
723 {
724 s->rmt_ack = pkt[6] & 0x3F;
725 }
726 /*endif*/
727 }
728 /*endif*/
729 }
730 else
731 {
732 if (len != 4)
733 span_log(&s->logging, SPAN_LOG_FLOW, "Non-extended message of length %d\n", len);
734 /*endif*/
735 }
736 /*endif*/
737 switch (event)
738 {
739 case V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO:
740 res = v150_1_sse_rx_initial_audio_packet(s, pkt, len);
741 break;
742 case V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA:
743 res = v150_1_sse_rx_voice_band_data_packet(s, pkt, len);
744 break;
745 case V150_1_SSE_MEDIA_STATE_MODEM_RELAY:
746 res = v150_1_sse_rx_modem_relay_packet(s, pkt, len);
747 break;
748 case V150_1_SSE_MEDIA_STATE_FAX_RELAY:
749 res = v150_1_sse_rx_fax_relay_packet(s, pkt, len);
750 break;
751 case V150_1_SSE_MEDIA_STATE_TEXT_RELAY:
752 res = v150_1_sse_rx_text_relay_packet(s, pkt, len);
753 break;
754 case V150_1_SSE_MEDIA_STATE_TEXT_PROBE:
755 res = v150_1_sse_rx_text_probe_packet(s, pkt, len);
756 break;
757 default:
758 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected SSE event %d\n", event);
759 res = -1;
760 break;
761 }
762 /*endswitch*/
763 s->rmt_mode = event;
764 }
765 /*endif*/
766 return res;
767}
768/*- End of function --------------------------------------------------------*/
769
770static int v150_1_sse_tx_initial_audio_packet(v150_1_sse_state_t *s)
771{
772 return 0;
773}
774/*- End of function --------------------------------------------------------*/
775
776static int v150_1_sse_tx_voice_band_data_packet(v150_1_sse_state_t *s)
777{
778 return 0;
779}
780/*- End of function --------------------------------------------------------*/
781
782static int v150_1_sse_tx_modem_relay_packet(v150_1_sse_state_t *s, int x, int ric, int ricinfo)
783{
784 uint8_t pkt[256];
785 int len;
786 uint8_t f;
787 span_timestamp_t now;
788
789 /* If we are using explicit acknowledgements, both the F and X bits need to be set */
790 if (s->explicit_acknowledgements)
791 {
792 if (s->force_response)
793 f = 0x03;
794 else
795 f = 0x01;
796 /*endif*/
797 }
798 else
799 {
800 f = 0x00;
801 }
802 /*endif*/
803 span_log(&s->logging, SPAN_LOG_FLOW, "Sending an SSE %s\n", v150_1_sse_ric_to_str(ric));
804 pkt[0] = f | (V150_1_SSE_MEDIA_STATE_MODEM_RELAY << 2);
805 pkt[1] = ric;
806 put_net_unaligned_uint16(&pkt[2], ricinfo);
807 len = 4;
808 switch (ric)
809 {
810 case V150_1_SSE_RIC_CLEARDOWN:
811 /* We may need to add more information as an extension. Note that V.150.1 originally made
812 the SSE message lengths variable in a way that can't really work. The only message this
813 affected was cleardown. Corrigendum 2 changed the extra bytes to an extension field, so
814 all messages are 4 bytes long until the extension bit it used to stretch them. */
815 break;
816 }
817 /*endswitch*/
818 if (s->explicit_acknowledgements)
819 {
820 /* The length of the extension field */
821 put_net_unaligned_uint16(&pkt[len], 1);
822 len += 2;
823 /* The actual content of the field */
824 pkt[len++] = s->rmt_mode;
825 }
826 /*endif*/
827 if (s->packet_handler)
828 s->packet_handler(s->packet_user_data, pkt, len);
829 /*endif*/
830 if (s->explicit_acknowledgements)
831 {
832 if (s->timer_handler)
833 {
834 now = s->timer_handler(s->timer_user_data, ~0);
835 s->timer_t0 = now + s->t0interval;
836 s->timer_t1 = now + s->t1interval;
837 s->counter_n0 = s->n0count;
838 s->force_response = false0;
839 update_timer(s);
840 }
841 /*endif*/
842 }
843 /*endif*/
844 return 0;
845}
846/*- End of function --------------------------------------------------------*/
847
848static int v150_1_sse_tx_fax_relay_packet(v150_1_sse_state_t *s, int x, int ric, int ricinfo)
849{
850 int res;
851 uint8_t pkt[256];
852 int len;
853 uint8_t f;
854
855 f = 0;
856 /* If we are using explicit acknowledgements, both the F and X bits need to be set */
857 if (s->explicit_acknowledgements)
858 {
859 f |= 0x01;
860 if (s->force_response)
861 f |= 0x02;
862 /*endif*/
863 }
864 /*endif*/
865 pkt[0] = (V150_1_SSE_MEDIA_STATE_FAX_RELAY << 2) | f;
866 pkt[1] = ric;
867 put_net_unaligned_uint16(&pkt[2], ricinfo);
868 len = 4;
869 if (s->explicit_acknowledgements)
870 {
871 put_net_unaligned_uint16(&pkt[len], 1);
872 len += 2;
873 pkt[len++] = s->rmt_mode;
874 }
875 /*endif*/
876 if (s->packet_handler)
877 res = s->packet_handler(s->packet_user_data, pkt, len);
878 /*endif*/
879 return 0;
880}
881/*- End of function --------------------------------------------------------*/
882
883static int v150_1_sse_tx_text_relay_packet(v150_1_sse_state_t *s)
884{
885 return 0;
886}
887/*- End of function --------------------------------------------------------*/
888
889static int v150_1_sse_tx_text_probe_packet(v150_1_sse_state_t *s)
890{
891 return 0;
892}
893/*- End of function --------------------------------------------------------*/
894
895SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_sse_tx_packet(v150_1_sse_state_t *s, int event, int ric, int ricinfo)
896{
897 int res;
898 int x;
899
900 x = 0;
901 span_log(&s->logging, SPAN_LOG_FLOW, "SSE event %s\n", v150_1_sse_media_state_to_str(event));
902 switch (event)
903 {
904 case V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO:
905 res = v150_1_sse_tx_initial_audio_packet(s);
906 break;
907 case V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA:
908 res = v150_1_sse_tx_voice_band_data_packet(s);
909 break;
910 case V150_1_SSE_MEDIA_STATE_MODEM_RELAY:
911 res = v150_1_sse_tx_modem_relay_packet(s, x, ric, ricinfo);
912 break;
913 case V150_1_SSE_MEDIA_STATE_FAX_RELAY:
914 res = v150_1_sse_tx_fax_relay_packet(s, x, ric, ricinfo);
915 break;
916 case V150_1_SSE_MEDIA_STATE_TEXT_RELAY:
917 res = v150_1_sse_tx_text_relay_packet(s);
918 break;
919 case V150_1_SSE_MEDIA_STATE_TEXT_PROBE:
920 res = v150_1_sse_tx_text_probe_packet(s);
921 break;
922 default:
923 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected SSE event %d\n", event);
924 res = -1;
925 break;
926 }
927 /*endswitch*/
928 s->lcl_mode = event;
929 return res;
930}
931/*- End of function --------------------------------------------------------*/
932
933SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_sse_timer_expired(v150_1_sse_state_t *s, span_timestamp_t now)
934{
935 span_log(&s->logging, SPAN_LOG_FLOW, "Timer expired at %lu\n", now);
936
937 if (s->immediate_timer)
938 {
939 s->immediate_timer = false0;
940 /* TODO: */
941 }
942 /*endif*/
943 if (s->timer_t0 != 0 && s->timer_t0 <= now)
944 {
945 span_log(&s->logging, SPAN_LOG_FLOW, "T0 expired\n");
946 if (--s->counter_n0 > 0)
947 {
948 span_log(&s->logging, SPAN_LOG_FLOW, "Resend (%d)\n", s->counter_n0);
949 s->timer_t0 = now + s->t0interval;
950 update_timer(s);
951 }
952 else
953 {
954 span_log(&s->logging, SPAN_LOG_FLOW, "Count exceeded\n");
955 }
956 /*endif*/
957 }
958 /*endif*/
959 if (s->timer_t1 != 0 && s->timer_t1 <= now)
960 {
961 span_log(&s->logging, SPAN_LOG_FLOW, "T1 expired\n");
962 }
963 /*endif*/
964 return 0;
965}
966/*- End of function --------------------------------------------------------*/
967
968SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_sse_explicit_acknowledgements(v150_1_sse_state_t *s,
969 bool_Bool explicit_acknowledgements)
970{
971 s->explicit_acknowledgements = explicit_acknowledgements;
972 return 0;
973}
974/*- End of function --------------------------------------------------------*/
975
976SPAN_DECLARE(logging_state_t *)__attribute__((visibility("default"))) logging_state_t * v150_1_sse_get_logging_state(v150_1_sse_state_t *s)
977{
978 return &s->logging;
979}
980/*- End of function --------------------------------------------------------*/
981
982SPAN_DECLARE(v150_1_sse_state_t *)__attribute__((visibility("default"))) v150_1_sse_state_t * v150_1_sse_init(v150_1_sse_state_t *s,
983 v150_1_sse_packet_handler_t packet_handler,
984 void *packet_user_data,
985 v150_1_sse_status_handler_t status_handler,
986 void *status_user_data,
987 v150_1_sse_timer_handler_t timer_handler,
988 void *timer_user_data)
989{
990 if (packet_handler == NULL((void*)0))
991 return NULL((void*)0);
992 /*endif*/
993 if (s == NULL((void*)0))
994 {
995 if ((s = (v150_1_sse_state_t *) malloc(sizeof(*s))) == NULL((void*)0))
996 return NULL((void*)0);
997 /*endif*/
998 }
999 /*endif*/
1000 memset(s, 0, sizeof(*s));
1001
1002 span_log_init(&s->logging, SPAN_LOG_NONE, NULL((void*)0));
1003 span_log_set_protocol(&s->logging, "V.150.1 SSE");
1004
1005 s->reliability_method = V150_1_SSE_RELIABILITY_NONE;
1006 s->explicit_acknowledgements = false0;
1007 s->repetitions = 3;
1008 s->repetition_interval = 20000;
1009
1010 /* Set default values for the explicit acknowledgement parameters */
1011 /* V.150.1 C.4.3.1 */
1012 s->n0count = 3;
1013 s->t0interval = 10000;
1014 s->t1interval = 300000;
1015
1016 /* V.150.1 C.4.3.1 */
1017 /* Let p be the probability that a packet sent by one MoIP node through the packet
1018 network will be successfully received by the other node.
1019 Let t be the latency that can be tolerated in the delivery of mode updates
1020 Let q be the reliability required in the delivery of mode updates within the given
1021 latency
1022 Let rtd be the round trip delay through the packet network between the two nodes
1023 Let owd be the one way delay through the packet network from one node to the other
1024 (i.e. rtd/2) */
1025 //s->n0count = floor(log(1 - q)/log(1 - p));
1026 //s->t0interval = max(0, ((rtd/2) - t)/(n0count - 1));
1027 //s->t1interval = 1.5*rtd;
1028
1029 /* V.150.1 C.5.3 */
1030 s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
1031 s->rmt_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
1032
1033 s->previous_rx_timestamp = 0xFFFFFFFF;
1034
1035 s->packet_handler = packet_handler;
1036 s->packet_user_data = packet_user_data;
1037 s->status_handler = status_handler;
1038 s->status_user_data = status_user_data;
1039 s->timer_handler = timer_handler;
1040 s->timer_user_data = timer_user_data;
1041
1042 return s;
1043}
1044/*- End of function --------------------------------------------------------*/
1045/*- End of file ------------------------------------------------------------*/