Bug Summary

File:v150_1_sse.c
Warning:line 910, column 9
Value stored to 'res' 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 uint8_t first;
282 int i;
283 int shortest_is;
284
285 if (s->immediate_timer)
286 {
287 shortest = 1;
288 shortest_is = 4;
289 }
290 else
291 {
292 /* Find the earliest expiring of the active timers, and set the timeout to that. */
293 shortest = ~0;
294 shortest_is = 0;
295
296 if (s->timer_t0 < shortest)
297 {
298 shortest = s->timer_t0;
299 shortest_is = 0;
300 }
301 /*endif*/
302 if (s->timer_t0 < shortest)
303 {
304 shortest = s->timer_t1;
305 shortest_is = 1;
306 }
307 /*endif*/
308 /* If we haven't shrunk shortest from maximum, we have no timer to set, so we stop the timer,
309 if its set. */
310 if (shortest == ~0)
311 shortest = 0;
312 /*endif*/
313 }
314 /*endif*/
315 span_log(&s->logging, SPAN_LOG_FLOW, "Update timer to %lu (%d)\n", shortest, shortest_is);
316 if (s->timer_handler)
317 s->timer_handler(s->timer_user_data, shortest);
318 /*endif*/
319 return 0;
320}
321/*- End of function --------------------------------------------------------*/
322
323static int v150_1_sse_rx_initial_audio_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
324{
325 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO)
326 {
327 /* Even if we don't support audio, C.5.3.2 says we need to make this our local state */
328 s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
329 s->rmt_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
330 }
331 else
332 {
333 }
334 /*endif*/
335 return 0;
336}
337/*- End of function --------------------------------------------------------*/
338
339static int v150_1_sse_rx_voice_band_data_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
340{
341 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA)
342 {
343 /* Whether we change to VBD or plain audio is our choice. C.5.3.2. */
344 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
345 s->lcl_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
346 s->rmt_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
347 }
348 else
349 {
350 }
351 /*endif*/
352 return 0;
353}
354/*- End of function --------------------------------------------------------*/
355
356static int v150_1_sse_rx_modem_relay_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
357{
358 int res;
359 int ric;
360 int ric_info;
361
362 res = 0;
363 ric = pkt[1];
364 ric_info = get_net_unaligned_uint16(pkt + 2);
365 span_log(&s->logging,
366 SPAN_LOG_FLOW,
367 "SSE force response %d, reason %s - %d\n",
368 (pkt[0] >> 1) & 0x01,
369 v150_1_sse_ric_to_str(ric),
370 ric_info);
371 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_MODEM_RELAY)
372 {
373 /* Whether we change to modem relay, VBD or plain audio is our choice. C.5.3.2. */
374 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
375 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
376 s->lcl_mode = V150_1_SSE_MEDIA_STATE_MODEM_RELAY;
377 s->rmt_mode = V150_1_SSE_MEDIA_STATE_MODEM_RELAY;
378 }
379 else
380 {
381 }
382 /*endif*/
383 switch (ric)
384 {
385 case V150_1_SSE_RIC_V8_CM:
386 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.8 detection\n");
387 /* We need to respond with a P' */
388 span_log(&s->logging, SPAN_LOG_FLOW, "Sending an SSE %s\n", v150_1_sse_ric_to_str(ric));
389 v150_1_sse_tx_modem_relay_packet(s, 0, V150_1_SSE_RIC_P_STATE_TRANSITION, 0);
390 if (s->status_handler)
391 res = s->status_handler(s->status_user_data, 42);
392 /*endif*/
393 break;
394 case V150_1_SSE_RIC_V8_JM:
395 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.8 detection\n");
396 break;
397 case V150_1_SSE_RIC_V32BIS_AA:
398 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.32bis detection\n");
399 /* We need to respond with a P' */
400 span_log(&s->logging, SPAN_LOG_FLOW, "Sending an SSE P'\n");
401 v150_1_sse_tx_modem_relay_packet(s, 0, V150_1_SSE_RIC_P_STATE_TRANSITION, 0);
402 if (s->status_handler)
403 res = s->status_handler(s->status_user_data, 42);
404 /*endif*/
405 break;
406 case V150_1_SSE_RIC_V32BIS_AC:
407 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.32bis detection\n");
408 break;
409 case V150_1_SSE_RIC_V22BIS_USB1:
410 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
411 break;
412 case V150_1_SSE_RIC_V22BIS_SB1:
413 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
414 break;
415 case V150_1_SSE_RIC_V22BIS_S1:
416 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
417 break;
418 case V150_1_SSE_RIC_V21_CH2:
419 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 detection\n");
420 break;
421 case V150_1_SSE_RIC_V21_CH1:
422 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 detection\n");
423 break;
424 case V150_1_SSE_RIC_V23_HIGH_CHANNEL:
425 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 detection\n");
426 break;
427 case V150_1_SSE_RIC_V23_LOW_CHANNEL:
428 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 detection\n");
429 break;
430 case V150_1_SSE_RIC_TONE_2225HZ:
431 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on 2225Hz tone detection\n");
432 break;
433 case V150_1_SSE_RIC_V21_CH2_HDLC_FLAGS:
434 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 flags detection\n");
435 break;
436 case V150_1_SSE_RIC_INDETERMINATE_SIGNAL:
437 break;
438 case V150_1_SSE_RIC_SILENCE:
439 break;
440 case V150_1_SSE_RIC_CNG:
441 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on CNG detection\n");
442 break;
443 case V150_1_SSE_RIC_VOICE:
444 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on voice detection\n");
445 break;
446 case V150_1_SSE_RIC_TIMEOUT:
447 span_log(&s->logging, SPAN_LOG_FLOW, "Timeout %d - %s\n", (ric_info >> 8), v150_1_sse_timeout_reason_to_str(ric_info >> 8));
448 break;
449 case V150_1_SSE_RIC_P_STATE_TRANSITION:
450 span_log(&s->logging, SPAN_LOG_FLOW, "P' received\n");
451 break;
452 case V150_1_SSE_RIC_CLEARDOWN:
453 span_log(&s->logging, SPAN_LOG_FLOW, "Cleardown %d - %s\n", (ric_info >> 8), v150_1_sse_cleardown_reason_to_str(ric_info >> 8));
454 break;
455 case V150_1_SSE_RIC_ANS_CED:
456 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on ANS/CED detection\n");
457 break;
458 case V150_1_SSE_RIC_ANSAM:
459 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on ANSam detection\n");
460 break;
461 case V150_1_SSE_RIC_ANS_PR:
462 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on /ANS detection\n");
463 break;
464 case V150_1_SSE_RIC_ANSAM_PR:
465 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on /ANSam detection\n");
466 break;
467 case V150_1_SSE_RIC_V92_QC1A:
468 break;
469 case V150_1_SSE_RIC_V92_QC1D:
470 break;
471 case V150_1_SSE_RIC_V92_QC2A:
472 break;
473 case V150_1_SSE_RIC_V92_QC2D:
474 break;
475 case V150_1_SSE_RIC_V8BIS_CRE:
476 break;
477 case V150_1_SSE_RIC_V8BIS_CRD:
478 break;
479 case V150_1_SSE_RIC_TIA825A_45_45BPS:
480 break;
481 case V150_1_SSE_RIC_TIA825A_50BPS:
482 break;
483 case V150_1_SSE_RIC_EDT:
484 break;
485 case V150_1_SSE_RIC_BELL103:
486 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on Bell103 detection\n");
487 break;
488 case V150_1_SSE_RIC_V21_TEXT_TELEPHONE:
489 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 text telephone detection\n");
490 break;
491 case V150_1_SSE_RIC_V23_MINITEL:
492 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 minitel detection\n");
493 break;
494 case V150_1_SSE_RIC_V18_TEXT_TELEPHONE:
495 break;
496 case V150_1_SSE_RIC_V18_DTMF_TEXT_RELAY:
497 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on DTMF text relay detection\n");
498 break;
499 case V150_1_SSE_RIC_CTM:
500 break;
501 }
502 /*endswitch*/
503 return res;
504}
505/*- End of function --------------------------------------------------------*/
506
507static int v150_1_sse_rx_fax_relay_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
508{
509 int res;
510 int ric;
511 int ric_info;
512
513 res = 0;
514 ric = pkt[1];
515 ric_info = get_net_unaligned_uint16(pkt + 2);
516 span_log(&s->logging,
517 SPAN_LOG_FLOW,
518 "SSE force %d, reason %s - %d\n",
519 (pkt[0] >> 1) & 0x01,
520 v150_1_sse_ric_to_str(ric),
521 ric_info);
522 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_FAX_RELAY)
523 {
524 /* Whether we change to FAX relay, VBD or plain audio is our choice. C.5.3.2. */
525 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
526 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
527 s->lcl_mode = V150_1_SSE_MEDIA_STATE_FAX_RELAY;
528 s->rmt_mode = V150_1_SSE_MEDIA_STATE_FAX_RELAY;
529 }
530 else
531 {
532 }
533 /*endif*/
534 switch (ric)
535 {
536 case V150_1_SSE_RIC_V8_CM:
537 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.8 detection\n");
538 /* We need to respond with a P' */
539 v150_1_sse_tx_fax_relay_packet(s, 0, V150_1_SSE_RIC_P_STATE_TRANSITION, 0);
540 if (s->status_handler)
541 res = s->status_handler(s->status_user_data, 42);
542 /*endif*/
543 break;
544 case V150_1_SSE_RIC_V8_JM:
545 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.8 detection\n");
546 break;
547 case V150_1_SSE_RIC_V32BIS_AA:
548 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.32bis detection\n");
549 /* We need to respond with a P' */
550 v150_1_sse_tx_fax_relay_packet(s, 0, V150_1_SSE_RIC_P_STATE_TRANSITION, 0);
551 if (s->status_handler)
552 res = s->status_handler(s->status_user_data, 42);
553 /*endif*/
554 break;
555 case V150_1_SSE_RIC_V32BIS_AC:
556 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.32bis detection\n");
557 break;
558 case V150_1_SSE_RIC_V22BIS_USB1:
559 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
560 break;
561 case V150_1_SSE_RIC_V22BIS_SB1:
562 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
563 break;
564 case V150_1_SSE_RIC_V22BIS_S1:
565 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.22bis detection\n");
566 break;
567 case V150_1_SSE_RIC_V21_CH2:
568 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 detection\n");
569 break;
570 case V150_1_SSE_RIC_V21_CH1:
571 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 detection\n");
572 break;
573 case V150_1_SSE_RIC_V23_HIGH_CHANNEL:
574 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 detection\n");
575 break;
576 case V150_1_SSE_RIC_V23_LOW_CHANNEL:
577 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 detection\n");
578 break;
579 case V150_1_SSE_RIC_TONE_2225HZ:
580 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on 2225Hz tone detection\n");
581 break;
582 case V150_1_SSE_RIC_V21_CH2_HDLC_FLAGS:
583 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 flags detection\n");
584 break;
585 case V150_1_SSE_RIC_INDETERMINATE_SIGNAL:
586 break;
587 case V150_1_SSE_RIC_SILENCE:
588 break;
589 case V150_1_SSE_RIC_CNG:
590 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on CNG detection\n");
591 break;
592 case V150_1_SSE_RIC_VOICE:
593 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on voice detection\n");
594 break;
595 case V150_1_SSE_RIC_TIMEOUT:
596 span_log(&s->logging, SPAN_LOG_FLOW, "Timeout %d - %s\n", (ric_info >> 8), v150_1_sse_timeout_reason_to_str(ric_info >> 8));
597 break;
598 case V150_1_SSE_RIC_P_STATE_TRANSITION:
599 span_log(&s->logging, SPAN_LOG_FLOW, "P' received\n");
600 break;
601 case V150_1_SSE_RIC_CLEARDOWN:
602 span_log(&s->logging, SPAN_LOG_FLOW, "Cleardown %d - %s\n", (ric_info >> 8), v150_1_sse_cleardown_reason_to_str(ric_info >> 8));
603 break;
604 case V150_1_SSE_RIC_ANS_CED:
605 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on ANS/CED detection\n");
606 break;
607 case V150_1_SSE_RIC_ANSAM:
608 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on ANSam detection\n");
609 break;
610 case V150_1_SSE_RIC_ANS_PR:
611 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on /ANS detection\n");
612 break;
613 case V150_1_SSE_RIC_ANSAM_PR:
614 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on /ANSam detection\n");
615 break;
616 case V150_1_SSE_RIC_V92_QC1A:
617 break;
618 case V150_1_SSE_RIC_V92_QC1D:
619 break;
620 case V150_1_SSE_RIC_V92_QC2A:
621 break;
622 case V150_1_SSE_RIC_V92_QC2D:
623 break;
624 case V150_1_SSE_RIC_V8BIS_CRE:
625 break;
626 case V150_1_SSE_RIC_V8BIS_CRD:
627 break;
628 case V150_1_SSE_RIC_TIA825A_45_45BPS:
629 break;
630 case V150_1_SSE_RIC_TIA825A_50BPS:
631 break;
632 case V150_1_SSE_RIC_EDT:
633 break;
634 case V150_1_SSE_RIC_BELL103:
635 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on Bell103 detection\n");
636 break;
637 case V150_1_SSE_RIC_V21_TEXT_TELEPHONE:
638 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.21 text telephone detection\n");
639 break;
640 case V150_1_SSE_RIC_V23_MINITEL:
641 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on V.23 minitel detection\n");
642 break;
643 case V150_1_SSE_RIC_V18_TEXT_TELEPHONE:
644 break;
645 case V150_1_SSE_RIC_V18_DTMF_TEXT_RELAY:
646 span_log(&s->logging, SPAN_LOG_FLOW, "Switch on DTMF text relay detection\n");
647 break;
648 case V150_1_SSE_RIC_CTM:
649 break;
650 }
651 /*endswitch*/
652 return res;
653}
654/*- End of function --------------------------------------------------------*/
655
656static int v150_1_sse_rx_text_relay_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
657{
658 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_TEXT_RELAY)
659 {
660 /* Whether we change to text relay, VBD or plain audio is our choice. C.5.3.2. */
661 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
662 //s->lcl_mode = V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA;
663 s->lcl_mode = V150_1_SSE_MEDIA_STATE_TEXT_RELAY;
664 s->rmt_mode = V150_1_SSE_MEDIA_STATE_TEXT_RELAY;
665 }
666 else
667 {
668 }
669 /*endif*/
670 return 0;
671}
672/*- End of function --------------------------------------------------------*/
673
674static int v150_1_sse_rx_text_probe_packet(v150_1_sse_state_t *s, const uint8_t pkt[], int len)
675{
676 if (s->rmt_mode != V150_1_SSE_MEDIA_STATE_TEXT_RELAY)
677 {
678 s->lcl_mode = V150_1_SSE_MEDIA_STATE_TEXT_RELAY;
679 s->rmt_mode = V150_1_SSE_MEDIA_STATE_TEXT_RELAY;
680 }
681 else
682 {
683 }
684 /*endif*/
685 return 0;
686}
687/*- End of function --------------------------------------------------------*/
688
689SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_sse_rx_packet(v150_1_sse_state_t *s,
690 uint16_t seq_no,
691 uint32_t timestamp,
692 const uint8_t pkt[],
693 int len)
694{
695 int event;
696 int res;
697 int f;
698 int x;
699 int ext_len;
700
701 span_log(&s->logging, SPAN_LOG_FLOW, "SSE rx message - %d bytes\n", len);
702 if (len < 4)
703 return -1;
704 /*endif*/
705
706 if (s->previous_rx_timestamp != timestamp)
707 {
708 /* V.150.1 C.4.1 says act on the first received copy of an SSE message. Expect
709 the sequence number to increase, but the timestamp should remain the same for
710 redundant repeats. */
711 s->previous_rx_timestamp = timestamp;
712
713 event = (pkt[0] >> 2) & 0x3F;
714 f = (pkt[0] >> 1) & 0x01;
715 x = pkt[0] & 0x01;
716 span_log(&s->logging, SPAN_LOG_FLOW, "SSE event %s\n", v150_1_sse_media_state_to_str(event));
717 if (x)
718 {
719 if (len >= 6)
720 {
721 /* Deal with the extension */
722 ext_len = get_net_unaligned_uint16(&pkt[4]) & 0x7FF;
723 if (ext_len >= 1)
724 {
725 s->rmt_ack = pkt[6] & 0x3F;
726 }
727 /*endif*/
728 }
729 /*endif*/
730 }
731 else
732 {
733 if (len != 4)
734 span_log(&s->logging, SPAN_LOG_FLOW, "Non-extended message of length %d\n", len);
735 /*endif*/
736 }
737 /*endif*/
738 switch (event)
739 {
740 case V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO:
741 res = v150_1_sse_rx_initial_audio_packet(s, pkt, len);
742 break;
743 case V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA:
744 res = v150_1_sse_rx_voice_band_data_packet(s, pkt, len);
745 break;
746 case V150_1_SSE_MEDIA_STATE_MODEM_RELAY:
747 res = v150_1_sse_rx_modem_relay_packet(s, pkt, len);
748 break;
749 case V150_1_SSE_MEDIA_STATE_FAX_RELAY:
750 res = v150_1_sse_rx_fax_relay_packet(s, pkt, len);
751 break;
752 case V150_1_SSE_MEDIA_STATE_TEXT_RELAY:
753 res = v150_1_sse_rx_text_relay_packet(s, pkt, len);
754 break;
755 case V150_1_SSE_MEDIA_STATE_TEXT_PROBE:
756 res = v150_1_sse_rx_text_probe_packet(s, pkt, len);
757 break;
758 default:
759 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected SSE event %d\n", event);
760 res = -1;
761 break;
762 }
763 /*endswitch*/
764 s->rmt_mode = event;
765 }
766 /*endif*/
767 return res;
768}
769/*- End of function --------------------------------------------------------*/
770
771static int v150_1_sse_tx_initial_audio_packet(v150_1_sse_state_t *s)
772{
773 return 0;
774}
775/*- End of function --------------------------------------------------------*/
776
777static int v150_1_sse_tx_voice_band_data_packet(v150_1_sse_state_t *s)
778{
779 return 0;
780}
781/*- End of function --------------------------------------------------------*/
782
783static int v150_1_sse_tx_modem_relay_packet(v150_1_sse_state_t *s, int x, int ric, int ricinfo)
784{
785 int res;
786 uint8_t pkt[256];
787 int len;
788 uint8_t f;
789 span_timestamp_t now;
790
791 /* If we are using explicit acknowledgements, both the F and X bits need to be set */
792 if (s->explicit_acknowledgements)
793 {
794 if (s->force_response)
795 f = 0x03;
796 else
797 f = 0x01;
798 /*endif*/
799 }
800 else
801 {
802 f = 0x00;
803 }
804 /*endif*/
805 span_log(&s->logging, SPAN_LOG_FLOW, "Sending an SSE %s\n", v150_1_sse_ric_to_str(ric));
806 pkt[0] = f | (V150_1_SSE_MEDIA_STATE_MODEM_RELAY << 2);
807 pkt[1] = ric;
808 put_net_unaligned_uint16(&pkt[2], ricinfo);
809 len = 4;
810 switch (ric)
811 {
812 case V150_1_SSE_RIC_CLEARDOWN:
813 /* We may need to add more information as an extension. Note that V.150.1 originally made
814 the SSE message lengths variable in a way that can't really work. The only message this
815 affected was cleardown. Corrigendum 2 changed the extra bytes to an extension field, so
816 all messages are 4 bytes long until the extension bit it used to stretch them. */
817 break;
818 }
819 /*endswitch*/
820 if (s->explicit_acknowledgements)
821 {
822 /* The length of the extension field */
823 put_net_unaligned_uint16(&pkt[len], 1);
824 len += 2;
825 /* The actual content of the field */
826 pkt[len++] = s->rmt_mode;
827 }
828 /*endif*/
829 if (s->packet_handler)
830 res = s->packet_handler(s->packet_user_data, pkt, len);
831 /*endif*/
832 if (s->explicit_acknowledgements)
833 {
834 if (s->timer_handler)
835 {
836 now = s->timer_handler(s->timer_user_data, ~0);
837 s->timer_t0 = now + s->t0interval;
838 s->timer_t1 = now + s->t1interval;
839 s->counter_n0 = s->n0count;
840 s->force_response = false0;
841 update_timer(s);
842 }
843 /*endif*/
844 }
845 /*endif*/
846 return 0;
847}
848/*- End of function --------------------------------------------------------*/
849
850static int v150_1_sse_tx_fax_relay_packet(v150_1_sse_state_t *s, int x, int ric, int ricinfo)
851{
852 int res;
853 uint8_t pkt[256];
854 int len;
855 uint8_t f;
856
857 /* If we are using explicit acknowledgements, both the F and X bits need to be set */
858 if (s->explicit_acknowledgements)
859 {
860 if (s->force_response)
861 f = 0x03;
862 else
863 f = 0x01;
864 /*endif*/
865 }
866 /*endif*/
867 pkt[0] = f | (V150_1_SSE_MEDIA_STATE_FAX_RELAY << 2);
868 pkt[1] = ric;
869 put_net_unaligned_uint16(&pkt[2], ricinfo);
870 len = 4;
871 if (s->explicit_acknowledgements)
872 {
873 put_net_unaligned_uint16(&pkt[len], 1);
874 len += 2;
875 pkt[len++] = s->rmt_mode;
876 }
877 /*endif*/
878 if (s->packet_handler)
879 res = s->packet_handler(s->packet_user_data, pkt, len);
880 /*endif*/
881 return 0;
882}
883/*- End of function --------------------------------------------------------*/
884
885static int v150_1_sse_tx_text_relay_packet(v150_1_sse_state_t *s)
886{
887 return 0;
888}
889/*- End of function --------------------------------------------------------*/
890
891static int v150_1_sse_tx_text_probe_packet(v150_1_sse_state_t *s)
892{
893 return 0;
894}
895/*- End of function --------------------------------------------------------*/
896
897SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_sse_tx_packet(v150_1_sse_state_t *s, int event, int ric, int ricinfo)
898{
899 int res;
900 int x;
901
902 x = 0;
903 span_log(&s->logging, SPAN_LOG_FLOW, "SSE event %s\n", v150_1_sse_media_state_to_str(event));
904 switch (event)
905 {
906 case V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO:
907 res = v150_1_sse_tx_initial_audio_packet(s);
908 break;
909 case V150_1_SSE_MEDIA_STATE_VOICE_BAND_DATA:
910 res = v150_1_sse_tx_voice_band_data_packet(s);
Value stored to 'res' is never read
911 break;
912 case V150_1_SSE_MEDIA_STATE_MODEM_RELAY:
913 res = v150_1_sse_tx_modem_relay_packet(s, x, ric, ricinfo);
914 break;
915 case V150_1_SSE_MEDIA_STATE_FAX_RELAY:
916 res = v150_1_sse_tx_fax_relay_packet(s, x, ric, ricinfo);
917 break;
918 case V150_1_SSE_MEDIA_STATE_TEXT_RELAY:
919 res = v150_1_sse_tx_text_relay_packet(s);
920 break;
921 case V150_1_SSE_MEDIA_STATE_TEXT_PROBE:
922 res = v150_1_sse_tx_text_probe_packet(s);
923 break;
924 default:
925 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected SSE event %d\n", event);
926 res = -1;
927 break;
928 }
929 /*endswitch*/
930 s->lcl_mode = event;
931 return 0;
932}
933/*- End of function --------------------------------------------------------*/
934
935SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_sse_timer_expired(v150_1_sse_state_t *s, span_timestamp_t now)
936{
937 int i;
938
939 span_log(&s->logging, SPAN_LOG_FLOW, "Timer expired at %lu\n", now);
940
941 if (s->immediate_timer)
942 {
943 s->immediate_timer = false0;
944 /* TODO: */
945 }
946 /*endif*/
947 if (s->timer_t0 != 0 && s->timer_t0 <= now)
948 {
949 span_log(&s->logging, SPAN_LOG_FLOW, "T0 expired\n");
950 if (--s->counter_n0 > 0)
951 {
952 span_log(&s->logging, SPAN_LOG_FLOW, "Resend (%d)\n", s->counter_n0);
953 s->timer_t0 = now + s->t0interval;
954 update_timer(s);
955 }
956 else
957 {
958 span_log(&s->logging, SPAN_LOG_FLOW, "Count exceeded\n");
959 }
960 /*endif*/
961 }
962 /*endif*/
963 if (s->timer_t1 != 0 && s->timer_t1 <= now)
964 {
965 span_log(&s->logging, SPAN_LOG_FLOW, "T1 expired\n");
966 }
967 /*endif*/
968 return 0;
969}
970/*- End of function --------------------------------------------------------*/
971
972SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_sse_explicit_acknowledgements(v150_1_sse_state_t *s,
973 bool_Bool explicit_acknowledgements)
974{
975 s->explicit_acknowledgements = explicit_acknowledgements;
976 return 0;
977}
978/*- End of function --------------------------------------------------------*/
979
980SPAN_DECLARE(logging_state_t *)__attribute__((visibility("default"))) logging_state_t * v150_1_sse_get_logging_state(v150_1_sse_state_t *s)
981{
982 return &s->logging;
983}
984/*- End of function --------------------------------------------------------*/
985
986SPAN_DECLARE(v150_1_sse_state_t *)__attribute__((visibility("default"))) v150_1_sse_state_t * v150_1_sse_init(v150_1_sse_state_t *s,
987 v150_1_sse_packet_handler_t packet_handler,
988 void *packet_user_data,
989 v150_1_sse_status_handler_t status_handler,
990 void *status_user_data,
991 v150_1_sse_timer_handler_t timer_handler,
992 void *timer_user_data)
993{
994 if (packet_handler == NULL((void*)0))
995 return NULL((void*)0);
996 /*endif*/
997 if (s == NULL((void*)0))
998 {
999 if ((s = (v150_1_sse_state_t *) malloc(sizeof(*s))) == NULL((void*)0))
1000 return NULL((void*)0);
1001 /*endif*/
1002 }
1003 /*endif*/
1004 memset(s, 0, sizeof(*s));
1005
1006 span_log_init(&s->logging, SPAN_LOG_NONE, NULL((void*)0));
1007 span_log_set_protocol(&s->logging, "V.150.1 SSE");
1008
1009 s->reliability_method = V150_1_SSE_RELIABILITY_NONE;
1010 s->explicit_acknowledgements = false0;
1011 s->repetitions = 3;
1012 s->repetition_interval = 20000;
1013
1014 /* Set default values for the explicit acknowledgement parameters */
1015 /* V.150.1 C.4.3.1 */
1016 s->n0count = 3;
1017 s->t0interval = 10000;
1018 s->t1interval = 300000;
1019
1020 /* V.150.1 C.4.3.1 */
1021 /* Let p be the probability that a packet sent by one MoIP node through the packet
1022 network will be successfully received by the other node.
1023 Let t be the latency that can be tolerated in the delivery of mode updates
1024 Let q be the reliability required in the delivery of mode updates within the given
1025 latency
1026 Let rtd be the round trip delay through the packet network between the two nodes
1027 Let owd be the one way delay through the packet network from one node to the other
1028 (i.e. rtd/2) */
1029 //s->n0count = floor(log(1 - q)/log(1 - p));
1030 //s->t0interval = max(0, ((rtd/2) - t)/(n0count - 1));
1031 //s->t1interval = 1.5*rtd;
1032
1033 /* V.150.1 C.5.3 */
1034 s->lcl_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
1035 s->rmt_mode = V150_1_SSE_MEDIA_STATE_INITIAL_AUDIO;
1036
1037 s->previous_rx_timestamp = 0xFFFFFFFF;
1038
1039 s->packet_handler = packet_handler;
1040 s->packet_user_data = packet_user_data;
1041 s->status_handler = status_handler;
1042 s->status_user_data = status_user_data;
1043 s->timer_handler = timer_handler;
1044 s->timer_user_data = timer_user_data;
1045
1046 return s;
1047}
1048/*- End of function --------------------------------------------------------*/
1049/*- End of file ------------------------------------------------------------*/