Asterisk - The Open Source Telephony Project  GIT-master-0190e70
res_pjsip_t38.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \author Joshua Colp <jcolp@digium.com>
22  *
23  * \brief SIP T.38 handling
24  */
25 
26 /*** MODULEINFO
27  <depend>pjproject</depend>
28  <depend>res_pjsip</depend>
29  <depend>res_pjsip_session</depend>
30  <support_level>core</support_level>
31  ***/
32 
33 #include "asterisk.h"
34 
35 #include <pjsip.h>
36 #include <pjsip_ua.h>
37 #include <pjmedia.h>
38 #include <pjlib.h>
39 
40 #include "asterisk/utils.h"
41 #include "asterisk/module.h"
42 #include "asterisk/udptl.h"
43 #include "asterisk/netsock2.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/acl.h"
46 #include "asterisk/stream.h"
47 #include "asterisk/format_cache.h"
48 
49 #include "asterisk/res_pjsip.h"
51 
52 /*! \brief The number of seconds after receiving a T.38 re-invite before automatically rejecting it */
53 #define T38_AUTOMATIC_REJECTION_SECONDS 5
54 
55 /*! \brief Address for UDPTL */
56 static struct ast_sockaddr address;
57 
58 /*! \brief T.38 state information */
59 struct t38_state {
60  /*! \brief Current state */
62  /*! \brief Our T.38 parameters */
64  /*! \brief Their T.38 parameters */
66  /*! \brief Timer entry for automatically rejecting an inbound re-invite */
67  pj_timer_entry timer;
68  /*! Preserved media state for when T.38 ends */
70 };
71 
72 /*! \brief Destructor for T.38 state information */
73 static void t38_state_destroy(void *obj)
74 {
75  struct t38_state *state = obj;
76 
78  ast_free(obj);
79 }
80 
81 /*! \brief Datastore for attaching T.38 state information */
82 static const struct ast_datastore_info t38_datastore = {
83  .type = "t38",
84  .destroy = t38_state_destroy,
85 };
86 
87 /*! \brief Structure for T.38 parameters task data */
89  /*! \brief Session itself */
91  /*! \brief T.38 control frame */
92  struct ast_frame *frame;
93 };
94 
95 /*! \brief Destructor for T.38 data */
96 static void t38_parameters_task_data_destroy(void *obj)
97 {
98  struct t38_parameters_task_data *data = obj;
99 
100  ao2_cleanup(data->session);
101 
102  if (data->frame) {
103  ast_frfree(data->frame);
104  }
105 }
106 
107 /*! \brief Allocator for T.38 data */
109  struct ast_frame *frame)
110 {
112 
113  if (!data) {
114  return NULL;
115  }
116 
117  data->session = session;
118  ao2_ref(session, +1);
119  data->frame = ast_frdup(frame);
120  if (!data->frame) {
121  ao2_ref(data, -1);
122  data = NULL;
123  }
124 
125  return data;
126 }
127 
128 /*! \brief Helper function for changing the T.38 state */
129 static void t38_change_state(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
130  struct t38_state *state, enum ast_sip_session_t38state new_state)
131 {
132  enum ast_sip_session_t38state old_state = session->t38state;
133  struct ast_control_t38_parameters parameters = { .request_response = 0, };
134  pj_time_val delay = { .sec = T38_AUTOMATIC_REJECTION_SECONDS };
135 
136  if (old_state == new_state) {
137  return;
138  }
139 
140  session->t38state = new_state;
141  ast_debug(2, "T.38 state changed to '%u' from '%u' on channel '%s'\n",
142  new_state, old_state,
143  session->channel ? ast_channel_name(session->channel) : "<gone>");
144 
145  if (pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
146  &state->timer, 0)) {
147  ast_debug(2, "Automatic T.38 rejection on channel '%s' terminated\n",
148  session->channel ? ast_channel_name(session->channel) : "<gone>");
149  ao2_ref(session, -1);
150  }
151 
152  if (!session->channel) {
153  return;
154  }
155 
156  switch (new_state) {
157  case T38_PEER_REINVITE:
158  ao2_ref(session, +1);
159  if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &state->timer, &delay) != PJ_SUCCESS) {
160  ast_log(LOG_WARNING, "Scheduling of automatic T.38 rejection for channel '%s' failed\n",
161  ast_channel_name(session->channel));
162  ao2_ref(session, -1);
163  }
164  parameters = state->their_parms;
165  parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
167  ast_udptl_set_tag(session_media->udptl, "%s", ast_channel_name(session->channel));
168 
169  /* Inform the bridge the channel is in that it needs to be reconfigured */
170  ast_channel_set_unbridged(session->channel, 1);
171  break;
172  case T38_ENABLED:
173  parameters = state->their_parms;
174  parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
176  ast_udptl_set_tag(session_media->udptl, "%s", ast_channel_name(session->channel));
177  break;
178  case T38_REJECTED:
179  case T38_DISABLED:
180  if (old_state == T38_ENABLED) {
182  } else if (old_state == T38_LOCAL_REINVITE) {
183  parameters.request_response = AST_T38_REFUSED;
184  }
185  break;
186  case T38_LOCAL_REINVITE:
187  /* Inform the bridge the channel is in that it needs to be reconfigured */
188  ast_channel_set_unbridged(session->channel, 1);
189  break;
190  case T38_MAX_ENUM:
191  /* Well, that shouldn't happen */
192  ast_assert(0);
193  break;
194  }
195 
196  if (parameters.request_response) {
197  ast_queue_control_data(session->channel, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
198  }
199 }
200 
201 /*! \brief Task function which rejects a T.38 re-invite and resumes handling it */
202 static int t38_automatic_reject(void *obj)
203 {
204  RAII_VAR(struct ast_sip_session *, session, obj, ao2_cleanup);
206 
207  if (!datastore) {
208  return 0;
209  }
210 
211  ast_debug(2, "Automatically rejecting T.38 request on channel '%s'\n",
212  session->channel ? ast_channel_name(session->channel) : "<gone>");
213 
214  t38_change_state(session, NULL, datastore->data, T38_REJECTED);
216 
217  return 0;
218 }
219 
220 /*! \brief Timer entry callback which queues a task to reject a T.38 re-invite and resume handling it */
221 static void t38_automatic_reject_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
222 {
223  struct ast_sip_session *session = entry->user_data;
224 
225  if (ast_sip_push_task(session->serializer, t38_automatic_reject, session)) {
226  ao2_ref(session, -1);
227  }
228 }
229 
230 /*! \brief Helper function which retrieves or allocates a T.38 state information datastore */
232 {
233  RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "t38"), ao2_cleanup);
234  struct t38_state *state;
235 
236  /* While the datastore refcount is decremented this is operating in the serializer so it will remain valid regardless */
237  if (datastore) {
238  return datastore->data;
239  }
240 
241  if (!(datastore = ast_sip_session_alloc_datastore(&t38_datastore, "t38"))
242  || !(datastore->data = ast_calloc(1, sizeof(struct t38_state)))
243  || ast_sip_session_add_datastore(session, datastore)) {
244  return NULL;
245  }
246 
247  state = datastore->data;
248 
249  /* This will get bumped up before scheduling */
250  pj_timer_entry_init(&state->timer, 0, session, t38_automatic_reject_timer_cb);
251 
252  return state;
253 }
254 
255 /*! \brief Initializes UDPTL support on a session, only done when actually needed */
256 static int t38_initialize_session(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
257 {
258  if (session_media->udptl) {
259  return 0;
260  }
261 
262  if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, &address))) {
263  return -1;
264  }
265 
267  ast_udptl_setnat(session_media->udptl, session->endpoint->media.t38.nat);
269  ast_debug(3, "UDPTL initialized on session for %s\n", ast_channel_name(session->channel));
270 
271  return 0;
272 }
273 
274 /*! \brief Callback for when T.38 reinvite SDP is created */
275 static int t38_reinvite_sdp_cb(struct ast_sip_session *session, pjmedia_sdp_session *sdp)
276 {
277  struct t38_state *state;
278 
279  state = t38_state_get_or_alloc(session);
280  if (!state) {
281  return -1;
282  }
283 
285 
286  return 0;
287 }
288 
289 /*! \brief Callback for when a response is received for a T.38 re-invite */
290 static int t38_reinvite_response_cb(struct ast_sip_session *session, pjsip_rx_data *rdata)
291 {
292  struct pjsip_status_line status = rdata->msg_info.msg->line.status;
293  struct t38_state *state;
294  struct ast_sip_session_media *session_media = NULL;
295 
296  if (status.code / 100 <= 1) {
297  /* Ignore any non-final responses (1xx) */
298  return 0;
299  }
300 
301  if (session->t38state != T38_LOCAL_REINVITE) {
302  /* Do nothing. We have already processed a final response. */
303  ast_debug(3, "Received %d response to T.38 re-invite on '%s' but already had a final response (T.38 state:%d)\n",
304  status.code,
305  session->channel ? ast_channel_name(session->channel) : "unknown channel",
306  session->t38state);
307  return 0;
308  }
309 
310  state = t38_state_get_or_alloc(session);
311  if (!session->channel || !state) {
312  ast_log(LOG_WARNING, "Received %d response to T.38 re-invite on '%s' but state unavailable\n",
313  status.code,
314  session->channel ? ast_channel_name(session->channel) : "unknown channel");
315  return 0;
316  }
317 
318  if (status.code / 100 == 2) {
319  /* Accept any 2xx response as successfully negotiated */
320  int index;
321 
322  session_media = session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
323  if (!session_media) {
324  ast_log(LOG_WARNING, "Received %d response to T.38 re-invite on '%s' but no active session media\n",
325  status.code, session->channel ? ast_channel_name(session->channel) : "unknown channel");
326  } else {
327  t38_change_state(session, session_media, state, T38_ENABLED);
328 
329  /* Stop all the streams in the stored away active state, they'll go back to being active once
330  * we reinvite back.
331  */
332  for (index = 0; index < AST_VECTOR_SIZE(&state->media_state->sessions); ++index) {
333  struct ast_sip_session_media *session_media = AST_VECTOR_GET(&state->media_state->sessions, index);
334 
335  if (session_media && session_media->handler && session_media->handler->stream_stop) {
336  session_media->handler->stream_stop(session_media);
337  }
338  }
339 
340  return 0;
341  }
342  } else {
343  session_media = session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
344  }
345 
346  /* If no session_media then response contained a declined stream, so disable */
347  t38_change_state(session, NULL, state, session_media ? T38_REJECTED : T38_DISABLED);
348 
349  /* Abort this attempt at switching to T.38 by resetting the pending state and freeing our stored away active state */
351  state->media_state = NULL;
353 
354  return 0;
355 }
356 
357 /*! \brief Helper function which creates a media state for strictly T.38 */
359 {
361  struct ast_stream *stream;
362  struct ast_format_cap *caps;
363  struct ast_sip_session_media *session_media;
364 
365  media_state = ast_sip_session_media_state_alloc();
366  if (!media_state) {
367  return NULL;
368  }
369 
370  media_state->topology = ast_stream_topology_alloc();
371  if (!media_state->topology) {
373  return NULL;
374  }
375 
376  stream = ast_stream_alloc("t38", AST_MEDIA_TYPE_IMAGE);
377  if (!stream) {
379  return NULL;
380  }
381 
383  if (ast_stream_topology_set_stream(media_state->topology, 0, stream)) {
384  ast_stream_free(stream);
386  return NULL;
387  }
388 
390  if (!caps) {
392  return NULL;
393  }
394 
395  ast_stream_set_formats(stream, caps);
396  /* stream holds a reference to cap, release the local reference
397  * now so we don't have to deal with it in the error condition. */
398  ao2_ref(caps, -1);
399  if (ast_format_cap_append(caps, ast_format_t38, 0)) {
401  return NULL;
402  }
403 
404  session_media = ast_sip_session_media_state_add(session, media_state, AST_MEDIA_TYPE_IMAGE, 0);
405  if (!session_media) {
407  return NULL;
408  }
409 
410  if (t38_initialize_session(session, session_media)) {
412  return NULL;
413  }
414 
415  return media_state;
416 }
417 
418 /*! \brief Task for reacting to T.38 control frame */
419 static int t38_interpret_parameters(void *obj)
420 {
421  RAII_VAR(struct t38_parameters_task_data *, data, obj, ao2_cleanup);
422  const struct ast_control_t38_parameters *parameters = data->frame->data.ptr;
423  struct t38_state *state = t38_state_get_or_alloc(data->session);
424  struct ast_sip_session_media *session_media = NULL;
425 
426  if (!state) {
427  return 0;
428  }
429 
430  switch (parameters->request_response) {
431  case AST_T38_NEGOTIATED:
432  case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */
433  /* Negotiation can not take place without a valid max_ifp value. */
434  if (!parameters->max_ifp) {
435  if (data->session->t38state == T38_PEER_REINVITE) {
436  t38_change_state(data->session, NULL, state, T38_REJECTED);
437  ast_sip_session_resume_reinvite(data->session);
438  } else if (data->session->t38state == T38_ENABLED) {
439  t38_change_state(data->session, NULL, state, T38_DISABLED);
440  ast_sip_session_refresh(data->session, NULL, NULL, NULL,
442  state->media_state = NULL;
443  }
444  break;
445  } else if (data->session->t38state == T38_PEER_REINVITE) {
446  state->our_parms = *parameters;
447  /* modify our parameters to conform to the peer's parameters,
448  * based on the rules in the ITU T.38 recommendation
449  */
450  if (!state->their_parms.fill_bit_removal) {
451  state->our_parms.fill_bit_removal = 0;
452  }
453  if (!state->their_parms.transcoding_mmr) {
454  state->our_parms.transcoding_mmr = 0;
455  }
456  if (!state->their_parms.transcoding_jbig) {
457  state->our_parms.transcoding_jbig = 0;
458  }
459  state->our_parms.version = MIN(state->our_parms.version, state->their_parms.version);
461  session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
462  if (!session_media) {
463  ast_log(LOG_ERROR, "Failed to negotiate parameters for reinvite on channel '%s' (No pending session media).\n",
464  data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
465  break;
466  }
467  ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
468  t38_change_state(data->session, session_media, state, T38_ENABLED);
469  ast_sip_session_resume_reinvite(data->session);
470  } else if ((data->session->t38state != T38_ENABLED) ||
471  ((data->session->t38state == T38_ENABLED) &&
472  (parameters->request_response == AST_T38_REQUEST_NEGOTIATE))) {
474 
475  media_state = t38_create_media_state(data->session);
476  if (!media_state) {
477  break;
478  }
479  state->our_parms = *parameters;
480  session_media = media_state->default_session[AST_MEDIA_TYPE_IMAGE];
481  if (!session_media) {
482  ast_log(LOG_ERROR, "Failed to negotiate parameters on channel '%s' (No default session media).\n",
483  data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
484  break;
485  }
486  ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
487  t38_change_state(data->session, NULL, state, T38_LOCAL_REINVITE);
489  AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, media_state);
490  }
491  break;
492  case AST_T38_TERMINATED:
493  case AST_T38_REFUSED:
494  case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */
495  if (data->session->t38state == T38_PEER_REINVITE) {
496  t38_change_state(data->session, NULL, state, T38_REJECTED);
497  ast_sip_session_resume_reinvite(data->session);
498  } else if (data->session->t38state == T38_ENABLED) {
499  t38_change_state(data->session, NULL, state, T38_DISABLED);
501  state->media_state = NULL;
502  }
503  break;
504  case AST_T38_REQUEST_PARMS: { /* Application wants remote's parameters re-sent */
505  struct ast_control_t38_parameters parameters = state->their_parms;
506 
507  if (data->session->t38state == T38_PEER_REINVITE) {
508  session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
509  if (!session_media) {
510  ast_log(LOG_ERROR, "Failed to request parameters for reinvite on channel '%s' (No pending session media).\n",
511  data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
512  break;
513  }
514  parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
516  ast_queue_control_data(data->session->channel, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
517  }
518  break;
519  }
520  default:
521  break;
522  }
523 
524  return 0;
525 }
526 
527 /*! \brief Frame hook callback for T.38 related stuff */
528 static struct ast_frame *t38_framehook(struct ast_channel *chan, struct ast_frame *f,
529  enum ast_framehook_event event, void *data)
530 {
532 
533  if (event != AST_FRAMEHOOK_EVENT_WRITE) {
534  return f;
535  }
536 
537  if (f->frametype == AST_FRAME_CONTROL
539  if (channel->session->endpoint->media.t38.enabled) {
541 
542  task_data = t38_parameters_task_data_alloc(channel->session, f);
543  if (task_data
544  && ast_sip_push_task(channel->session->serializer,
545  t38_interpret_parameters, task_data)) {
546  ao2_ref(task_data, -1);
547  }
548  } else {
549  static const struct ast_control_t38_parameters rsp_refused = {
551  };
552  static const struct ast_control_t38_parameters rsp_terminated = {
554  };
555  const struct ast_control_t38_parameters *parameters = f->data.ptr;
556 
557  switch (parameters->request_response) {
559  ast_debug(2, "T.38 support not enabled on %s, refusing T.38 negotiation\n",
560  ast_channel_name(chan));
562  &rsp_refused, sizeof(rsp_refused));
563  break;
565  ast_debug(2, "T.38 support not enabled on %s, 'terminating' T.38 session\n",
566  ast_channel_name(chan));
568  &rsp_terminated, sizeof(rsp_terminated));
569  break;
570  default:
571  break;
572  }
573  }
574  }
575 
576  return f;
577 }
578 
579 static void t38_masq(void *data, int framehook_id,
580  struct ast_channel *old_chan, struct ast_channel *new_chan)
581 {
582  if (ast_channel_tech(old_chan) == ast_channel_tech(new_chan)) {
583  return;
584  }
585 
586  /* This framehook is only applicable to PJSIP channels */
587  ast_framehook_detach(new_chan, framehook_id);
588 }
589 
590 static int t38_consume(void *data, enum ast_frame_type type)
591 {
592  return (type == AST_FRAME_CONTROL) ? 1 : 0;
593 }
594 
596  .type = "T38 framehook",
597 };
598 
599 /*! \brief Function called to attach T.38 framehook to channel when appropriate */
601 {
602  int framehook_id;
603  struct ast_datastore *datastore = NULL;
604  static struct ast_framehook_interface hook = {
606  .event_cb = t38_framehook,
607  .consume_cb = t38_consume,
608  .chan_fixup_cb = t38_masq,
609  .chan_breakdown_cb = t38_masq,
610  };
611 
612  /* If the channel's already gone, bail */
613  if (!session->channel) {
614  return;
615  }
616 
617  /* Always attach the framehook so we can quickly reject */
618 
619  ast_channel_lock(session->channel);
620 
621  /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
622  datastore = ast_channel_datastore_find(session->channel, &t38_framehook_datastore,
623  NULL);
624  if (datastore) {
625  ast_channel_unlock(session->channel);
626  return;
627  }
628 
629  framehook_id = ast_framehook_attach(session->channel, &hook);
630  if (framehook_id < 0) {
631  ast_log(LOG_WARNING, "Could not attach T.38 Frame hook, T.38 will be unavailable on '%s'\n",
632  ast_channel_name(session->channel));
633  ast_channel_unlock(session->channel);
634  return;
635  }
636 
637  datastore = ast_datastore_alloc(&t38_framehook_datastore, NULL);
638  if (!datastore) {
639  ast_log(LOG_ERROR, "Could not alloc T.38 Frame hook datastore, T.38 will be unavailable on '%s'\n",
640  ast_channel_name(session->channel));
641  ast_framehook_detach(session->channel, framehook_id);
642  ast_channel_unlock(session->channel);
643  return;
644  }
645 
646  ast_channel_datastore_add(session->channel, datastore);
647  ast_channel_unlock(session->channel);
648 }
649 
650 /*! \brief Function called when an INVITE arrives */
651 static int t38_incoming_invite_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
652 {
653  t38_attach_framehook(session);
654  return 0;
655 }
656 
657 /*! \brief Function called when an INVITE is sent */
658 static void t38_outgoing_invite_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
659 {
660  t38_attach_framehook(session);
661 }
662 
663 /*! \brief Get Max T.38 Transmission rate from T38 capabilities */
664 static unsigned int t38_get_rate(enum ast_control_t38_rate rate)
665 {
666  switch (rate) {
667  case AST_T38_RATE_2400:
668  return 2400;
669  case AST_T38_RATE_4800:
670  return 4800;
671  case AST_T38_RATE_7200:
672  return 7200;
673  case AST_T38_RATE_9600:
674  return 9600;
675  case AST_T38_RATE_12000:
676  return 12000;
677  case AST_T38_RATE_14400:
678  return 14400;
679  default:
680  return 0;
681  }
682 }
683 
684 /*! \brief Supplement for adding framehook to session channel */
686  .method = "INVITE",
687  .priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL + 1,
688  .incoming_request = t38_incoming_invite_request,
689  .outgoing_request = t38_outgoing_invite_request,
690 };
691 
692 /*! \brief Parse a T.38 image stream and store the attribute information */
693 static void t38_interpret_sdp(struct t38_state *state, struct ast_sip_session *session, struct ast_sip_session_media *session_media,
694  const struct pjmedia_sdp_media *stream)
695 {
696  unsigned int attr_i;
697 
698  for (attr_i = 0; attr_i < stream->attr_count; attr_i++) {
699  pjmedia_sdp_attr *attr = stream->attr[attr_i];
700 
701  if (!pj_stricmp2(&attr->name, "t38faxmaxbuffer")) {
702  /* This is purposely left empty, it is unused */
703  } else if (!pj_stricmp2(&attr->name, "t38maxbitrate") || !pj_stricmp2(&attr->name, "t38faxmaxrate")) {
704  switch (pj_strtoul(&attr->value)) {
705  case 14400:
707  break;
708  case 12000:
710  break;
711  case 9600:
713  break;
714  case 7200:
716  break;
717  case 4800:
719  break;
720  case 2400:
722  break;
723  }
724  } else if (!pj_stricmp2(&attr->name, "t38faxversion")) {
725  state->their_parms.version = pj_strtoul(&attr->value);
726  } else if (!pj_stricmp2(&attr->name, "t38faxmaxdatagram") || !pj_stricmp2(&attr->name, "t38maxdatagram")) {
727  if (!session->endpoint->media.t38.maxdatagram) {
728  ast_udptl_set_far_max_datagram(session_media->udptl, pj_strtoul(&attr->value));
729  }
730  } else if (!pj_stricmp2(&attr->name, "t38faxfillbitremoval")) {
731  state->their_parms.fill_bit_removal = 1;
732  } else if (!pj_stricmp2(&attr->name, "t38faxtranscodingmmr")) {
733  state->their_parms.transcoding_mmr = 1;
734  } else if (!pj_stricmp2(&attr->name, "t38faxtranscodingjbig")) {
735  state->their_parms.transcoding_jbig = 1;
736  } else if (!pj_stricmp2(&attr->name, "t38faxratemanagement")) {
737  if (!pj_stricmp2(&attr->value, "localTCF")) {
739  } else if (!pj_stricmp2(&attr->value, "transferredTCF")) {
741  }
742  } else if (!pj_stricmp2(&attr->name, "t38faxudpec")) {
743  if (session->t38state == T38_LOCAL_REINVITE) {
745  if (!pj_stricmp2(&attr->value, "t38UDPFEC")) {
747  } else if (!pj_stricmp2(&attr->value, "t38UDPRedundancy")) {
749  } else {
751  }
753  if (!pj_stricmp2(&attr->value, "t38UDPRedundancy")) {
755  } else {
757  }
758  } else {
760  }
761  } else {
762  if (!pj_stricmp2(&attr->value, "t38UDPRedundancy")) {
764  } else if (!pj_stricmp2(&attr->value, "t38UDPFEC")) {
766  } else {
768  }
769  }
770  }
771 
772  }
773 }
774 
775 /*! \brief Function which defers an incoming media stream */
777  struct ast_sip_session *session, struct ast_sip_session_media *session_media,
778  const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
779 {
780  struct t38_state *state;
781 
782  if (!session->endpoint->media.t38.enabled) {
783  ast_debug(3, "Not deferring incoming SDP stream: T.38 not enabled on %s\n", ast_channel_name(session->channel));
785  }
786 
787  if (t38_initialize_session(session, session_media)) {
788  ast_debug(3, "Not deferring incoming SDP stream: Failed to initialize UDPTL on %s\n", ast_channel_name(session->channel));
790  }
791 
792  if (!(state = t38_state_get_or_alloc(session))) {
794  }
795 
796  t38_interpret_sdp(state, session, session_media, stream);
797 
798  /* If they are initiating the re-invite we need to defer responding until later */
799  if (session->t38state == T38_DISABLED) {
800  t38_change_state(session, session_media, state, T38_PEER_REINVITE);
801  ast_debug(3, "Deferring incoming SDP stream on %s for peer re-invite\n", ast_channel_name(session->channel));
803  }
804 
806 }
807 
808 /*! \brief Function which negotiates an incoming media stream */
810  struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp,
811  int index, struct ast_stream *asterisk_stream)
812 {
813  struct t38_state *state;
814  char host[NI_MAXHOST];
815  pjmedia_sdp_media *stream = sdp->media[index];
816  RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
817 
818  if (!session->endpoint->media.t38.enabled) {
819  ast_debug(3, "Declining; T.38 not enabled on session\n");
820  return 0;
821  }
822 
823  if (!(state = t38_state_get_or_alloc(session))) {
824  return 0;
825  }
826 
827  if ((session->t38state == T38_REJECTED) || (session->t38state == T38_DISABLED)) {
828  ast_debug(3, "Declining; T.38 state is rejected or declined\n");
829  t38_change_state(session, NULL, state, T38_DISABLED);
830  return 0;
831  }
832 
833  ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
834 
835  /* Ensure that the address provided is valid */
836  if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_INET) <= 0) {
837  /* The provided host was actually invalid so we error out this negotiation */
838  ast_debug(3, "Declining; provided host is invalid\n");
839  return 0;
840  }
841 
842  /* Check the address family to make sure it matches configured */
843  if ((ast_sockaddr_is_ipv6(addrs) && !session->endpoint->media.t38.ipv6) ||
844  (ast_sockaddr_is_ipv4(addrs) && session->endpoint->media.t38.ipv6)) {
845  /* The address does not match configured */
846  ast_debug(3, "Declining, provided host does not match configured address family\n");
847  return 0;
848  }
849 
850  return 1;
851 }
852 
853 /*! \brief Function which creates an outgoing stream */
855  struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
856 {
857  pj_pool_t *pool = session->inv_session->pool_prov;
858  static const pj_str_t STR_IN = { "IN", 2 };
859  static const pj_str_t STR_IP4 = { "IP4", 3};
860  static const pj_str_t STR_IP6 = { "IP6", 3};
861  static const pj_str_t STR_UDPTL = { "udptl", 5 };
862  static const pj_str_t STR_T38 = { "t38", 3 };
863  static const pj_str_t STR_TRANSFERREDTCF = { "transferredTCF", 14 };
864  static const pj_str_t STR_LOCALTCF = { "localTCF", 8 };
865  static const pj_str_t STR_T38UDPFEC = { "t38UDPFEC", 9 };
866  static const pj_str_t STR_T38UDPREDUNDANCY = { "t38UDPRedundancy", 16 };
867  struct t38_state *state;
868  pjmedia_sdp_media *media;
869  const char *hostip = NULL;
870  struct ast_sockaddr addr;
871  char tmp[512];
872  pj_str_t stmp;
873 
874  if (!session->endpoint->media.t38.enabled) {
875  ast_debug(3, "Not creating outgoing SDP stream: T.38 not enabled\n");
876  return 1;
877  } else if ((session->t38state != T38_LOCAL_REINVITE) && (session->t38state != T38_PEER_REINVITE) &&
878  (session->t38state != T38_ENABLED)) {
879  ast_debug(3, "Not creating outgoing SDP stream: T.38 not enabled\n");
880  return 1;
881  } else if (!(state = t38_state_get_or_alloc(session))) {
882  return -1;
883  } else if (t38_initialize_session(session, session_media)) {
884  ast_debug(3, "Not creating outgoing SDP stream: Failed to initialize T.38 session\n");
885  return -1;
886  }
887 
888  if (!(media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media))) ||
889  !(media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn)))) {
890  return -1;
891  }
892 
893  pj_strdup2(pool, &media->desc.media, ast_codec_media_type2str(session_media->type));
894  media->desc.transport = STR_UDPTL;
895 
896  if (ast_strlen_zero(session->endpoint->media.address)) {
897  hostip = ast_sip_get_host_ip_string(session->endpoint->media.t38.ipv6 ? pj_AF_INET6() : pj_AF_INET());
898  } else {
899  hostip = session->endpoint->media.address;
900  }
901 
902  if (ast_strlen_zero(hostip)) {
903  ast_debug(3, "Not creating outgoing SDP stream: no known host IP\n");
904  return -1;
905  }
906 
907  media->conn->net_type = STR_IN;
908  media->conn->addr_type = session->endpoint->media.t38.ipv6 ? STR_IP6 : STR_IP4;
909  pj_strdup2(pool, &media->conn->addr, hostip);
910  ast_udptl_get_us(session_media->udptl, &addr);
911  media->desc.port = (pj_uint16_t) ast_sockaddr_port(&addr);
912  media->desc.port_count = 1;
913  media->desc.fmt[media->desc.fmt_count++] = STR_T38;
914 
915  snprintf(tmp, sizeof(tmp), "%u", state->our_parms.version);
916  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxVersion", pj_cstr(&stmp, tmp));
917 
918  snprintf(tmp, sizeof(tmp), "%u", t38_get_rate(state->our_parms.rate));
919  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38MaxBitRate", pj_cstr(&stmp, tmp));
920 
921  if (state->our_parms.fill_bit_removal) {
922  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxFillBitRemoval", NULL);
923  }
924 
925  if (state->our_parms.transcoding_mmr) {
926  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxTranscodingMMR", NULL);
927  }
928 
929  if (state->our_parms.transcoding_jbig) {
930  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxTranscodingJBIG", NULL);
931  }
932 
933  switch (state->our_parms.rate_management) {
935  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxRateManagement", &STR_TRANSFERREDTCF);
936  break;
938  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxRateManagement", &STR_LOCALTCF);
939  break;
940  }
941 
942  snprintf(tmp, sizeof(tmp), "%u", ast_udptl_get_local_max_datagram(session_media->udptl));
943  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxMaxDatagram", pj_cstr(&stmp, tmp));
944 
945  switch (ast_udptl_get_error_correction_scheme(session_media->udptl)) {
947  break;
949  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxUdpEC", &STR_T38UDPFEC);
950  break;
952  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxUdpEC", &STR_T38UDPREDUNDANCY);
953  break;
954  }
955 
956  sdp->media[sdp->media_count++] = media;
957 
958  return 1;
959 }
960 
962 {
963  struct ast_frame *frame;
964 
965  if (!session_media->udptl) {
966  return &ast_null_frame;
967  }
968 
969  frame = ast_udptl_read(session_media->udptl);
970  if (!frame) {
971  return NULL;
972  }
973 
974  frame->stream_num = session_media->stream_num;
975 
976  return frame;
977 }
978 
979 static int media_session_udptl_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
980 {
981  if (!session_media->udptl) {
982  return 0;
983  }
984 
985  return ast_udptl_write(session_media->udptl, frame);
986 }
987 
988 /*! \brief Function which applies a negotiated stream */
990  struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local,
991  const struct pjmedia_sdp_session *remote, int index, struct ast_stream *asterisk_stream)
992 {
993  RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
994  pjmedia_sdp_media *remote_stream = remote->media[index];
995  char host[NI_MAXHOST];
996  struct t38_state *state;
997 
998  if (!session_media->udptl) {
999  ast_debug(3, "Not applying negotiated SDP stream: no UDTPL session\n");
1000  return 0;
1001  }
1002 
1003  if (!(state = t38_state_get_or_alloc(session))) {
1004  return -1;
1005  }
1006 
1007  ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
1008 
1009  /* Ensure that the address provided is valid */
1010  if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
1011  /* The provided host was actually invalid so we error out this negotiation */
1012  ast_debug(3, "Not applying negotiated SDP stream: failed to resolve remote stream host\n");
1013  return -1;
1014  }
1015 
1016  ast_sockaddr_set_port(addrs, remote_stream->desc.port);
1017  ast_udptl_set_peer(session_media->udptl, addrs);
1018 
1019  t38_interpret_sdp(state, session, session_media, remote_stream);
1020 
1022  ast_sip_session_media_add_read_callback(session, session_media, ast_udptl_fd(session_media->udptl),
1024 
1025  return 0;
1026 }
1027 
1028 /*! \brief Function which updates the media stream with external media address, if applicable */
1029 static void change_outgoing_sdp_stream_media_address(pjsip_tx_data *tdata, struct pjmedia_sdp_media *stream, struct ast_sip_transport *transport)
1030 {
1032  char host[NI_MAXHOST];
1033  struct ast_sockaddr our_sdp_addr = { { 0, } };
1034 
1035  /* If the stream has been rejected there will be no connection line */
1036  if (!stream->conn || !transport_state) {
1037  return;
1038  }
1039 
1040  ast_copy_pj_str(host, &stream->conn->addr, sizeof(host));
1041  ast_sockaddr_parse(&our_sdp_addr, host, PARSE_PORT_FORBID);
1042 
1043  /* Reversed check here. We don't check the remote endpoint being
1044  * in our local net, but whether our outgoing session IP is
1045  * local. If it is not, we won't do rewriting. No localnet
1046  * configured? Always rewrite. */
1047  if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) {
1048  return;
1049  }
1050  ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_host(&transport_state->external_media_address));
1051  pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_host(&transport_state->external_media_address));
1052 }
1053 
1054 /*! \brief Function which destroys the UDPTL instance when session ends */
1055 static void stream_destroy(struct ast_sip_session_media *session_media)
1056 {
1057  if (session_media->udptl) {
1058  ast_udptl_destroy(session_media->udptl);
1059  }
1060  session_media->udptl = NULL;
1061 }
1062 
1063 /*! \brief SDP handler for 'image' media stream */
1065  .id = "image",
1066  .defer_incoming_sdp_stream = defer_incoming_sdp_stream,
1067  .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,
1068  .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
1069  .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
1070  .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
1071  .stream_destroy = stream_destroy,
1072 };
1073 
1074 /*! \brief Unloads the SIP T.38 module from Asterisk */
1075 static int unload_module(void)
1076 {
1077  ast_sip_session_unregister_sdp_handler(&image_sdp_handler, "image");
1078  ast_sip_session_unregister_supplement(&t38_supplement);
1079 
1080  return 0;
1081 }
1082 
1083 /*!
1084  * \brief Load the module
1085  *
1086  * Module loading including tests for configuration or dependencies.
1087  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
1088  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
1089  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
1090  * configuration file or other non-critical problem return
1091  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
1092  */
1093 static int load_module(void)
1094 {
1095  if (ast_check_ipv6()) {
1096  ast_sockaddr_parse(&address, "::", 0);
1097  } else {
1098  ast_sockaddr_parse(&address, "0.0.0.0", 0);
1099  }
1100 
1101  ast_sip_session_register_supplement(&t38_supplement);
1102 
1103  if (ast_sip_session_register_sdp_handler(&image_sdp_handler, "image")) {
1104  ast_log(LOG_ERROR, "Unable to register SDP handler for image stream type\n");
1105  goto end;
1106  }
1107 
1108  return AST_MODULE_LOAD_SUCCESS;
1109 end:
1110  unload_module();
1111 
1112  return AST_MODULE_LOAD_DECLINE;
1113 }
1114 
1115 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP T.38 UDPTL Support",
1116  .support_level = AST_MODULE_SUPPORT_CORE,
1117  .load = load_module,
1118  .unload = unload_module,
1119  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
1120  .requires = "res_pjsip,res_pjsip_session,udptl",
1121 );
const char * type
Definition: datastore.h:32
unsigned int maxdatagram
Definition: res_pjsip.h:743
static const char type[]
Definition: chan_ooh323.c:109
enum ast_sip_session_t38state t38state
#define ast_channel_lock(chan)
Definition: channel.h:2890
#define T38_ENABLED
Definition: chan_ooh323.c:102
Main Channel structure associated with a channel.
struct ast_sip_endpoint * endpoint
static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
Function which creates an outgoing stream.
struct ast_sip_session_media_state * ast_sip_session_media_state_alloc(void)
Allocate a session media state structure.
#define ast_frdup(fr)
Copies a frame.
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.
Asterisk main include file. File version handling, generic pbx functions.
Structure which contains media state information (streams, sessions)
#define ast_sip_transport_is_nonlocal(transport_state, addr)
Definition: res_pjsip.h:159
struct ast_sip_session_media_state * pending_media_state
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
Definition: udptl.c:973
static struct ast_frame * media_session_udptl_read_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
static int t38_reinvite_response_cb(struct ast_sip_session *session, pjsip_rx_data *rdata)
Callback for when a response is received for a T.38 re-invite.
static struct ast_sip_session_supplement t38_supplement
Supplement for adding framehook to session channel.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, int index, struct ast_stream *asterisk_stream)
Function which negotiates an incoming media stream.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
static void t38_change_state(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct t38_state *state, enum ast_sip_session_t38state new_state)
Helper function for changing the T.38 state.
char * address
Definition: f2c.h:59
struct ast_udptl * udptl
UDPTL instance itself.
enum ast_t38_ec_modes error_correction
Definition: res_pjsip.h:741
#define LOG_WARNING
Definition: logger.h:274
#define T38_AUTOMATIC_REJECTION_SECONDS
The number of seconds after receiving a T.38 re-invite before automatically rejecting it...
Definition: res_pjsip_t38.c:53
ast_framehook_event
These are the types of events that the framehook&#39;s event callback can receive.
Definition: framehook.h:151
union ast_frame::@257 data
static int tmp()
Definition: bt_open.c:389
static int load_module(void)
Load the module.
T.38 state information.
Definition: res_pjsip_t38.c:59
A handler for SDPs in SIP sessions.
static enum ast_sip_session_sdp_stream_defer defer_incoming_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
Function which defers an incoming media stream.
static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_session *remote, int index, struct ast_stream *asterisk_stream)
Function which applies a negotiated stream.
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
UDPTL support for T.38.
static struct ast_sip_session_sdp_handler image_sdp_handler
SDP handler for &#39;image&#39; media stream.
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
retrieves local_max_datagram.
Definition: udptl.c:984
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
enum ast_control_t38 request_response
Structure for a data store type.
Definition: datastore.h:31
A structure which contains a channel implementation and session.
const ast_string_field address
Definition: res_pjsip.h:755
Definition: astman.c:222
struct ast_sip_session * session
Pointer to session.
static struct ast_sip_session_media_state * t38_create_media_state(struct ast_sip_session *session)
Helper function which creates a media state for strictly T.38.
enum ast_sip_session_t38state state
Current state.
Definition: res_pjsip_t38.c:61
void ast_udptl_set_far_max_datagram(struct ast_udptl *udptl, unsigned int max_datagram)
sets far max datagram size. If max_datagram is = 0, the far max datagram size is set to a default val...
Definition: udptl.c:997
#define ast_assert(a)
Definition: utils.h:650
Definition: muted.c:95
Structure for a data store object.
Definition: datastore.h:68
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:5093
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2390
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Definition: pjsip_session.c:63
#define NULL
Definition: resample.c:96
void ast_udptl_destroy(struct ast_udptl *udptl)
Definition: udptl.c:1150
static int t38_automatic_reject(void *obj)
Task function which rejects a T.38 re-invite and resumes handling it.
struct ast_sip_session_media_state * ast_sip_session_media_state_clone(const struct ast_sip_session_media_state *media_state)
Clone a media state.
char * end
Definition: eagi_proxy.c:73
struct ast_frame * frame
T.38 control frame.
Definition: res_pjsip_t38.c:92
struct pjsip_inv_session * inv_session
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
Socket address structure.
Definition: netsock2.h:97
int ast_stream_topology_set_stream(struct ast_stream_topology *topology, unsigned int position, struct ast_stream *stream)
Set a specific position in a topology.
Definition: stream.c:796
A structure describing a SIP session.
static int t38_consume(void *data, enum ast_frame_type type)
struct ast_frame_subclass subclass
Media Stream API.
enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme(const struct ast_udptl *udptl)
Definition: udptl.c:940
Utility functions.
struct ast_sip_session_media_state * active_media_state
const char * ast_sip_get_host_ip_string(int af)
Retrieve the local host address in string form.
Definition: res_pjsip.c:5326
struct ast_sip_session * session
Session itself.
Definition: res_pjsip_t38.c:90
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:838
void ast_udptl_get_us(const struct ast_udptl *udptl, struct ast_sockaddr *us)
Definition: udptl.c:1140
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
#define MIN(a, b)
Definition: utils.h:226
struct ast_sip_session_media * ast_sip_session_media_state_add(struct ast_sip_session *session, struct ast_sip_session_media_state *media_state, enum ast_media_type type, int position)
Allocate an ast_session_media and add it to the media state&#39;s vector.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
static struct ast_frame * t38_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
Frame hook callback for T.38 related stuff.
static char host[256]
Definition: muted.c:77
Structure for SIP transport information.
Definition: res_pjsip.h:84
static void t38_attach_framehook(struct ast_sip_session *session)
Function called to attach T.38 framehook to channel when appropriate.
General Asterisk PBX channel definitions.
int ast_sip_session_register_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Register an SDP handler.
struct ast_datastore * ast_sip_session_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
Definition: main/utils.c:2411
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:851
static int t38_incoming_invite_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Function called when an INVITE arrives.
static struct ast_mansession session
struct ast_sip_session_media_state * media_state
Definition: res_pjsip_t38.c:69
static int media_session_udptl_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
Access Control of various sorts.
int ast_sip_session_refresh(struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, enum ast_sip_session_refresh_method method, int generate_new_sdp, struct ast_sip_session_media_state *media_state)
Send a reinvite or UPDATE on a session.
static struct t38_state * t38_state_get_or_alloc(struct ast_sip_session *session)
Helper function which retrieves or allocates a T.38 state information datastore.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
enum ast_control_t38_rate rate
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2309
struct ast_channel * channel
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
void ast_sip_session_resume_reinvite(struct ast_sip_session *session)
Resumes processing of a deferred incoming re-invite.
ast_sip_session_t38state
T.38 states for a session.
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
void ast_sip_session_unregister_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Unregister an SDP handler.
Network socket handling.
struct ast_taskprocessor * serializer
ast_frame_type
Frame types.
int stream_num
The stream number to place into any resulting frames.
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
retrieves far max ifp
Definition: udptl.c:1016
Set when the stream is sending and receiving media.
Definition: stream.h:82
#define LOG_ERROR
Definition: logger.h:285
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
void ast_udptl_set_peer(struct ast_udptl *udptl, const struct ast_sockaddr *them)
Definition: udptl.c:1130
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
static void t38_masq(void *data, int framehook_id, struct ast_channel *old_chan, struct ast_channel *new_chan)
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:4991
Transport to bind to.
Definition: res_pjsip.h:168
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
#define T38_DISABLED
Definition: chan_ooh323.c:101
static void t38_interpret_sdp(struct t38_state *state, struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream)
Parse a T.38 image stream and store the attribute information.
userdata associated with baseline taskprocessor test
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_sip_t38_configuration t38
Definition: res_pjsip.h:765
ast_sip_session_sdp_stream_defer
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2891
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
static void t38_outgoing_invite_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
Function called when an INVITE is sent.
#define ast_free(a)
Definition: astmm.h:182
ast_control_t38_rate
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int ast_sip_session_media_add_read_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, int fd, ast_sip_session_media_read_cb callback)
Set a read callback for a media session with a specific file descriptor.
static int unload_module(void)
Unloads the SIP T.38 module from Asterisk.
struct ast_control_t38_parameters our_parms
Our T.38 parameters.
Definition: res_pjsip_t38.c:63
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
int ast_udptl_fd(const struct ast_udptl *udptl)
Definition: udptl.c:730
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static const struct ast_datastore_info t38_framehook_datastore
static int t38_reinvite_sdp_cb(struct ast_sip_session *session, pjmedia_sdp_session *sdp)
Callback for when T.38 reinvite SDP is created.
struct ast_control_t38_parameters their_parms
Their T.38 parameters.
Definition: res_pjsip_t38.c:65
A structure containing SIP session media information.
pj_timer_entry timer
Timer entry for automatically rejecting an inbound re-invite.
Definition: res_pjsip_t38.c:67
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct ast_udptl * ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *in)
Definition: udptl.c:1028
A supplement to SIP message processing.
struct ast_frame * ast_udptl_read(struct ast_udptl *udptl)
Definition: udptl.c:762
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3614
struct ast_frame ast_null_frame
Definition: main/frame.c:79
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
Definition: stream.c:292
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
static unsigned int t38_get_rate(enum ast_control_t38_rate rate)
Get Max T.38 Transmission rate from T38 capabilities.
enum ast_media_type type
Media type of this session media.
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
Definition: stream.c:233
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_stream_topology * topology
The media stream topology.
Structure for T.38 parameters task data.
Definition: res_pjsip_t38.c:88
struct ast_sip_session_sdp_handler * handler
SDP handler that setup the RTP.
const char * ast_channel_name(const struct ast_channel *chan)
void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
Definition: udptl.c:945
#define ast_frfree(fr)
int ast_udptl_write(struct ast_udptl *udptl, struct ast_frame *f)
Definition: udptl.c:1161
static const struct ast_datastore_info t38_datastore
Datastore for attaching T.38 state information.
Definition: res_pjsip_t38.c:82
enum ast_control_t38_rate_management rate_management
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition: channel.c:1234
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
void ast_udptl_set_tag(struct ast_udptl *udptl, const char *format,...)
Associates a character string &#39;tag&#39; with a UDPTL session.
Definition: udptl.c:1112
Data structure associated with a single frame of data.
int ast_sip_session_media_set_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, ast_sip_session_media_write_cb callback)
Set a write callback for a media session.
static int t38_initialize_session(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
Initializes UDPTL support on a session, only done when actually needed.
Definition: search.h:40
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
enum ast_frame_type frametype
void ast_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state)
Reset a media state to a clean state.
static void stream_destroy(struct ast_sip_session_media *session_media)
Function which destroys the UDPTL instance when session ends.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2376
static void change_outgoing_sdp_stream_media_address(pjsip_tx_data *tdata, struct pjmedia_sdp_media *stream, struct ast_sip_transport *transport)
Function which updates the media stream with external media address, if applicable.
void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
Definition: udptl.c:745
static struct t38_parameters_task_data * t38_parameters_task_data_alloc(struct ast_sip_session *session, struct ast_frame *frame)
Allocator for T.38 data.
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
struct ast_format * ast_format_t38
Built-in cached T.38 format.
Definition: format_cache.c:246
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
static int t38_interpret_parameters(void *obj)
Task for reacting to T.38 control frame.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
static void t38_parameters_task_data_destroy(void *obj)
Destructor for T.38 data.
Definition: res_pjsip_t38.c:96
void(* stream_stop)(struct ast_sip_session_media *session_media)
Stop a session_media created by this handler but do not destroy resources.
static void t38_automatic_reject_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
Timer entry callback which queues a task to reject a T.38 re-invite and resume handling it...
int ast_sip_session_add_datastore(struct ast_sip_session *session, struct ast_datastore *datastore)
Add a datastore to a SIP session.
void ast_channel_set_unbridged(struct ast_channel *chan, int value)
Sets the unbridged flag and queues a NULL frame on the channel to trigger a check by bridge_channel_w...
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:331
Media Format Cache API.
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
Definition: netsock2.c:280
#define ast_sip_session_register_supplement(supplement)
static void t38_state_destroy(void *obj)
Destructor for T.38 state information.
Definition: res_pjsip_t38.c:73