Asterisk - The Open Source Telephony Project  GIT-master-b7027de
Data Structures | Macros | Functions | Variables
res_pjsip_t38.c File Reference

SIP T.38 handling. More...

#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjmedia.h>
#include <pjlib.h>
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/udptl.h"
#include "asterisk/netsock2.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/stream.h"
#include "asterisk/format_cache.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"

Go to the source code of this file.

Data Structures

struct  t38_parameters_task_data
 Structure for T.38 parameters task data. More...
 
struct  t38_state
 T.38 state information. More...
 

Macros

#define T38_AUTOMATIC_REJECTION_SECONDS   5
 The number of seconds after receiving a T.38 re-invite before automatically rejecting it. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
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. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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. More...
 
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. More...
 
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. More...
 
static int load_module (void)
 Load the module. More...
 
static struct ast_framemedia_session_udptl_read_callback (struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 
static int media_session_udptl_write_callback (struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
 
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. More...
 
static void stream_destroy (struct ast_sip_session_media *session_media)
 Function which destroys the UDPTL instance when session ends. More...
 
static void t38_attach_framehook (struct ast_sip_session *session)
 Function called to attach T.38 framehook to channel when appropriate. More...
 
static int t38_automatic_reject (void *obj)
 Task function which rejects a T.38 re-invite and resumes handling it. More...
 
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. More...
 
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. More...
 
static int t38_consume (void *data, enum ast_frame_type type)
 
static struct ast_sip_session_media_statet38_create_media_state (struct ast_sip_session *session)
 Helper function which creates a media state for strictly T.38. More...
 
static struct ast_framet38_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 Frame hook callback for T.38 related stuff. More...
 
static unsigned int t38_get_rate (enum ast_control_t38_rate rate)
 Get Max T.38 Transmission rate from T38 capabilities. More...
 
static int t38_incoming_invite_request (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 Function called when an INVITE arrives. More...
 
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. More...
 
static int t38_interpret_parameters (void *obj)
 Task for reacting to T.38 control frame. More...
 
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. More...
 
static void t38_masq (void *data, int framehook_id, struct ast_channel *old_chan, struct ast_channel *new_chan)
 
static void t38_outgoing_invite_request (struct ast_sip_session *session, struct pjsip_tx_data *tdata)
 Function called when an INVITE is sent. More...
 
static struct t38_parameters_task_datat38_parameters_task_data_alloc (struct ast_sip_session *session, struct ast_frame *frame)
 Allocator for T.38 data. More...
 
static void t38_parameters_task_data_destroy (void *obj)
 Destructor for T.38 data. More...
 
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. More...
 
static int t38_reinvite_sdp_cb (struct ast_sip_session *session, pjmedia_sdp_session *sdp)
 Callback for when T.38 reinvite SDP is created. More...
 
static void t38_state_destroy (void *obj)
 Destructor for T.38 state information. More...
 
static struct t38_statet38_state_get_or_alloc (struct ast_sip_session *session)
 Helper function which retrieves or allocates a T.38 state information datastore. More...
 
static int unload_module (void)
 Unloads the SIP T.38 module from Asterisk. More...
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP T.38 UDPTL Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "res_pjsip,res_pjsip_session,udptl", }
 
static struct ast_sockaddr address
 Address for UDPTL. More...
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_sip_session_sdp_handler image_sdp_handler
 SDP handler for 'image' media stream. More...
 
static const struct ast_datastore_info t38_datastore
 Datastore for attaching T.38 state information. More...
 
static const struct ast_datastore_info t38_framehook_datastore
 
static struct ast_sip_session_supplement t38_supplement
 Supplement for adding framehook to session channel. More...
 

Detailed Description

SIP T.38 handling.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file res_pjsip_t38.c.

Macro Definition Documentation

◆ T38_AUTOMATIC_REJECTION_SECONDS

#define T38_AUTOMATIC_REJECTION_SECONDS   5

The number of seconds after receiving a T.38 re-invite before automatically rejecting it.

Definition at line 53 of file res_pjsip_t38.c.

Referenced by t38_change_state().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1130 of file res_pjsip_t38.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1130 of file res_pjsip_t38.c.

◆ apply_negotiated_sdp_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 
)
static

Function which applies a negotiated stream.

Definition at line 998 of file res_pjsip_t38.c.

References AST_AF_UNSPEC, ast_copy_pj_str(), ast_debug, ast_free, ast_sip_session_media_add_read_callback(), ast_sip_session_media_set_write_callback(), ast_sockaddr_resolve(), ast_sockaddr_set_port, ast_udptl_fd(), ast_udptl_set_peer(), host, media_session_udptl_read_callback(), media_session_udptl_write_callback(), NULL, PARSE_PORT_FORBID, RAII_VAR, t38_state::state, t38_interpret_sdp(), t38_state_get_or_alloc(), and ast_sip_session_media::udptl.

1001 {
1002  RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
1003  pjmedia_sdp_media *remote_stream = remote->media[index];
1004  char host[NI_MAXHOST];
1005  struct t38_state *state;
1006 
1007  if (!session_media->udptl) {
1008  ast_debug(3, "Not applying negotiated SDP stream: no UDTPL session\n");
1009  return 0;
1010  }
1011 
1012  if (!(state = t38_state_get_or_alloc(session))) {
1013  return -1;
1014  }
1015 
1016  ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
1017 
1018  /* Ensure that the address provided is valid */
1019  if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
1020  /* The provided host was actually invalid so we error out this negotiation */
1021  ast_debug(3, "Not applying negotiated SDP stream: failed to resolve remote stream host\n");
1022  return -1;
1023  }
1024 
1025  ast_sockaddr_set_port(addrs, remote_stream->desc.port);
1026  ast_udptl_set_peer(session_media->udptl, addrs);
1027 
1028  t38_interpret_sdp(state, session, session_media, remote_stream);
1029 
1031  ast_sip_session_media_add_read_callback(session, session_media, ast_udptl_fd(session_media->udptl),
1033 
1034  return 0;
1035 }
enum sip_cc_notify_state state
Definition: chan_sip.c:960
static struct ast_frame * media_session_udptl_read_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
struct ast_udptl * udptl
UDPTL instance itself.
T.38 state information.
Definition: res_pjsip_t38.c:59
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:5240
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static char host[256]
Definition: muted.c:77
#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:911
static int media_session_udptl_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
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.
void ast_udptl_set_peer(struct ast_udptl *udptl, const struct ast_sockaddr *them)
Definition: udptl.c:1130
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
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.
#define ast_free(a)
Definition: astmm.h:182
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.
int ast_udptl_fd(const struct ast_udptl *udptl)
Definition: udptl.c:730
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.
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

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1130 of file res_pjsip_t38.c.

◆ change_outgoing_sdp_stream_media_address()

static void change_outgoing_sdp_stream_media_address ( pjsip_tx_data *  tdata,
struct pjmedia_sdp_media *  stream,
struct ast_sip_transport transport 
)
static

Function which updates the media stream with external media address, if applicable.

Definition at line 1038 of file res_pjsip_t38.c.

References ao2_cleanup, ast_copy_pj_str(), ast_debug, ast_sip_get_transport_state(), ast_sip_transport_is_nonlocal, ast_sockaddr_parse(), ast_sockaddr_stringify_host(), ast_sorcery_object_get_id(), host, PARSE_PORT_FORBID, and RAII_VAR.

1039 {
1041  char host[NI_MAXHOST];
1042  struct ast_sockaddr our_sdp_addr = { { 0, } };
1043 
1044  /* If the stream has been rejected there will be no connection line */
1045  if (!stream->conn || !transport_state) {
1046  return;
1047  }
1048 
1049  ast_copy_pj_str(host, &stream->conn->addr, sizeof(host));
1050  ast_sockaddr_parse(&our_sdp_addr, host, PARSE_PORT_FORBID);
1051 
1052  /* Reversed check here. We don't check the remote endpoint being
1053  * in our local net, but whether our outgoing session IP is
1054  * local. If it is not, we won't do rewriting. No localnet
1055  * configured? Always rewrite. */
1056  if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) {
1057  return;
1058  }
1059  ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_host(&transport_state->external_media_address));
1060  pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_host(&transport_state->external_media_address));
1061 }
#define ast_sip_transport_is_nonlocal(transport_state, addr)
Definition: res_pjsip.h:162
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
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:5240
Socket address structure.
Definition: netsock2.h:97
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static char host[256]
Definition: muted.c:77
Structure for SIP transport information.
Definition: res_pjsip.h:87
#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:911
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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

◆ create_outgoing_sdp_stream()

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 
)
static

Function which creates an outgoing stream.

Definition at line 863 of file res_pjsip_t38.c.

References ast_sip_endpoint_media_configuration::address, ast_codec_media_type2str(), ast_debug, ast_sip_get_host_ip_string(), ast_sockaddr_port, ast_strlen_zero, AST_T38_RATE_MANAGEMENT_LOCAL_TCF, AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF, ast_udptl_get_error_correction_scheme(), ast_udptl_get_local_max_datagram(), ast_udptl_get_us(), ast_sip_t38_configuration::enabled, ast_sip_session::endpoint, ast_control_t38_parameters::fill_bit_removal, ast_sip_session::inv_session, ast_sip_t38_configuration::ipv6, ast_sip_endpoint::media, NULL, t38_state::our_parms, ast_control_t38_parameters::rate, ast_control_t38_parameters::rate_management, t38_state::state, ast_sip_endpoint_media_configuration::t38, T38_ENABLED, t38_get_rate(), t38_initialize_session(), T38_LOCAL_REINVITE, T38_PEER_REINVITE, t38_state_get_or_alloc(), ast_sip_session::t38state, tmp(), ast_control_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_mmr, ast_sip_session_media::type, ast_sip_session_media::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and ast_control_t38_parameters::version.

865 {
866  pj_pool_t *pool = session->inv_session->pool_prov;
867  static const pj_str_t STR_IN = { "IN", 2 };
868  static const pj_str_t STR_IP4 = { "IP4", 3};
869  static const pj_str_t STR_IP6 = { "IP6", 3};
870  static const pj_str_t STR_UDPTL = { "udptl", 5 };
871  static const pj_str_t STR_T38 = { "t38", 3 };
872  static const pj_str_t STR_TRANSFERREDTCF = { "transferredTCF", 14 };
873  static const pj_str_t STR_LOCALTCF = { "localTCF", 8 };
874  static const pj_str_t STR_T38UDPFEC = { "t38UDPFEC", 9 };
875  static const pj_str_t STR_T38UDPREDUNDANCY = { "t38UDPRedundancy", 16 };
876  struct t38_state *state;
877  pjmedia_sdp_media *media;
878  const char *hostip = NULL;
879  struct ast_sockaddr addr;
880  char tmp[512];
881  pj_str_t stmp;
882 
883  if (!session->endpoint->media.t38.enabled) {
884  ast_debug(3, "Not creating outgoing SDP stream: T.38 not enabled\n");
885  return 1;
886  } else if ((session->t38state != T38_LOCAL_REINVITE) && (session->t38state != T38_PEER_REINVITE) &&
887  (session->t38state != T38_ENABLED)) {
888  ast_debug(3, "Not creating outgoing SDP stream: T.38 not enabled\n");
889  return 1;
890  } else if (!(state = t38_state_get_or_alloc(session))) {
891  return -1;
892  } else if (t38_initialize_session(session, session_media)) {
893  ast_debug(3, "Not creating outgoing SDP stream: Failed to initialize T.38 session\n");
894  return -1;
895  }
896 
897  if (!(media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media))) ||
898  !(media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn)))) {
899  return -1;
900  }
901 
902  pj_strdup2(pool, &media->desc.media, ast_codec_media_type2str(session_media->type));
903  media->desc.transport = STR_UDPTL;
904 
905  if (ast_strlen_zero(session->endpoint->media.address)) {
906  hostip = ast_sip_get_host_ip_string(session->endpoint->media.t38.ipv6 ? pj_AF_INET6() : pj_AF_INET());
907  } else {
908  hostip = session->endpoint->media.address;
909  }
910 
911  if (ast_strlen_zero(hostip)) {
912  ast_debug(3, "Not creating outgoing SDP stream: no known host IP\n");
913  return -1;
914  }
915 
916  media->conn->net_type = STR_IN;
917  media->conn->addr_type = session->endpoint->media.t38.ipv6 ? STR_IP6 : STR_IP4;
918  pj_strdup2(pool, &media->conn->addr, hostip);
919  ast_udptl_get_us(session_media->udptl, &addr);
920  media->desc.port = (pj_uint16_t) ast_sockaddr_port(&addr);
921  media->desc.port_count = 1;
922  media->desc.fmt[media->desc.fmt_count++] = STR_T38;
923 
924  snprintf(tmp, sizeof(tmp), "%u", state->our_parms.version);
925  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxVersion", pj_cstr(&stmp, tmp));
926 
927  snprintf(tmp, sizeof(tmp), "%u", t38_get_rate(state->our_parms.rate));
928  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38MaxBitRate", pj_cstr(&stmp, tmp));
929 
930  if (state->our_parms.fill_bit_removal) {
931  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxFillBitRemoval", NULL);
932  }
933 
934  if (state->our_parms.transcoding_mmr) {
935  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxTranscodingMMR", NULL);
936  }
937 
938  if (state->our_parms.transcoding_jbig) {
939  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxTranscodingJBIG", NULL);
940  }
941 
942  switch (state->our_parms.rate_management) {
944  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxRateManagement", &STR_TRANSFERREDTCF);
945  break;
947  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxRateManagement", &STR_LOCALTCF);
948  break;
949  }
950 
951  snprintf(tmp, sizeof(tmp), "%u", ast_udptl_get_local_max_datagram(session_media->udptl));
952  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxMaxDatagram", pj_cstr(&stmp, tmp));
953 
954  switch (ast_udptl_get_error_correction_scheme(session_media->udptl)) {
956  break;
958  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxUdpEC", &STR_T38UDPFEC);
959  break;
961  media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxUdpEC", &STR_T38UDPREDUNDANCY);
962  break;
963  }
964 
965  sdp->media[sdp->media_count++] = media;
966 
967  return 1;
968 }
enum sip_cc_notify_state state
Definition: chan_sip.c:960
enum ast_sip_session_t38state t38state
#define T38_ENABLED
Definition: chan_ooh323.c:102
struct ast_sip_endpoint * endpoint
struct ast_udptl * udptl
UDPTL instance itself.
static int tmp()
Definition: bt_open.c:389
T.38 state information.
Definition: res_pjsip_t38.c:59
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
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
retrieves local_max_datagram.
Definition: udptl.c:984
const ast_string_field address
Definition: res_pjsip.h:758
#define NULL
Definition: resample.c:96
struct pjsip_inv_session * inv_session
Socket address structure.
Definition: netsock2.h:97
enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme(const struct ast_udptl *udptl)
Definition: udptl.c:940
const char * ast_sip_get_host_ip_string(int af)
Retrieve the local host address in string form.
Definition: res_pjsip.c:5473
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
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.
enum ast_control_t38_rate rate
struct ast_sip_t38_configuration t38
Definition: res_pjsip.h:768
#define ast_strlen_zero(a)
Definition: muted.c:73
struct ast_control_t38_parameters our_parms
Our T.38 parameters.
Definition: res_pjsip_t38.c:63
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.
enum ast_control_t38_rate_management rate_management
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.

◆ defer_incoming_sdp_stream()

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 
)
static

Function which defers an incoming media stream.

Definition at line 785 of file res_pjsip_t38.c.

References ast_channel_name(), ast_debug, AST_SIP_SESSION_SDP_DEFER_ERROR, AST_SIP_SESSION_SDP_DEFER_NEEDED, AST_SIP_SESSION_SDP_DEFER_NOT_HANDLED, AST_SIP_SESSION_SDP_DEFER_NOT_NEEDED, ast_sip_session::channel, ast_sip_t38_configuration::enabled, ast_sip_session::endpoint, ast_sip_endpoint::media, t38_state::state, ast_sip_endpoint_media_configuration::t38, t38_change_state(), T38_DISABLED, t38_initialize_session(), t38_interpret_sdp(), T38_PEER_REINVITE, t38_state_get_or_alloc(), and ast_sip_session::t38state.

788 {
789  struct t38_state *state;
790 
791  if (!session->endpoint->media.t38.enabled) {
792  ast_debug(3, "Not deferring incoming SDP stream: T.38 not enabled on %s\n", ast_channel_name(session->channel));
794  }
795 
796  if (t38_initialize_session(session, session_media)) {
797  ast_debug(3, "Not deferring incoming SDP stream: Failed to initialize UDPTL on %s\n", ast_channel_name(session->channel));
799  }
800 
801  if (!(state = t38_state_get_or_alloc(session))) {
803  }
804 
805  t38_interpret_sdp(state, session, session_media, stream);
806 
807  /* If they are initiating the re-invite we need to defer responding until later */
808  if (session->t38state == T38_DISABLED) {
809  t38_change_state(session, session_media, state, T38_PEER_REINVITE);
810  ast_debug(3, "Deferring incoming SDP stream on %s for peer re-invite\n", ast_channel_name(session->channel));
812  }
813 
815 }
enum sip_cc_notify_state state
Definition: chan_sip.c:960
enum ast_sip_session_t38state t38state
struct ast_sip_endpoint * endpoint
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.
T.38 state information.
Definition: res_pjsip_t38.c:59
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
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.
struct ast_channel * channel
#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.
struct ast_sip_t38_configuration t38
Definition: res_pjsip.h:768
const char * ast_channel_name(const struct ast_channel *chan)
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.

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 1102 of file res_pjsip_t38.c.

References ast_check_ipv6(), ast_log, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DRIVER, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_CORE, ast_sip_session_register_sdp_handler(), ast_sip_session_register_supplement, ast_sockaddr_parse(), ASTERISK_GPL_KEY, end, LOG_ERROR, and unload_module().

1103 {
1104  if (ast_check_ipv6()) {
1105  ast_sockaddr_parse(&address, "::", 0);
1106  } else {
1107  ast_sockaddr_parse(&address, "0.0.0.0", 0);
1108  }
1109 
1111 
1113  ast_log(LOG_ERROR, "Unable to register SDP handler for image stream type\n");
1114  goto end;
1115  }
1116 
1117  return AST_MODULE_LOAD_SUCCESS;
1118 end:
1119  unload_module();
1120 
1121  return AST_MODULE_LOAD_DECLINE;
1122 }
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
char * address
Definition: f2c.h:59
static struct ast_sip_session_sdp_handler image_sdp_handler
SDP handler for &#39;image&#39; media stream.
char * end
Definition: eagi_proxy.c:73
#define ast_log
Definition: astobj2.c:42
int ast_sip_session_register_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Register an SDP handler.
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
Definition: main/utils.c:2540
#define LOG_ERROR
Definition: logger.h:285
static int unload_module(void)
Unloads the SIP T.38 module from Asterisk.
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_sip_session_register_supplement(supplement)

◆ media_session_udptl_read_callback()

static struct ast_frame* media_session_udptl_read_callback ( struct ast_sip_session session,
struct ast_sip_session_media session_media 
)
static

Definition at line 970 of file res_pjsip_t38.c.

References ast_null_frame, ast_udptl_read(), NULL, ast_sip_session_media::stream_num, ast_frame::stream_num, and ast_sip_session_media::udptl.

Referenced by apply_negotiated_sdp_stream().

971 {
972  struct ast_frame *frame;
973 
974  if (!session_media->udptl) {
975  return &ast_null_frame;
976  }
977 
978  frame = ast_udptl_read(session_media->udptl);
979  if (!frame) {
980  return NULL;
981  }
982 
983  frame->stream_num = session_media->stream_num;
984 
985  return frame;
986 }
struct ast_udptl * udptl
UDPTL instance itself.
#define NULL
Definition: resample.c:96
int stream_num
The stream number to place into any resulting frames.
struct ast_frame * ast_udptl_read(struct ast_udptl *udptl)
Definition: udptl.c:762
struct ast_frame ast_null_frame
Definition: main/frame.c:79
Data structure associated with a single frame of data.

◆ media_session_udptl_write_callback()

static int media_session_udptl_write_callback ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
struct ast_frame frame 
)
static

Definition at line 988 of file res_pjsip_t38.c.

References ast_udptl_write(), and ast_sip_session_media::udptl.

Referenced by apply_negotiated_sdp_stream().

989 {
990  if (!session_media->udptl) {
991  return 0;
992  }
993 
994  return ast_udptl_write(session_media->udptl, frame);
995 }
struct ast_udptl * udptl
UDPTL instance itself.
int ast_udptl_write(struct ast_udptl *udptl, struct ast_frame *f)
Definition: udptl.c:1161

◆ negotiate_incoming_sdp_stream()

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 
)
static

Function which negotiates an incoming media stream.

Definition at line 818 of file res_pjsip_t38.c.

References AST_AF_INET, ast_copy_pj_str(), ast_debug, ast_free, ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_resolve(), ast_sip_t38_configuration::enabled, ast_sip_session::endpoint, host, ast_sip_t38_configuration::ipv6, ast_sip_endpoint::media, NULL, PARSE_PORT_FORBID, RAII_VAR, t38_state::state, ast_sip_endpoint_media_configuration::t38, t38_change_state(), T38_DISABLED, T38_REJECTED, t38_state_get_or_alloc(), and ast_sip_session::t38state.

821 {
822  struct t38_state *state;
823  char host[NI_MAXHOST];
824  pjmedia_sdp_media *stream = sdp->media[index];
825  RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
826 
827  if (!session->endpoint->media.t38.enabled) {
828  ast_debug(3, "Declining; T.38 not enabled on session\n");
829  return 0;
830  }
831 
832  if (!(state = t38_state_get_or_alloc(session))) {
833  return 0;
834  }
835 
836  if ((session->t38state == T38_REJECTED) || (session->t38state == T38_DISABLED)) {
837  ast_debug(3, "Declining; T.38 state is rejected or declined\n");
838  t38_change_state(session, NULL, state, T38_DISABLED);
839  return 0;
840  }
841 
842  ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
843 
844  /* Ensure that the address provided is valid */
845  if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_INET) <= 0) {
846  /* The provided host was actually invalid so we error out this negotiation */
847  ast_debug(3, "Declining; provided host is invalid\n");
848  return 0;
849  }
850 
851  /* Check the address family to make sure it matches configured */
852  if ((ast_sockaddr_is_ipv6(addrs) && !session->endpoint->media.t38.ipv6) ||
853  (ast_sockaddr_is_ipv4(addrs) && session->endpoint->media.t38.ipv6)) {
854  /* The address does not match configured */
855  ast_debug(3, "Declining, provided host does not match configured address family\n");
856  return 0;
857  }
858 
859  return 1;
860 }
enum sip_cc_notify_state state
Definition: chan_sip.c:960
enum ast_sip_session_t38state t38state
struct ast_sip_endpoint * endpoint
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.
T.38 state information.
Definition: res_pjsip_t38.c:59
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:5240
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static char host[256]
Definition: muted.c:77
#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:911
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 T38_DISABLED
Definition: chan_ooh323.c:101
struct ast_sip_t38_configuration t38
Definition: res_pjsip.h:768
#define ast_free(a)
Definition: astmm.h:182
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
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

◆ stream_destroy()

static void stream_destroy ( struct ast_sip_session_media session_media)
static

Function which destroys the UDPTL instance when session ends.

Definition at line 1064 of file res_pjsip_t38.c.

References ast_udptl_destroy(), NULL, and ast_sip_session_media::udptl.

1065 {
1066  if (session_media->udptl) {
1067  ast_udptl_destroy(session_media->udptl);
1068  }
1069  session_media->udptl = NULL;
1070 }
struct ast_udptl * udptl
UDPTL instance itself.
#define NULL
Definition: resample.c:96
void ast_udptl_destroy(struct ast_udptl *udptl)
Definition: udptl.c:1150

◆ t38_attach_framehook()

static void t38_attach_framehook ( struct ast_sip_session session)
static

Function called to attach T.38 framehook to channel when appropriate.

Definition at line 609 of file res_pjsip_t38.c.

References ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_datastore_alloc, ast_framehook_attach(), ast_framehook_detach(), AST_FRAMEHOOK_INTERFACE_VERSION, ast_log, ast_sip_session::channel, LOG_ERROR, LOG_WARNING, NULL, t38_consume(), t38_framehook(), t38_masq(), and ast_framehook_interface::version.

Referenced by t38_incoming_invite_request(), and t38_outgoing_invite_request().

610 {
611  int framehook_id;
612  struct ast_datastore *datastore = NULL;
613  static struct ast_framehook_interface hook = {
615  .event_cb = t38_framehook,
616  .consume_cb = t38_consume,
617  .chan_fixup_cb = t38_masq,
618  .chan_breakdown_cb = t38_masq,
619  };
620 
621  /* If the channel's already gone, bail */
622  if (!session->channel) {
623  return;
624  }
625 
626  /* Always attach the framehook so we can quickly reject */
627 
628  ast_channel_lock(session->channel);
629 
630  /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
632  NULL);
633  if (datastore) {
634  ast_channel_unlock(session->channel);
635  return;
636  }
637 
638  framehook_id = ast_framehook_attach(session->channel, &hook);
639  if (framehook_id < 0) {
640  ast_log(LOG_WARNING, "Could not attach T.38 Frame hook, T.38 will be unavailable on '%s'\n",
641  ast_channel_name(session->channel));
642  ast_channel_unlock(session->channel);
643  return;
644  }
645 
647  if (!datastore) {
648  ast_log(LOG_ERROR, "Could not alloc T.38 Frame hook datastore, T.38 will be unavailable on '%s'\n",
649  ast_channel_name(session->channel));
650  ast_framehook_detach(session->channel, framehook_id);
651  ast_channel_unlock(session->channel);
652  return;
653  }
654 
655  ast_channel_datastore_add(session->channel, datastore);
656  ast_channel_unlock(session->channel);
657 }
#define ast_channel_lock(chan)
Definition: channel.h:2902
#define LOG_WARNING
Definition: logger.h:274
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
Structure for a data store object.
Definition: datastore.h:68
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
#define NULL
Definition: resample.c:96
static int t38_consume(void *data, enum ast_frame_type type)
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 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.
struct ast_channel * channel
#define LOG_ERROR
Definition: logger.h:285
static void t38_masq(void *data, int framehook_id, struct ast_channel *old_chan, struct ast_channel *new_chan)
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
#define ast_channel_unlock(chan)
Definition: channel.h:2903
static const struct ast_datastore_info t38_framehook_datastore
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2376

◆ t38_automatic_reject()

static int t38_automatic_reject ( void *  obj)
static

Task function which rejects a T.38 re-invite and resumes handling it.

Definition at line 202 of file res_pjsip_t38.c.

References ao2_cleanup, ast_channel_name(), ast_debug, ast_sip_session_get_datastore(), ast_sip_session_resume_reinvite(), NULL, RAII_VAR, session, t38_change_state(), and T38_REJECTED.

Referenced by t38_automatic_reject_timer_cb().

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 }
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.
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
A structure describing a SIP session.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
#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:911
static struct ast_mansession session
void ast_sip_session_resume_reinvite(struct ast_sip_session *session)
Resumes processing of a deferred incoming re-invite.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const char * ast_channel_name(const struct ast_channel *chan)

◆ t38_automatic_reject_timer_cb()

static void t38_automatic_reject_timer_cb ( pj_timer_heap_t *  timer_heap,
struct pj_timer_entry *  entry 
)
static

Timer entry callback which queues a task to reject a T.38 re-invite and resume handling it.

Definition at line 221 of file res_pjsip_t38.c.

References ao2_ref, ast_sip_push_task(), ast_sip_session::serializer, session, and t38_automatic_reject().

Referenced by t38_state_get_or_alloc().

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 }
static int t38_automatic_reject(void *obj)
Task function which rejects a T.38 re-invite and resumes handling it.
A structure describing a SIP session.
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_taskprocessor * serializer
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:5138
Definition: search.h:40

◆ t38_change_state()

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 
)
static

Helper function for changing the T.38 state.

Definition at line 129 of file res_pjsip_t38.c.

References ao2_ref, ast_assert, ast_channel_name(), ast_channel_set_unbridged(), AST_CONTROL_T38_PARAMETERS, ast_debug, ast_log, ast_queue_control_data(), ast_sip_get_pjsip_endpoint(), AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_TERMINATED, ast_udptl_get_far_max_ifp(), ast_udptl_set_tag(), ast_sip_session::channel, LOG_WARNING, ast_control_t38_parameters::max_ifp, ast_control_t38_parameters::request_response, T38_AUTOMATIC_REJECTION_SECONDS, T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_MAX_ENUM, T38_PEER_REINVITE, T38_REJECTED, ast_sip_session::t38state, t38_state::their_parms, t38_state::timer, and ast_sip_session_media::udptl.

Referenced by defer_incoming_sdp_stream(), negotiate_incoming_sdp_stream(), t38_automatic_reject(), t38_interpret_parameters(), and t38_reinvite_response_cb().

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 }
enum ast_sip_session_t38state t38state
#define T38_ENABLED
Definition: chan_ooh323.c:102
struct ast_udptl * udptl
UDPTL instance itself.
#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
enum ast_control_t38 request_response
#define ast_assert(a)
Definition: utils.h:710
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_channel * channel
ast_sip_session_t38state
T.38 states for a session.
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
retrieves far max ifp
Definition: udptl.c:1016
#define T38_DISABLED
Definition: chan_ooh323.c:101
struct ast_control_t38_parameters their_parms
Their T.38 parameters.
Definition: res_pjsip_t38.c:65
pj_timer_entry timer
Timer entry for automatically rejecting an inbound re-invite.
Definition: res_pjsip_t38.c:67
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
const char * ast_channel_name(const struct ast_channel *chan)
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
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
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...

◆ t38_consume()

static int t38_consume ( void *  data,
enum ast_frame_type  type 
)
static

Definition at line 599 of file res_pjsip_t38.c.

References AST_FRAME_CONTROL.

Referenced by t38_attach_framehook().

600 {
601  return (type == AST_FRAME_CONTROL) ? 1 : 0;
602 }
static const char type[]
Definition: chan_ooh323.c:109

◆ t38_create_media_state()

static struct ast_sip_session_media_state* t38_create_media_state ( struct ast_sip_session session)
static

Helper function which creates a media state for strictly T.38.

Definition at line 367 of file res_pjsip_t38.c.

References ao2_ref, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_t38, AST_MEDIA_TYPE_IMAGE, ast_sip_session_media_state_add(), ast_sip_session_media_state_alloc(), ast_sip_session_media_state_free(), ast_stream_alloc(), ast_stream_free(), ast_stream_set_formats(), ast_stream_set_state(), AST_STREAM_STATE_SENDRECV, ast_stream_topology_alloc(), ast_stream_topology_set_stream(), t38_state::media_state, NULL, t38_initialize_session(), and ast_sip_session_media_state::topology.

Referenced by t38_interpret_parameters().

368 {
369  struct ast_sip_session_media_state *media_state;
370  struct ast_stream *stream;
371  struct ast_format_cap *caps;
372  struct ast_sip_session_media *session_media;
373 
374  media_state = ast_sip_session_media_state_alloc();
375  if (!media_state) {
376  return NULL;
377  }
378 
379  media_state->topology = ast_stream_topology_alloc();
380  if (!media_state->topology) {
382  return NULL;
383  }
384 
385  stream = ast_stream_alloc("t38", AST_MEDIA_TYPE_IMAGE);
386  if (!stream) {
388  return NULL;
389  }
390 
392  if (ast_stream_topology_set_stream(media_state->topology, 0, stream)) {
393  ast_stream_free(stream);
395  return NULL;
396  }
397 
399  if (!caps) {
401  return NULL;
402  }
403 
404  ast_stream_set_formats(stream, caps);
405  /* stream holds a reference to cap, release the local reference
406  * now so we don't have to deal with it in the error condition. */
407  ao2_ref(caps, -1);
408  if (ast_format_cap_append(caps, ast_format_t38, 0)) {
410  return NULL;
411  }
412 
413  session_media = ast_sip_session_media_state_add(session, media_state, AST_MEDIA_TYPE_IMAGE, 0);
414  if (!session_media) {
416  return NULL;
417  }
418 
419  if (t38_initialize_session(session, session_media)) {
421  return NULL;
422  }
423 
424  return media_state;
425 }
struct ast_sip_session_media_state * ast_sip_session_media_state_alloc(void)
Allocate a session media state structure.
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.
Structure which contains media state information (streams, sessions)
#define NULL
Definition: resample.c:96
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
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
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 ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Set when the stream is sending and receiving media.
Definition: stream.h:82
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
A structure containing SIP session media information.
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
Definition: stream.c:292
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
Definition: stream.c:233
struct ast_stream_topology * topology
The media stream topology.
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.
struct ast_format * ast_format_t38
Built-in cached T.38 format.
Definition: format_cache.c:241

◆ t38_framehook()

static struct ast_frame* t38_framehook ( struct ast_channel chan,
struct ast_frame f,
enum ast_framehook_event  event,
void *  data 
)
static

Frame hook callback for T.38 related stuff.

Definition at line 537 of file res_pjsip_t38.c.

References ao2_ref, ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FRAME_CONTROL, AST_FRAMEHOOK_EVENT_WRITE, ast_queue_control_data(), ast_sip_push_task(), AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_frame::data, ast_sip_t38_configuration::enabled, ast_sip_session::endpoint, ast_frame::frametype, ast_frame_subclass::integer, ast_sip_endpoint::media, ast_frame::ptr, ast_control_t38_parameters::request_response, ast_sip_session::serializer, ast_sip_channel_pvt::session, ast_frame::subclass, ast_sip_endpoint_media_configuration::t38, t38_interpret_parameters(), and t38_parameters_task_data_alloc().

Referenced by t38_attach_framehook().

539 {
541 
543  return f;
544  }
545 
546  if (f->frametype == AST_FRAME_CONTROL
548  if (channel->session->endpoint->media.t38.enabled) {
550 
551  task_data = t38_parameters_task_data_alloc(channel->session, f);
552  if (task_data
553  && ast_sip_push_task(channel->session->serializer,
554  t38_interpret_parameters, task_data)) {
555  ao2_ref(task_data, -1);
556  }
557  } else {
558  static const struct ast_control_t38_parameters rsp_refused = {
560  };
561  static const struct ast_control_t38_parameters rsp_terminated = {
563  };
564  const struct ast_control_t38_parameters *parameters = f->data.ptr;
565 
566  switch (parameters->request_response) {
568  ast_debug(2, "T.38 support not enabled on %s, refusing T.38 negotiation\n",
569  ast_channel_name(chan));
571  &rsp_refused, sizeof(rsp_refused));
572  break;
574  ast_debug(2, "T.38 support not enabled on %s, 'terminating' T.38 session\n",
575  ast_channel_name(chan));
577  &rsp_terminated, sizeof(rsp_terminated));
578  break;
579  default:
580  break;
581  }
582  }
583  }
584 
585  return f;
586 }
struct ast_sip_endpoint * endpoint
void * ast_channel_tech_pvt(const struct ast_channel *chan)
union ast_frame::@257 data
enum ast_control_t38 request_response
A structure which contains a channel implementation and session.
Definition: astman.c:222
struct ast_sip_session * session
Pointer to session.
Definition: muted.c:95
struct ast_frame_subclass subclass
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_taskprocessor * serializer
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:5138
userdata associated with baseline taskprocessor test
struct ast_sip_t38_configuration t38
Definition: res_pjsip.h:768
Structure for T.38 parameters task data.
Definition: res_pjsip_t38.c:88
const char * ast_channel_name(const struct ast_channel *chan)
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
enum ast_frame_type frametype
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.
static int t38_interpret_parameters(void *obj)
Task for reacting to T.38 control frame.

◆ t38_get_rate()

static unsigned int t38_get_rate ( enum ast_control_t38_rate  rate)
static

Get Max T.38 Transmission rate from T38 capabilities.

Definition at line 673 of file res_pjsip_t38.c.

References AST_T38_RATE_12000, AST_T38_RATE_14400, AST_T38_RATE_2400, AST_T38_RATE_4800, AST_T38_RATE_7200, and AST_T38_RATE_9600.

Referenced by create_outgoing_sdp_stream().

674 {
675  switch (rate) {
676  case AST_T38_RATE_2400:
677  return 2400;
678  case AST_T38_RATE_4800:
679  return 4800;
680  case AST_T38_RATE_7200:
681  return 7200;
682  case AST_T38_RATE_9600:
683  return 9600;
684  case AST_T38_RATE_12000:
685  return 12000;
686  case AST_T38_RATE_14400:
687  return 14400;
688  default:
689  return 0;
690  }
691 }
enum ast_control_t38_rate rate

◆ t38_incoming_invite_request()

static int t38_incoming_invite_request ( struct ast_sip_session session,
struct pjsip_rx_data *  rdata 
)
static

Function called when an INVITE arrives.

Definition at line 660 of file res_pjsip_t38.c.

References t38_attach_framehook().

661 {
662  t38_attach_framehook(session);
663  return 0;
664 }
static void t38_attach_framehook(struct ast_sip_session *session)
Function called to attach T.38 framehook to channel when appropriate.

◆ t38_initialize_session()

static int t38_initialize_session ( struct ast_sip_session session,
struct ast_sip_session_media session_media 
)
static

Initializes UDPTL support on a session, only done when actually needed.

Definition at line 256 of file res_pjsip_t38.c.

References ast_channel_name(), ast_debug, ast_udptl_new_with_bindaddr(), ast_udptl_set_error_correction_scheme(), ast_udptl_set_far_max_datagram(), ast_udptl_setnat(), ast_sip_session::channel, ast_sip_session::endpoint, ast_sip_t38_configuration::error_correction, ast_sip_t38_configuration::maxdatagram, ast_sip_endpoint::media, ast_sip_t38_configuration::nat, NULL, ast_sip_endpoint_media_configuration::t38, and ast_sip_session_media::udptl.

Referenced by create_outgoing_sdp_stream(), defer_incoming_sdp_stream(), and t38_create_media_state().

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 }
unsigned int maxdatagram
Definition: res_pjsip.h:746
struct ast_sip_endpoint * endpoint
char * address
Definition: f2c.h:59
struct ast_udptl * udptl
UDPTL instance itself.
enum ast_t38_ec_modes error_correction
Definition: res_pjsip.h:744
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 NULL
Definition: resample.c:96
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
struct ast_channel * channel
struct ast_sip_t38_configuration t38
Definition: res_pjsip.h:768
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
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
void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
Definition: udptl.c:745

◆ t38_interpret_parameters()

static int t38_interpret_parameters ( void *  obj)
static

Task for reacting to T.38 control frame.

Definition at line 428 of file res_pjsip_t38.c.

References ao2_cleanup, ast_channel_name(), AST_CONTROL_T38_PARAMETERS, ast_log, AST_MEDIA_TYPE_IMAGE, ast_queue_control_data(), ast_sip_session_refresh(), AST_SIP_SESSION_REFRESH_METHOD_INVITE, ast_sip_session_resume_reinvite(), AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_REQUEST_PARMS, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_udptl_get_far_max_ifp(), ast_udptl_set_local_max_ifp(), ast_sip_session_media_state::default_session, ast_control_t38_parameters::fill_bit_removal, LOG_ERROR, ast_control_t38_parameters::max_ifp, t38_state::media_state, MIN, NULL, t38_state::our_parms, RAII_VAR, ast_control_t38_parameters::rate_management, ast_control_t38_parameters::request_response, t38_change_state(), t38_create_media_state(), T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_REINVITE, t38_reinvite_response_cb(), t38_reinvite_sdp_cb(), T38_REJECTED, t38_state_get_or_alloc(), t38_state::their_parms, ast_control_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_mmr, ast_sip_session_media::udptl, and ast_control_t38_parameters::version.

Referenced by t38_framehook().

429 {
430  RAII_VAR(struct t38_parameters_task_data *, data, obj, ao2_cleanup);
431  const struct ast_control_t38_parameters *parameters = data->frame->data.ptr;
432  struct t38_state *state = t38_state_get_or_alloc(data->session);
433  struct ast_sip_session_media *session_media = NULL;
434 
435  if (!state) {
436  return 0;
437  }
438 
439  switch (parameters->request_response) {
440  case AST_T38_NEGOTIATED:
441  case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */
442  /* Negotiation can not take place without a valid max_ifp value. */
443  if (!parameters->max_ifp) {
444  if (data->session->t38state == T38_PEER_REINVITE) {
445  t38_change_state(data->session, NULL, state, T38_REJECTED);
446  ast_sip_session_resume_reinvite(data->session);
447  } else if (data->session->t38state == T38_ENABLED) {
448  t38_change_state(data->session, NULL, state, T38_DISABLED);
449  ast_sip_session_refresh(data->session, NULL, NULL, NULL,
451  state->media_state = NULL;
452  }
453  break;
454  } else if (data->session->t38state == T38_PEER_REINVITE) {
455  state->our_parms = *parameters;
456  /* modify our parameters to conform to the peer's parameters,
457  * based on the rules in the ITU T.38 recommendation
458  */
459  if (!state->their_parms.fill_bit_removal) {
460  state->our_parms.fill_bit_removal = 0;
461  }
462  if (!state->their_parms.transcoding_mmr) {
463  state->our_parms.transcoding_mmr = 0;
464  }
465  if (!state->their_parms.transcoding_jbig) {
466  state->our_parms.transcoding_jbig = 0;
467  }
468  state->our_parms.version = MIN(state->our_parms.version, state->their_parms.version);
470  session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
471  if (!session_media) {
472  ast_log(LOG_ERROR, "Failed to negotiate parameters for reinvite on channel '%s' (No pending session media).\n",
473  data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
474  break;
475  }
476  ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
477  t38_change_state(data->session, session_media, state, T38_ENABLED);
478  ast_sip_session_resume_reinvite(data->session);
479  } else if ((data->session->t38state != T38_ENABLED) ||
480  ((data->session->t38state == T38_ENABLED) &&
481  (parameters->request_response == AST_T38_REQUEST_NEGOTIATE))) {
482  struct ast_sip_session_media_state *media_state;
483 
484  media_state = t38_create_media_state(data->session);
485  if (!media_state) {
486  break;
487  }
488  state->our_parms = *parameters;
489  session_media = media_state->default_session[AST_MEDIA_TYPE_IMAGE];
490  if (!session_media) {
491  ast_log(LOG_ERROR, "Failed to negotiate parameters on channel '%s' (No default session media).\n",
492  data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
493  break;
494  }
495  ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
496  t38_change_state(data->session, NULL, state, T38_LOCAL_REINVITE);
498  AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, media_state);
499  }
500  break;
501  case AST_T38_TERMINATED:
502  case AST_T38_REFUSED:
503  case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */
504  if (data->session->t38state == T38_PEER_REINVITE) {
505  t38_change_state(data->session, NULL, state, T38_REJECTED);
506  ast_sip_session_resume_reinvite(data->session);
507  } else if (data->session->t38state == T38_ENABLED) {
508  t38_change_state(data->session, NULL, state, T38_DISABLED);
510  state->media_state = NULL;
511  }
512  break;
513  case AST_T38_REQUEST_PARMS: { /* Application wants remote's parameters re-sent */
514  struct ast_control_t38_parameters parameters = state->their_parms;
515 
516  if (data->session->t38state == T38_PEER_REINVITE) {
517  session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
518  if (!session_media) {
519  ast_log(LOG_ERROR, "Failed to request parameters for reinvite on channel '%s' (No pending session media).\n",
520  data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
521  break;
522  }
523  parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
525  ast_queue_control_data(data->session->channel, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
526  }
527  break;
528  }
529  default:
530  break;
531  }
532 
533  return 0;
534 }
#define T38_ENABLED
Definition: chan_ooh323.c:102
Structure which contains media state information (streams, sessions)
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
Definition: udptl.c:973
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 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.
struct ast_udptl * udptl
UDPTL instance itself.
T.38 state information.
Definition: res_pjsip_t38.c:59
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
enum ast_control_t38 request_response
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.
#define NULL
Definition: resample.c:96
#define MIN(a, b)
Definition: utils.h:226
#define ast_log
Definition: astobj2.c:42
#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:911
struct ast_sip_session_media_state * media_state
Definition: res_pjsip_t38.c:69
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.
void ast_sip_session_resume_reinvite(struct ast_sip_session *session)
Resumes processing of a deferred incoming re-invite.
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
retrieves far max ifp
Definition: udptl.c:1016
#define LOG_ERROR
Definition: logger.h:285
#define T38_DISABLED
Definition: chan_ooh323.c:101
struct ast_control_t38_parameters our_parms
Our T.38 parameters.
Definition: res_pjsip_t38.c:63
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.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Structure for T.38 parameters task data.
Definition: res_pjsip_t38.c:88
const char * ast_channel_name(const struct ast_channel *chan)
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

◆ t38_interpret_sdp()

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 
)
static

Parse a T.38 image stream and store the attribute information.

Definition at line 702 of file res_pjsip_t38.c.

References AST_T38_RATE_12000, AST_T38_RATE_14400, AST_T38_RATE_2400, AST_T38_RATE_4800, AST_T38_RATE_7200, AST_T38_RATE_9600, AST_T38_RATE_MANAGEMENT_LOCAL_TCF, AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF, ast_udptl_set_error_correction_scheme(), ast_udptl_set_far_max_datagram(), ast_sip_session::endpoint, ast_sip_t38_configuration::error_correction, ast_control_t38_parameters::fill_bit_removal, ast_sip_t38_configuration::maxdatagram, ast_sip_endpoint::media, ast_control_t38_parameters::rate, ast_control_t38_parameters::rate_management, ast_sip_endpoint_media_configuration::t38, T38_LOCAL_REINVITE, ast_sip_session::t38state, t38_state::their_parms, ast_control_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_mmr, ast_sip_session_media::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and ast_control_t38_parameters::version.

Referenced by apply_negotiated_sdp_stream(), and defer_incoming_sdp_stream().

704 {
705  unsigned int attr_i;
706 
707  for (attr_i = 0; attr_i < stream->attr_count; attr_i++) {
708  pjmedia_sdp_attr *attr = stream->attr[attr_i];
709 
710  if (!pj_stricmp2(&attr->name, "t38faxmaxbuffer")) {
711  /* This is purposely left empty, it is unused */
712  } else if (!pj_stricmp2(&attr->name, "t38maxbitrate") || !pj_stricmp2(&attr->name, "t38faxmaxrate")) {
713  switch (pj_strtoul(&attr->value)) {
714  case 14400:
716  break;
717  case 12000:
719  break;
720  case 9600:
722  break;
723  case 7200:
725  break;
726  case 4800:
728  break;
729  case 2400:
731  break;
732  }
733  } else if (!pj_stricmp2(&attr->name, "t38faxversion")) {
734  state->their_parms.version = pj_strtoul(&attr->value);
735  } else if (!pj_stricmp2(&attr->name, "t38faxmaxdatagram") || !pj_stricmp2(&attr->name, "t38maxdatagram")) {
736  if (!session->endpoint->media.t38.maxdatagram) {
737  ast_udptl_set_far_max_datagram(session_media->udptl, pj_strtoul(&attr->value));
738  }
739  } else if (!pj_stricmp2(&attr->name, "t38faxfillbitremoval")) {
740  state->their_parms.fill_bit_removal = 1;
741  } else if (!pj_stricmp2(&attr->name, "t38faxtranscodingmmr")) {
742  state->their_parms.transcoding_mmr = 1;
743  } else if (!pj_stricmp2(&attr->name, "t38faxtranscodingjbig")) {
744  state->their_parms.transcoding_jbig = 1;
745  } else if (!pj_stricmp2(&attr->name, "t38faxratemanagement")) {
746  if (!pj_stricmp2(&attr->value, "localTCF")) {
748  } else if (!pj_stricmp2(&attr->value, "transferredTCF")) {
750  }
751  } else if (!pj_stricmp2(&attr->name, "t38faxudpec")) {
752  if (session->t38state == T38_LOCAL_REINVITE) {
754  if (!pj_stricmp2(&attr->value, "t38UDPFEC")) {
756  } else if (!pj_stricmp2(&attr->value, "t38UDPRedundancy")) {
758  } else {
760  }
762  if (!pj_stricmp2(&attr->value, "t38UDPRedundancy")) {
764  } else {
766  }
767  } else {
769  }
770  } else {
771  if (!pj_stricmp2(&attr->value, "t38UDPRedundancy")) {
773  } else if (!pj_stricmp2(&attr->value, "t38UDPFEC")) {
775  } else {
777  }
778  }
779  }
780 
781  }
782 }
unsigned int maxdatagram
Definition: res_pjsip.h:746
enum ast_sip_session_t38state t38state
struct ast_sip_endpoint * endpoint
struct ast_udptl * udptl
UDPTL instance itself.
enum ast_t38_ec_modes error_correction
Definition: res_pjsip.h:744
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
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
enum ast_control_t38_rate rate
struct ast_sip_t38_configuration t38
Definition: res_pjsip.h:768
struct ast_control_t38_parameters their_parms
Their T.38 parameters.
Definition: res_pjsip_t38.c:65
void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
Definition: udptl.c:945
enum ast_control_t38_rate_management rate_management

◆ t38_masq()

static void t38_masq ( void *  data,
int  framehook_id,
struct ast_channel old_chan,
struct ast_channel new_chan 
)
static

Definition at line 588 of file res_pjsip_t38.c.

References ast_channel_tech(), and ast_framehook_detach().

Referenced by t38_attach_framehook().

590 {
591  if (ast_channel_tech(old_chan) == ast_channel_tech(new_chan)) {
592  return;
593  }
594 
595  /* This framehook is only applicable to PJSIP channels */
596  ast_framehook_detach(new_chan, framehook_id);
597 }
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)

◆ t38_outgoing_invite_request()

static void t38_outgoing_invite_request ( struct ast_sip_session session,
struct pjsip_tx_data *  tdata 
)
static

Function called when an INVITE is sent.

Definition at line 667 of file res_pjsip_t38.c.

References t38_attach_framehook().

668 {
669  t38_attach_framehook(session);
670 }
static void t38_attach_framehook(struct ast_sip_session *session)
Function called to attach T.38 framehook to channel when appropriate.

◆ t38_parameters_task_data_alloc()

static struct t38_parameters_task_data* t38_parameters_task_data_alloc ( struct ast_sip_session session,
struct ast_frame frame 
)
static

Allocator for T.38 data.

Definition at line 108 of file res_pjsip_t38.c.

References ao2_alloc, ao2_ref, ast_frdup, t38_parameters_task_data::frame, NULL, session, t38_parameters_task_data::session, and t38_parameters_task_data_destroy().

Referenced by t38_framehook().

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 }
#define ast_frdup(fr)
Copies a frame.
#define NULL
Definition: resample.c:96
struct ast_frame * frame
T.38 control frame.
Definition: res_pjsip_t38.c:92
struct ast_sip_session * session
Session itself.
Definition: res_pjsip_t38.c:90
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
Structure for T.38 parameters task data.
Definition: res_pjsip_t38.c:88
static void t38_parameters_task_data_destroy(void *obj)
Destructor for T.38 data.
Definition: res_pjsip_t38.c:96

◆ t38_parameters_task_data_destroy()

static void t38_parameters_task_data_destroy ( void *  obj)
static

Destructor for T.38 data.

Definition at line 96 of file res_pjsip_t38.c.

References ao2_cleanup, ast_frfree, t38_parameters_task_data::frame, and t38_parameters_task_data::session.

Referenced by t38_parameters_task_data_alloc().

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 }
struct ast_frame * frame
T.38 control frame.
Definition: res_pjsip_t38.c:92
struct ast_sip_session * session
Session itself.
Definition: res_pjsip_t38.c:90
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Structure for T.38 parameters task data.
Definition: res_pjsip_t38.c:88
#define ast_frfree(fr)

◆ t38_reinvite_response_cb()

static int t38_reinvite_response_cb ( struct ast_sip_session session,
pjsip_rx_data *  rdata 
)
static

Callback for when a response is received for a T.38 re-invite.

Definition at line 290 of file res_pjsip_t38.c.

References ast_sip_session::active_media_state, ast_channel_name(), ast_debug, ast_log, AST_MEDIA_TYPE_IMAGE, ast_sip_session_media_state_free(), ast_sip_session_media_state_reset(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sip_session::channel, ast_sip_session_media_state::default_session, ast_sip_session_media::handler, LOG_WARNING, t38_state::media_state, NULL, ast_sip_session::pending_media_state, t38_state::state, ast_sip_session_sdp_handler::stream_stop, t38_change_state(), T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_REJECTED, t38_state_get_or_alloc(), ast_sip_session::t38state, and ast_sip_session_media::udptl.

Referenced by t38_interpret_parameters().

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 
324  /*
325  * If there is a session_media object, but no udptl object available
326  * then it's assumed the stream was declined.
327  */
328  if (session_media && !session_media->udptl) {
329  session_media = NULL;
330  }
331 
332  if (!session_media) {
333  ast_log(LOG_WARNING, "Received %d response to T.38 re-invite on '%s' but no active session media\n",
334  status.code, session->channel ? ast_channel_name(session->channel) : "unknown channel");
335  } else {
336  t38_change_state(session, session_media, state, T38_ENABLED);
337 
338  /* Stop all the streams in the stored away active state, they'll go back to being active once
339  * we reinvite back.
340  */
341  for (index = 0; index < AST_VECTOR_SIZE(&state->media_state->sessions); ++index) {
342  struct ast_sip_session_media *session_media = AST_VECTOR_GET(&state->media_state->sessions, index);
343 
344  if (session_media && session_media->handler && session_media->handler->stream_stop) {
345  session_media->handler->stream_stop(session_media);
346  }
347  }
348 
349  return 0;
350  }
351  } else {
352  session_media = session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
353  }
354 
355  /* If no session_media then response contained a declined stream, so disable */
356  t38_change_state(session, NULL, state, session_media ? T38_REJECTED : T38_DISABLED);
357 
358  /* Abort this attempt at switching to T.38 by resetting the pending state and freeing our stored away active state */
360  state->media_state = NULL;
362 
363  return 0;
364 }
enum sip_cc_notify_state state
Definition: chan_sip.c:960
enum ast_sip_session_t38state t38state
#define T38_ENABLED
Definition: chan_ooh323.c:102
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.
struct ast_sip_session_media_state * pending_media_state
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.
struct ast_udptl * udptl
UDPTL instance itself.
#define LOG_WARNING
Definition: logger.h:274
T.38 state information.
Definition: res_pjsip_t38.c:59
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
#define NULL
Definition: resample.c:96
struct ast_sip_session_media_state * active_media_state
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
struct ast_sip_session_media_state * media_state
Definition: res_pjsip_t38.c:69
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.
struct ast_channel * channel
#define T38_DISABLED
Definition: chan_ooh323.c:101
A structure containing SIP session media information.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
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_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state)
Reset a media state to a clean state.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
void(* stream_stop)(struct ast_sip_session_media *session_media)
Stop a session_media created by this handler but do not destroy resources.
jack_status_t status
Definition: app_jack.c:146

◆ t38_reinvite_sdp_cb()

static int t38_reinvite_sdp_cb ( struct ast_sip_session session,
pjmedia_sdp_session *  sdp 
)
static

Callback for when T.38 reinvite SDP is created.

Definition at line 275 of file res_pjsip_t38.c.

References ast_sip_session::active_media_state, ast_sip_session_media_state_clone(), t38_state::media_state, t38_state::state, and t38_state_get_or_alloc().

Referenced by t38_interpret_parameters().

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 }
enum sip_cc_notify_state state
Definition: chan_sip.c:960
T.38 state information.
Definition: res_pjsip_t38.c:59
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.
struct ast_sip_session_media_state * active_media_state
struct ast_sip_session_media_state * media_state
Definition: res_pjsip_t38.c:69
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.

◆ t38_state_destroy()

static void t38_state_destroy ( void *  obj)
static

Destructor for T.38 state information.

Definition at line 73 of file res_pjsip_t38.c.

References ast_free, ast_sip_session_media_state_free(), and t38_state::media_state.

74 {
75  struct t38_state *state = obj;
76 
78  ast_free(obj);
79 }
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.
T.38 state information.
Definition: res_pjsip_t38.c:59
struct ast_sip_session_media_state * media_state
Definition: res_pjsip_t38.c:69
#define ast_free(a)
Definition: astmm.h:182

◆ t38_state_get_or_alloc()

static struct t38_state* t38_state_get_or_alloc ( struct ast_sip_session session)
static

Helper function which retrieves or allocates a T.38 state information datastore.

Definition at line 231 of file res_pjsip_t38.c.

References ao2_cleanup, ast_calloc, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_datastore(), NULL, RAII_VAR, t38_state::state, t38_automatic_reject_timer_cb(), and t38_state::timer.

Referenced by apply_negotiated_sdp_stream(), create_outgoing_sdp_stream(), defer_incoming_sdp_stream(), negotiate_incoming_sdp_stream(), t38_interpret_parameters(), t38_reinvite_response_cb(), and t38_reinvite_sdp_cb().

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 }
enum sip_cc_notify_state state
Definition: chan_sip.c:960
T.38 state information.
Definition: res_pjsip_t38.c:59
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
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.
#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:911
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
pj_timer_entry timer
Timer entry for automatically rejecting an inbound re-invite.
Definition: res_pjsip_t38.c:67
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static const struct ast_datastore_info t38_datastore
Datastore for attaching T.38 state information.
Definition: res_pjsip_t38.c:82
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.

◆ unload_module()

static int unload_module ( void  )
static

Unloads the SIP T.38 module from Asterisk.

Definition at line 1084 of file res_pjsip_t38.c.

References ast_sip_session_unregister_sdp_handler(), and ast_sip_session_unregister_supplement().

Referenced by load_module().

1085 {
1088 
1089  return 0;
1090 }
static struct ast_sip_session_supplement t38_supplement
Supplement for adding framehook to session channel.
static struct ast_sip_session_sdp_handler image_sdp_handler
SDP handler for &#39;image&#39; media stream.
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
void ast_sip_session_unregister_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Unregister an SDP handler.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP T.38 UDPTL Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "res_pjsip,res_pjsip_session,udptl", }
static

Definition at line 1130 of file res_pjsip_t38.c.

◆ address

struct ast_sockaddr address
static

Address for UDPTL.

Definition at line 56 of file res_pjsip_t38.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1130 of file res_pjsip_t38.c.

◆ image_sdp_handler

struct ast_sip_session_sdp_handler image_sdp_handler
static

SDP handler for 'image' media stream.

Definition at line 1073 of file res_pjsip_t38.c.

◆ t38_datastore

const struct ast_datastore_info t38_datastore
static
Initial value:
= {
.type = "t38",
.destroy = t38_state_destroy,
}
static void t38_state_destroy(void *obj)
Destructor for T.38 state information.
Definition: res_pjsip_t38.c:73

Datastore for attaching T.38 state information.

Definition at line 82 of file res_pjsip_t38.c.

◆ t38_framehook_datastore

const struct ast_datastore_info t38_framehook_datastore
static
Initial value:
= {
.type = "T38 framehook",
}

Definition at line 604 of file res_pjsip_t38.c.

◆ t38_supplement

struct ast_sip_session_supplement t38_supplement
static

Supplement for adding framehook to session channel.

Definition at line 694 of file res_pjsip_t38.c.