Asterisk - The Open Source Telephony Project GIT-master-f36a736
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"
Include dependency graph for res_pjsip_t38.c:

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.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1171 of file res_pjsip_t38.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1171 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 1039 of file res_pjsip_t38.c.

1042{
1043 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
1044 pjmedia_sdp_media *remote_stream = remote->media[index];
1045 char host[NI_MAXHOST];
1046 struct t38_state *state;
1047
1048 if (!session_media->udptl) {
1049 ast_debug(3, "Not applying negotiated SDP stream: no UDTPL session\n");
1050 return 0;
1051 }
1052
1054 return -1;
1055 }
1056
1057 ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
1058
1059 /* Ensure that the address provided is valid */
1060 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
1061 /* The provided host was actually invalid so we error out this negotiation */
1062 ast_debug(3, "Not applying negotiated SDP stream: failed to resolve remote stream host\n");
1063 return -1;
1064 }
1065
1066 ast_sockaddr_set_port(addrs, remote_stream->desc.port);
1067 ast_udptl_set_peer(session_media->udptl, addrs);
1068
1069 t38_interpret_sdp(state, session, session_media, remote_stream);
1070
1072 ast_sip_session_media_add_read_callback(session, session_media, ast_udptl_fd(session_media->udptl),
1074
1075 return 0;
1076}
static struct ast_mansession session
#define ast_free(a)
Definition: astmm.h:180
enum cc_state state
Definition: ccss.c:393
#define ast_debug(level,...)
Log a DEBUG message.
@ AST_AF_UNSPEC
Definition: netsock2.h:54
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_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
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:2201
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_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 media_session_udptl_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
static struct ast_frame * media_session_udptl_read_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
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.
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 NULL
Definition: resample.c:96
struct ast_udptl * udptl
UDPTL instance itself.
Socket address structure.
Definition: netsock2.h:97
T.38 state information.
Definition: res_pjsip_t38.c:59
int ast_udptl_fd(const struct ast_udptl *udptl)
Definition: udptl.c:728
void ast_udptl_set_peer(struct ast_udptl *udptl, const struct ast_sockaddr *them)
Definition: udptl.c:1128
#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:941

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(), media_session_udptl_read_callback(), media_session_udptl_write_callback(), NULL, PARSE_PORT_FORBID, RAII_VAR, session, state, t38_interpret_sdp(), t38_state_get_or_alloc(), and ast_sip_session_media::udptl.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1171 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 1079 of file res_pjsip_t38.c.

1080{
1082 char host[NI_MAXHOST];
1083 struct ast_sockaddr our_sdp_addr = { { 0, } };
1084
1085 /* If the stream has been rejected there will be no connection line */
1086 if (!stream->conn || !transport_state) {
1087 return;
1088 }
1089
1090 ast_copy_pj_str(host, &stream->conn->addr, sizeof(host));
1091 ast_sockaddr_parse(&our_sdp_addr, host, PARSE_PORT_FORBID);
1092
1093 /* Reversed check here. We don't check the remote endpoint being
1094 * in our local net, but whether our outgoing session IP is
1095 * local. If it is not, we won't do rewriting. No localnet
1096 * configured? Always rewrite. */
1097 if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) {
1098 return;
1099 }
1100 ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
1101 pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
1102}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
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 char * ast_sockaddr_stringify_addr_remote(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition: netsock2.h:313
#define ast_sip_transport_is_nonlocal(transport_state, addr)
Definition: res_pjsip.h:209
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
Structure for SIP transport information.
Definition: res_pjsip.h:116

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_addr_remote(), ast_sorcery_object_get_id(), PARSE_PORT_FORBID, and RAII_VAR.

◆ 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 904 of file res_pjsip_t38.c.

906{
907 pj_pool_t *pool = session->inv_session->pool_prov;
908 static const pj_str_t STR_IN = { "IN", 2 };
909 static const pj_str_t STR_IP4 = { "IP4", 3};
910 static const pj_str_t STR_IP6 = { "IP6", 3};
911 static const pj_str_t STR_UDPTL = { "udptl", 5 };
912 static const pj_str_t STR_T38 = { "t38", 3 };
913 static const pj_str_t STR_TRANSFERREDTCF = { "transferredTCF", 14 };
914 static const pj_str_t STR_LOCALTCF = { "localTCF", 8 };
915 static const pj_str_t STR_T38UDPFEC = { "t38UDPFEC", 9 };
916 static const pj_str_t STR_T38UDPREDUNDANCY = { "t38UDPRedundancy", 16 };
917 struct t38_state *state;
918 pjmedia_sdp_media *media;
919 const char *hostip = NULL;
920 struct ast_sockaddr addr;
921 char tmp[512];
922 pj_str_t stmp;
923
924 if (!session->endpoint->media.t38.enabled) {
925 ast_debug(3, "Not creating outgoing SDP stream: T.38 not enabled\n");
926 return 1;
927 } else if ((session->t38state != T38_LOCAL_REINVITE) && (session->t38state != T38_PEER_REINVITE) &&
928 (session->t38state != T38_ENABLED)) {
929 ast_debug(3, "Not creating outgoing SDP stream: T.38 not enabled\n");
930 return 1;
931 } else if (!(state = t38_state_get_or_alloc(session))) {
932 return -1;
933 } else if (t38_initialize_session(session, session_media)) {
934 ast_debug(3, "Not creating outgoing SDP stream: Failed to initialize T.38 session\n");
935 return -1;
936 }
937
938 if (!(media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media))) ||
939 !(media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn)))) {
940 return -1;
941 }
942
943 pj_strdup2(pool, &media->desc.media, ast_codec_media_type2str(session_media->type));
944 media->desc.transport = STR_UDPTL;
945
946 if (ast_strlen_zero(session->endpoint->media.address)) {
947 hostip = ast_sip_get_host_ip_string(session->endpoint->media.t38.ipv6 ? pj_AF_INET6() : pj_AF_INET());
948 } else {
949 hostip = session->endpoint->media.address;
950 }
951
952 if (ast_strlen_zero(hostip)) {
953 ast_debug(3, "Not creating outgoing SDP stream: no known host IP\n");
954 return -1;
955 }
956
957 media->conn->net_type = STR_IN;
958 media->conn->addr_type = session->endpoint->media.t38.ipv6 ? STR_IP6 : STR_IP4;
959 pj_strdup2(pool, &media->conn->addr, hostip);
960 ast_udptl_get_us(session_media->udptl, &addr);
961 media->desc.port = (pj_uint16_t) ast_sockaddr_port(&addr);
962 media->desc.port_count = 1;
963 media->desc.fmt[media->desc.fmt_count++] = STR_T38;
964
965 snprintf(tmp, sizeof(tmp), "%u", state->our_parms.version);
966 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxVersion", pj_cstr(&stmp, tmp));
967
968 snprintf(tmp, sizeof(tmp), "%u", t38_get_rate(state->our_parms.rate));
969 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38MaxBitRate", pj_cstr(&stmp, tmp));
970
971 if (state->our_parms.fill_bit_removal) {
972 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxFillBitRemoval", NULL);
973 }
974
975 if (state->our_parms.transcoding_mmr) {
976 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxTranscodingMMR", NULL);
977 }
978
979 if (state->our_parms.transcoding_jbig) {
980 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxTranscodingJBIG", NULL);
981 }
982
983 switch (state->our_parms.rate_management) {
985 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxRateManagement", &STR_TRANSFERREDTCF);
986 break;
988 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxRateManagement", &STR_LOCALTCF);
989 break;
990 }
991
992 snprintf(tmp, sizeof(tmp), "%u", ast_udptl_get_local_max_datagram(session_media->udptl));
993 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxMaxDatagram", pj_cstr(&stmp, tmp));
994
995 switch (ast_udptl_get_error_correction_scheme(session_media->udptl)) {
997 break;
999 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxUdpEC", &STR_T38UDPFEC);
1000 break;
1002 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxUdpEC", &STR_T38UDPREDUNDANCY);
1003 break;
1004 }
1005
1006 sdp->media[sdp->media_count++] = media;
1007
1008 return 1;
1009}
static int tmp()
Definition: bt_open.c:389
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:348
@ AST_T38_RATE_MANAGEMENT_LOCAL_TCF
@ AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517
const char * ast_sip_get_host_ip_string(int af)
Retrieve the local host address in string form.
Definition: res_pjsip.c:2493
@ T38_PEER_REINVITE
@ T38_LOCAL_REINVITE
@ T38_ENABLED
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.
static unsigned int t38_get_rate(enum ast_control_t38_rate rate)
Get Max T.38 Transmission rate from T38 capabilities.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
enum ast_media_type type
Media type of this session media.
enum ast_t38_ec_modes ast_udptl_get_error_correction_scheme(const struct ast_udptl *udptl)
Definition: udptl.c:938
void ast_udptl_get_us(const struct ast_udptl *udptl, struct ast_sockaddr *us)
Definition: udptl.c:1138
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
retrieves local_max_datagram.
Definition: udptl.c:982
@ UDPTL_ERROR_CORRECTION_FEC
Definition: udptl.h:39
@ UDPTL_ERROR_CORRECTION_NONE
Definition: udptl.h:38
@ UDPTL_ERROR_CORRECTION_REDUNDANCY
Definition: udptl.h:40

References 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(), NULL, session, state, T38_ENABLED, t38_get_rate(), t38_initialize_session(), T38_LOCAL_REINVITE, T38_PEER_REINVITE, t38_state_get_or_alloc(), tmp(), ast_sip_session_media::type, ast_sip_session_media::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.

◆ 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 826 of file res_pjsip_t38.c.

829{
830 struct t38_state *state;
831
832 if (!session->endpoint->media.t38.enabled) {
833 ast_debug(3, "Not deferring incoming SDP stream: T.38 not enabled on %s\n", ast_channel_name(session->channel));
835 }
836
837 if (t38_initialize_session(session, session_media)) {
838 ast_debug(3, "Not deferring incoming SDP stream: Failed to initialize UDPTL on %s\n", ast_channel_name(session->channel));
840 }
841
844 }
845
846 t38_interpret_sdp(state, session, session_media, stream);
847
848 /* If they are initiating the re-invite we need to defer responding until later */
849 if (session->t38state == T38_DISABLED) {
851 ast_debug(3, "Deferring incoming SDP stream on %s for peer re-invite\n", ast_channel_name(session->channel));
853 }
854
856}
const char * ast_channel_name(const struct ast_channel *chan)
@ T38_DISABLED
@ AST_SIP_SESSION_SDP_DEFER_NEEDED
@ AST_SIP_SESSION_SDP_DEFER_NOT_HANDLED
@ AST_SIP_SESSION_SDP_DEFER_NOT_NEEDED
@ AST_SIP_SESSION_SDP_DEFER_ERROR
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.

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, session, state, t38_change_state(), T38_DISABLED, t38_initialize_session(), t38_interpret_sdp(), T38_PEER_REINVITE, and t38_state_get_or_alloc().

◆ 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 1143 of file res_pjsip_t38.c.

1144{
1145 if (ast_check_ipv6()) {
1146 ast_sockaddr_parse(&address, "::", 0);
1147 } else {
1148 ast_sockaddr_parse(&address, "0.0.0.0", 0);
1149 }
1150
1152
1154 ast_log(LOG_ERROR, "Unable to register SDP handler for image stream type\n");
1155 goto end;
1156 }
1157
1159end:
1160 unload_module();
1161
1163}
#define ast_log
Definition: astobj2.c:42
char * end
Definition: eagi_proxy.c:73
char * address
Definition: f2c.h:59
#define LOG_ERROR
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_sip_session_register_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Register an SDP handler.
#define ast_sip_session_register_supplement(supplement)
static struct ast_sip_session_sdp_handler image_sdp_handler
SDP handler for 'image' media stream.
static int unload_module(void)
Unloads the SIP T.38 module from Asterisk.
static struct ast_sip_session_supplement t38_supplement
Supplement for adding framehook to session channel.
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
Definition: utils.c:2792

References ast_check_ipv6(), ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_sip_session_register_sdp_handler(), ast_sip_session_register_supplement, ast_sockaddr_parse(), end, image_sdp_handler, LOG_ERROR, t38_supplement, and unload_module().

◆ 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 1011 of file res_pjsip_t38.c.

1012{
1013 struct ast_frame *frame;
1014
1015 if (!session_media->udptl) {
1016 return &ast_null_frame;
1017 }
1018
1019 frame = ast_udptl_read(session_media->udptl);
1020 if (!frame) {
1021 return NULL;
1022 }
1023
1024 frame->stream_num = session_media->stream_num;
1025
1026 return frame;
1027}
struct ast_frame ast_null_frame
Definition: main/frame.c:79
Data structure associated with a single frame of data.
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:760

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

Referenced by apply_negotiated_sdp_stream().

◆ 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 1029 of file res_pjsip_t38.c.

1030{
1031 if (!session_media->udptl) {
1032 return 0;
1033 }
1034
1035 return ast_udptl_write(session_media->udptl, frame);
1036}
int ast_udptl_write(struct ast_udptl *udptl, struct ast_frame *f)
Definition: udptl.c:1159

References ast_udptl_write(), and ast_sip_session_media::udptl.

Referenced by apply_negotiated_sdp_stream().

◆ 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 859 of file res_pjsip_t38.c.

862{
863 struct t38_state *state;
864 char host[NI_MAXHOST];
865 pjmedia_sdp_media *stream = sdp->media[index];
866 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
867
868 if (!session->endpoint->media.t38.enabled) {
869 ast_debug(3, "Declining; T.38 not enabled on session\n");
870 return 0;
871 }
872
874 return 0;
875 }
876
877 if ((session->t38state == T38_REJECTED) || (session->t38state == T38_DISABLED)) {
878 ast_debug(3, "Declining; T.38 state is rejected or declined\n");
880 return 0;
881 }
882
883 ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
884
885 /* Ensure that the address provided is valid */
886 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
887 /* The provided host was actually invalid so we error out this negotiation */
888 ast_debug(3, "Declining; provided host is invalid\n");
889 return 0;
890 }
891
892 /* Check the address family to make sure it matches configured */
893 if ((ast_sockaddr_is_ipv6(addrs) && !session->endpoint->media.t38.ipv6) ||
894 (ast_sockaddr_is_ipv4(addrs) && session->endpoint->media.t38.ipv6)) {
895 /* The address does not match configured */
896 ast_debug(3, "Declining, provided host does not match configured address family\n");
897 return 0;
898 }
899
900 return 1;
901}
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
@ T38_REJECTED

References AST_AF_UNSPEC, ast_copy_pj_str(), ast_debug, ast_free, ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_resolve(), NULL, PARSE_PORT_FORBID, RAII_VAR, session, state, t38_change_state(), T38_DISABLED, T38_REJECTED, and t38_state_get_or_alloc().

◆ 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 1105 of file res_pjsip_t38.c.

1106{
1107 if (session_media->udptl) {
1108 ast_udptl_destroy(session_media->udptl);
1109 }
1110 session_media->udptl = NULL;
1111}
void ast_udptl_destroy(struct ast_udptl *udptl)
Definition: udptl.c:1148

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

◆ 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 650 of file res_pjsip_t38.c.

651{
652 int framehook_id;
653 struct ast_datastore *datastore = NULL;
654 static struct ast_framehook_interface hook = {
656 .event_cb = t38_framehook,
657 .consume_cb = t38_consume,
658 .chan_fixup_cb = t38_masq,
659 .chan_breakdown_cb = t38_masq,
660 };
661
662 /* If the channel's already gone, bail */
663 if (!session->channel) {
664 return;
665 }
666
667 /* Always attach the framehook so we can quickly reject */
668
669 ast_channel_lock(session->channel);
670
671 /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
673 NULL);
674 if (datastore) {
675 ast_channel_unlock(session->channel);
676 return;
677 }
678
679 framehook_id = ast_framehook_attach(session->channel, &hook);
680 if (framehook_id < 0) {
681 ast_log(LOG_WARNING, "Could not attach T.38 Frame hook, T.38 will be unavailable on '%s'\n",
682 ast_channel_name(session->channel));
683 ast_channel_unlock(session->channel);
684 return;
685 }
686
688 if (!datastore) {
689 ast_log(LOG_ERROR, "Could not alloc T.38 Frame hook datastore, T.38 will be unavailable on '%s'\n",
690 ast_channel_name(session->channel));
691 ast_framehook_detach(session->channel, framehook_id);
692 ast_channel_unlock(session->channel);
693 return;
694 }
695
696 ast_channel_datastore_add(session->channel, datastore);
697 ast_channel_unlock(session->channel);
698}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2404
#define ast_channel_lock(chan)
Definition: channel.h:2968
#define ast_channel_unlock(chan)
Definition: channel.h:2969
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:2418
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
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
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
#define LOG_WARNING
static const struct ast_datastore_info t38_framehook_datastore
static int t38_consume(void *data, enum ast_frame_type type)
static void t38_masq(void *data, int framehook_id, struct ast_channel *old_chan, struct ast_channel *new_chan)
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.
Structure for a data store object.
Definition: datastore.h:64

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, LOG_ERROR, LOG_WARNING, NULL, session, t38_consume(), t38_framehook(), t38_framehook_datastore, t38_masq(), and ast_framehook_interface::version.

Referenced by t38_incoming_invite_request(), and t38_outgoing_invite_request().

◆ 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.

203{
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}
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
void ast_sip_session_resume_reinvite(struct ast_sip_session *session)
Resumes processing of a deferred incoming re-invite.
A structure describing a SIP session.

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().

◆ 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.

222{
223 struct ast_sip_session *session = entry->user_data;
224
226 ao2_ref(session, -1);
227 }
228}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
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:2099
static int t38_automatic_reject(void *obj)
Task function which rejects a T.38 re-invite and resumes handling it.
Definition: search.h:40

References ao2_ref, ast_sip_push_task(), session, and t38_automatic_reject().

Referenced by t38_state_get_or_alloc().

◆ 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.

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) {
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 */
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) {
184 }
185 break;
187 /* Inform the bridge the channel is in that it needs to be reconfigured */
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}
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:1257
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...
@ AST_T38_TERMINATED
@ AST_T38_REFUSED
@ AST_T38_NEGOTIATED
@ AST_T38_REQUEST_NEGOTIATE
@ AST_CONTROL_T38_PARAMETERS
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:520
ast_sip_session_t38state
T.38 states for a session.
@ T38_MAX_ENUM
#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
void ast_udptl_set_tag(struct ast_udptl *udptl, const char *format,...)
Associates a character string 'tag' with a UDPTL session.
Definition: udptl.c:1110
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
retrieves far max ifp
Definition: udptl.c:1014
#define ast_assert(a)
Definition: utils.h:739

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(), LOG_WARNING, ast_control_t38_parameters::max_ifp, ast_control_t38_parameters::request_response, session, T38_AUTOMATIC_REJECTION_SECONDS, T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_MAX_ENUM, T38_PEER_REINVITE, T38_REJECTED, 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().

◆ t38_consume()

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

Definition at line 640 of file res_pjsip_t38.c.

641{
642 return (type == AST_FRAME_CONTROL) ? 1 : 0;
643}
static const char type[]
Definition: chan_ooh323.c:109
@ AST_FRAME_CONTROL

References AST_FRAME_CONTROL, and type.

Referenced by t38_attach_framehook().

◆ 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 408 of file res_pjsip_t38.c.

409{
410 struct ast_sip_session_media_state *media_state;
411 struct ast_stream *stream;
412 struct ast_format_cap *caps;
413 struct ast_sip_session_media *session_media;
414
415 media_state = ast_sip_session_media_state_alloc();
416 if (!media_state) {
417 return NULL;
418 }
419
420 media_state->topology = ast_stream_topology_alloc();
421 if (!media_state->topology) {
423 return NULL;
424 }
425
426 stream = ast_stream_alloc("t38", AST_MEDIA_TYPE_IMAGE);
427 if (!stream) {
429 return NULL;
430 }
431
433 if (ast_stream_topology_set_stream(media_state->topology, 0, stream)) {
434 ast_stream_free(stream);
436 return NULL;
437 }
438
440 if (!caps) {
442 return NULL;
443 }
444
445 ast_stream_set_formats(stream, caps);
446 /* stream holds a reference to cap, release the local reference
447 * now so we don't have to deal with it in the error condition. */
448 ao2_ref(caps, -1);
451 return NULL;
452 }
453
454 session_media = ast_sip_session_media_state_add(session, media_state, AST_MEDIA_TYPE_IMAGE, 0);
455 if (!session_media) {
457 return NULL;
458 }
459
460 if (t38_initialize_session(session, session_media)) {
462 return NULL;
463 }
464
465 return media_state;
466}
@ AST_MEDIA_TYPE_IMAGE
Definition: codec.h:34
struct ast_format * ast_format_t38
Built-in cached T.38 format.
Definition: format_cache.c:241
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
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.
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's vector.
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:652
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
Definition: stream.c:233
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:799
@ AST_STREAM_STATE_SENDRECV
Set when the stream is sending and receiving media.
Definition: stream.h:82
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
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
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
Definition: stream.c:292
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Structure which contains media state information (streams, sessions)
struct ast_stream_topology * topology
The media stream topology.
A structure containing SIP session media information.

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(), NULL, session, t38_initialize_session(), and ast_sip_session_media_state::topology.

Referenced by t38_interpret_parameters().

◆ 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 578 of file res_pjsip_t38.c.

580{
581 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
582
584 return f;
585 }
586
589 if (channel->session->endpoint->media.t38.enabled) {
591
593 if (task_data
596 ao2_ref(task_data, -1);
597 }
598 } else {
599 static const struct ast_control_t38_parameters rsp_refused = {
601 };
602 static const struct ast_control_t38_parameters rsp_terminated = {
604 };
605 const struct ast_control_t38_parameters *parameters = f->data.ptr;
606
607 switch (parameters->request_response) {
609 ast_debug(2, "T.38 support not enabled on %s, refusing T.38 negotiation\n",
610 ast_channel_name(chan));
612 &rsp_refused, sizeof(rsp_refused));
613 break;
615 ast_debug(2, "T.38 support not enabled on %s, 'terminating' T.38 session\n",
616 ast_channel_name(chan));
618 &rsp_terminated, sizeof(rsp_terminated));
619 break;
620 default:
621 break;
622 }
623 }
624 }
625
626 return f;
627}
void * ast_channel_tech_pvt(const struct ast_channel *chan)
@ AST_FRAMEHOOK_EVENT_WRITE
Definition: framehook.h:153
@ AST_T38_REQUEST_TERMINATE
static int t38_interpret_parameters(void *obj)
Task for reacting to T.38 control frame.
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.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
struct ast_sip_t38_configuration t38
Definition: res_pjsip.h:914
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:991
struct ast_sip_endpoint * endpoint
struct ast_taskprocessor * serializer
Definition: astman.c:222
Structure for T.38 parameters task data.
Definition: res_pjsip_t38.c:88
userdata associated with baseline taskprocessor test

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().

◆ 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 714 of file res_pjsip_t38.c.

715{
716 switch (rate) {
718 return 2400;
720 return 4800;
722 return 7200;
724 return 9600;
726 return 12000;
728 return 14400;
729 default:
730 return 0;
731 }
732}
@ AST_T38_RATE_12000
@ AST_T38_RATE_9600
@ AST_T38_RATE_2400
@ AST_T38_RATE_14400
@ AST_T38_RATE_7200
@ AST_T38_RATE_4800

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().

◆ 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 701 of file res_pjsip_t38.c.

702{
704 return 0;
705}
static void t38_attach_framehook(struct ast_sip_session *session)
Function called to attach T.38 framehook to channel when appropriate.

References session, and t38_attach_framehook().

◆ 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.

257{
258 struct ast_sockaddr temp_media_address;
259 struct ast_sockaddr *media_address = &address;
260
261 if (session_media->udptl) {
262 return 0;
263 }
264
265 if (session->endpoint->media.t38.bind_udptl_to_media_address && !ast_strlen_zero(session->endpoint->media.address)) {
266 if (ast_sockaddr_parse(&temp_media_address, session->endpoint->media.address, 0)) {
267 ast_debug(5, "Endpoint %s: Binding UDPTL media to %s\n",
269 session->endpoint->media.address);
270 media_address = &temp_media_address;
271 } else {
272 ast_debug(5, "Endpoint %s: UDPTL media address invalid: %s\n",
274 session->endpoint->media.address);
275 }
276 } else {
277 struct ast_sip_transport *transport;
278
279 transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport",
280 session->endpoint->transport);
281 if (transport) {
282 struct ast_sip_transport_state *trans_state;
283
285 if (trans_state) {
286 char hoststr[PJ_INET6_ADDRSTRLEN];
287
288 pj_sockaddr_print(&trans_state->host, hoststr, sizeof(hoststr), 0);
289 if (ast_sockaddr_parse(&temp_media_address, hoststr, 0)) {
290 ast_debug(5, "Transport %s bound to %s: Using it for UDPTL media.\n",
291 session->endpoint->transport, hoststr);
292 media_address = &temp_media_address;
293 } else {
294 ast_debug(5, "Transport %s bound to %s: Invalid for UDPTL media.\n",
295 session->endpoint->transport, hoststr);
296 }
297 ao2_ref(trans_state, -1);
298 }
299 ao2_ref(transport, -1);
300 }
301 }
302
303 if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, media_address))) {
304 return -1;
305 }
306
307 ast_udptl_set_error_correction_scheme(session_media->udptl, session->endpoint->media.t38.error_correction);
308 ast_udptl_setnat(session_media->udptl, session->endpoint->media.t38.nat);
309 ast_udptl_set_far_max_datagram(session_media->udptl, session->endpoint->media.t38.maxdatagram);
310 ast_debug(3, "UDPTL initialized on session for %s\n", ast_channel_name(session->channel));
311
312 return 0;
313}
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static struct ast_sockaddr address
Address for UDPTL.
Definition: res_pjsip_t38.c:56
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
struct pjsip_transport * transport
Transport itself.
Definition: res_pjsip.h:118
Transport to bind to.
Definition: res_pjsip.h:218
void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
Definition: udptl.c:743
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:1026
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:995
void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
Definition: udptl.c:943

References address, ao2_ref, ast_channel_name(), ast_debug, ast_sip_get_sorcery(), ast_sip_get_transport_state(), ast_sockaddr_parse(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_id(), ast_strlen_zero(), ast_udptl_new_with_bindaddr(), ast_udptl_set_error_correction_scheme(), ast_udptl_set_far_max_datagram(), ast_udptl_setnat(), ast_sip_transport_state::host, NULL, session, ast_sip_transport_state::transport, and ast_sip_session_media::udptl.

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

◆ t38_interpret_parameters()

static int t38_interpret_parameters ( void *  obj)
static

Task for reacting to T.38 control frame.

Definition at line 469 of file res_pjsip_t38.c.

470{
471 RAII_VAR(struct t38_parameters_task_data *, data, obj, ao2_cleanup);
472 const struct ast_control_t38_parameters *parameters = data->frame->data.ptr;
473 struct t38_state *state = t38_state_get_or_alloc(data->session);
474 struct ast_sip_session_media *session_media = NULL;
475
476 if (!state) {
477 return 0;
478 }
479
480 switch (parameters->request_response) {
482 case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */
483 /* Negotiation can not take place without a valid max_ifp value. */
484 if (!parameters->max_ifp) {
485 if (data->session->t38state == T38_PEER_REINVITE) {
486 t38_change_state(data->session, NULL, state, T38_REJECTED);
487 ast_sip_session_resume_reinvite(data->session);
488 } else if (data->session->t38state == T38_ENABLED) {
489 t38_change_state(data->session, NULL, state, T38_DISABLED);
490 ast_sip_session_refresh(data->session, NULL, NULL, NULL,
492 state->media_state = NULL;
493 }
494 break;
495 } else if (data->session->t38state == T38_PEER_REINVITE) {
496 state->our_parms = *parameters;
497 /* modify our parameters to conform to the peer's parameters,
498 * based on the rules in the ITU T.38 recommendation
499 */
500 if (!state->their_parms.fill_bit_removal) {
501 state->our_parms.fill_bit_removal = 0;
502 }
503 if (!state->their_parms.transcoding_mmr) {
504 state->our_parms.transcoding_mmr = 0;
505 }
506 if (!state->their_parms.transcoding_jbig) {
507 state->our_parms.transcoding_jbig = 0;
508 }
509 state->our_parms.version = MIN(state->our_parms.version, state->their_parms.version);
510 state->our_parms.rate_management = state->their_parms.rate_management;
511 session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
512 if (!session_media) {
513 ast_log(LOG_ERROR, "Failed to negotiate parameters for reinvite on channel '%s' (No pending session media).\n",
514 data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
515 break;
516 }
517 ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
518 t38_change_state(data->session, session_media, state, T38_ENABLED);
519 ast_sip_session_resume_reinvite(data->session);
520 } else if ((data->session->t38state != T38_ENABLED) ||
521 ((data->session->t38state == T38_ENABLED) &&
523 struct ast_sip_session_media_state *media_state;
524
525 media_state = t38_create_media_state(data->session);
526 if (!media_state) {
527 break;
528 }
529 state->our_parms = *parameters;
530 session_media = media_state->default_session[AST_MEDIA_TYPE_IMAGE];
531 if (!session_media) {
532 ast_log(LOG_ERROR, "Failed to negotiate parameters on channel '%s' (No default session media).\n",
533 data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
534 break;
535 }
536 ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
540 }
541 break;
543 case AST_T38_REFUSED:
544 case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */
545 if (data->session->t38state == T38_PEER_REINVITE) {
546 t38_change_state(data->session, NULL, state, T38_REJECTED);
547 ast_sip_session_resume_reinvite(data->session);
548 } else if (data->session->t38state == T38_ENABLED) {
549 t38_change_state(data->session, NULL, state, T38_DISABLED);
551 state->media_state = NULL;
552 }
553 break;
554 case AST_T38_REQUEST_PARMS: { /* Application wants remote's parameters re-sent */
555 struct ast_control_t38_parameters parameters = state->their_parms;
556
557 if (data->session->t38state == T38_PEER_REINVITE) {
558 session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
559 if (!session_media) {
560 ast_log(LOG_ERROR, "Failed to request parameters for reinvite on channel '%s' (No pending session media).\n",
561 data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
562 break;
563 }
564 parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
566 ast_queue_control_data(data->session->channel, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
567 }
568 break;
569 }
570 default:
571 break;
572 }
573
574 return 0;
575}
@ AST_T38_REQUEST_PARMS
@ AST_SIP_SESSION_REFRESH_METHOD_INVITE
Definition: res_pjsip.h:622
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 int t38_reinvite_sdp_cb(struct ast_sip_session *session, pjmedia_sdp_session *sdp)
Callback for when T.38 reinvite SDP is created.
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_media_state * t38_create_media_state(struct ast_sip_session *session)
Helper function which creates a media state for strictly T.38.
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
void ast_udptl_set_local_max_ifp(struct ast_udptl *udptl, unsigned int max_ifp)
Definition: udptl.c:971
#define MIN(a, b)
Definition: utils.h:231

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, LOG_ERROR, ast_control_t38_parameters::max_ifp, MIN, NULL, RAII_VAR, 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(), and ast_sip_session_media::udptl.

Referenced by t38_framehook().

◆ 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 743 of file res_pjsip_t38.c.

745{
746 unsigned int attr_i;
747
748 for (attr_i = 0; attr_i < stream->attr_count; attr_i++) {
749 pjmedia_sdp_attr *attr = stream->attr[attr_i];
750
751 if (!pj_stricmp2(&attr->name, "t38faxmaxbuffer")) {
752 /* This is purposely left empty, it is unused */
753 } else if (!pj_stricmp2(&attr->name, "t38maxbitrate") || !pj_stricmp2(&attr->name, "t38faxmaxrate")) {
754 switch (pj_strtoul(&attr->value)) {
755 case 14400:
756 state->their_parms.rate = AST_T38_RATE_14400;
757 break;
758 case 12000:
759 state->their_parms.rate = AST_T38_RATE_12000;
760 break;
761 case 9600:
762 state->their_parms.rate = AST_T38_RATE_9600;
763 break;
764 case 7200:
765 state->their_parms.rate = AST_T38_RATE_7200;
766 break;
767 case 4800:
768 state->their_parms.rate = AST_T38_RATE_4800;
769 break;
770 case 2400:
771 state->their_parms.rate = AST_T38_RATE_2400;
772 break;
773 }
774 } else if (!pj_stricmp2(&attr->name, "t38faxversion")) {
775 state->their_parms.version = pj_strtoul(&attr->value);
776 } else if (!pj_stricmp2(&attr->name, "t38faxmaxdatagram") || !pj_stricmp2(&attr->name, "t38maxdatagram")) {
777 if (!session->endpoint->media.t38.maxdatagram) {
778 ast_udptl_set_far_max_datagram(session_media->udptl, pj_strtoul(&attr->value));
779 }
780 } else if (!pj_stricmp2(&attr->name, "t38faxfillbitremoval")) {
781 state->their_parms.fill_bit_removal = 1;
782 } else if (!pj_stricmp2(&attr->name, "t38faxtranscodingmmr")) {
783 state->their_parms.transcoding_mmr = 1;
784 } else if (!pj_stricmp2(&attr->name, "t38faxtranscodingjbig")) {
785 state->their_parms.transcoding_jbig = 1;
786 } else if (!pj_stricmp2(&attr->name, "t38faxratemanagement")) {
787 if (!pj_stricmp2(&attr->value, "localTCF")) {
788 state->their_parms.rate_management = AST_T38_RATE_MANAGEMENT_LOCAL_TCF;
789 } else if (!pj_stricmp2(&attr->value, "transferredTCF")) {
790 state->their_parms.rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF;
791 }
792 } else if (!pj_stricmp2(&attr->name, "t38faxudpec")) {
793 if (session->t38state == T38_LOCAL_REINVITE) {
794 if (session->endpoint->media.t38.error_correction == UDPTL_ERROR_CORRECTION_FEC) {
795 if (!pj_stricmp2(&attr->value, "t38UDPFEC")) {
797 } else if (!pj_stricmp2(&attr->value, "t38UDPRedundancy")) {
799 } else {
801 }
802 } else if (session->endpoint->media.t38.error_correction == UDPTL_ERROR_CORRECTION_REDUNDANCY) {
803 if (!pj_stricmp2(&attr->value, "t38UDPRedundancy")) {
805 } else {
807 }
808 } else {
810 }
811 } else {
812 if (!pj_stricmp2(&attr->value, "t38UDPRedundancy")) {
814 } else if (!pj_stricmp2(&attr->value, "t38UDPFEC")) {
816 } else {
818 }
819 }
820 }
821
822 }
823}

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(), session, T38_LOCAL_REINVITE, ast_sip_session_media::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.

Referenced by apply_negotiated_sdp_stream(), and defer_incoming_sdp_stream().

◆ 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 629 of file res_pjsip_t38.c.

631{
632 if (ast_channel_tech(old_chan) == ast_channel_tech(new_chan)) {
633 return;
634 }
635
636 /* This framehook is only applicable to PJSIP channels */
637 ast_framehook_detach(new_chan, framehook_id);
638}
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)

References ast_channel_tech(), and ast_framehook_detach().

Referenced by t38_attach_framehook().

◆ 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 708 of file res_pjsip_t38.c.

709{
711}

References session, and t38_attach_framehook().

◆ 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.

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 ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ast_frdup(fr)
Copies a frame.
static void t38_parameters_task_data_destroy(void *obj)
Destructor for T.38 data.
Definition: res_pjsip_t38.c:96
struct ast_sip_session * session
Session itself.
Definition: res_pjsip_t38.c:90
struct ast_frame * frame
T.38 control frame.
Definition: res_pjsip_t38.c:92

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

Referenced by t38_framehook().

◆ 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.

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}
#define ast_frfree(fr)

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

Referenced by t38_parameters_task_data_alloc().

◆ 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 331 of file res_pjsip_t38.c.

332{
333 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
334 struct t38_state *state;
335 struct ast_sip_session_media *session_media = NULL;
336
337 if (status.code / 100 <= 1) {
338 /* Ignore any non-final responses (1xx) */
339 return 0;
340 }
341
342 if (session->t38state != T38_LOCAL_REINVITE) {
343 /* Do nothing. We have already processed a final response. */
344 ast_debug(3, "Received %d response to T.38 re-invite on '%s' but already had a final response (T.38 state:%d)\n",
345 status.code,
346 session->channel ? ast_channel_name(session->channel) : "unknown channel",
347 session->t38state);
348 return 0;
349 }
350
352 if (!session->channel || !state) {
353 ast_log(LOG_WARNING, "Received %d response to T.38 re-invite on '%s' but state unavailable\n",
354 status.code,
355 session->channel ? ast_channel_name(session->channel) : "unknown channel");
356 return 0;
357 }
358
359 if (status.code / 100 == 2) {
360 /* Accept any 2xx response as successfully negotiated */
361 int index;
362
363 session_media = session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
364
365 /*
366 * If there is a session_media object, but no udptl object available
367 * then it's assumed the stream was declined.
368 */
369 if (session_media && !session_media->udptl) {
370 session_media = NULL;
371 }
372
373 if (!session_media) {
374 ast_log(LOG_WARNING, "Received %d response to T.38 re-invite on '%s' but no active session media\n",
375 status.code, session->channel ? ast_channel_name(session->channel) : "unknown channel");
376 } else {
377 t38_change_state(session, session_media, state, T38_ENABLED);
378
379 /* Stop all the streams in the stored away active state, they'll go back to being active once
380 * we reinvite back.
381 */
382 for (index = 0; index < AST_VECTOR_SIZE(&state->media_state->sessions); ++index) {
383 struct ast_sip_session_media *session_media = AST_VECTOR_GET(&state->media_state->sessions, index);
384
385 if (session_media && session_media->handler && session_media->handler->stream_stop) {
386 session_media->handler->stream_stop(session_media);
387 }
388 }
389
390 return 0;
391 }
392 } else {
393 session_media = session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
394 }
395
396 /* If no session_media then response contained a declined stream, so disable */
398
399 /* Abort this attempt at switching to T.38 by resetting the pending state and freeing our stored away active state */
401 state->media_state = NULL;
402 ast_sip_session_media_state_reset(session->pending_media_state);
403
404 return 0;
405}
jack_status_t status
Definition: app_jack.c:146
void ast_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state)
Reset a media state to a clean state.
struct ast_sip_session_sdp_handler * handler
SDP handler that setup the RTP.
void(* stream_stop)(struct ast_sip_session_media *session_media)
Stop a session_media created by this handler but do not destroy resources.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References 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_media::handler, LOG_WARNING, NULL, session, state, status, ast_sip_session_sdp_handler::stream_stop, t38_change_state(), T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_REJECTED, t38_state_get_or_alloc(), and ast_sip_session_media::udptl.

Referenced by t38_interpret_parameters().

◆ 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 316 of file res_pjsip_t38.c.

317{
318 struct t38_state *state;
319
321 if (!state) {
322 return -1;
323 }
324
325 state->media_state = ast_sip_session_media_state_clone(session->active_media_state);
326
327 return 0;
328}
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.

References ast_sip_session_media_state_clone(), session, state, and t38_state_get_or_alloc().

Referenced by t38_interpret_parameters().

◆ 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.

74{
75 struct t38_state *state = obj;
76
78 ast_free(obj);
79}

References ast_free, and ast_sip_session_media_state_free().

◆ 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.

232{
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}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int ast_sip_session_add_datastore(struct ast_sip_session *session, struct ast_datastore *datastore)
Add a datastore to a SIP session.
struct ast_datastore * ast_sip_session_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
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.
static const struct ast_datastore_info t38_datastore
Datastore for attaching T.38 state information.
Definition: res_pjsip_t38.c:82

References ao2_cleanup, ast_calloc, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_datastore(), NULL, RAII_VAR, session, state, t38_automatic_reject_timer_cb(), and t38_datastore.

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().

◆ unload_module()

static int unload_module ( void  )
static

Unloads the SIP T.38 module from Asterisk.

Definition at line 1125 of file res_pjsip_t38.c.

1126{
1129
1130 return 0;
1131}
void ast_sip_session_unregister_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Unregister an SDP handler.
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

References ast_sip_session_unregister_sdp_handler(), ast_sip_session_unregister_supplement(), image_sdp_handler, and t38_supplement.

Referenced by load_module().

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 1171 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.

Referenced by t38_initialize_session().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1171 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 1114 of file res_pjsip_t38.c.

Referenced by load_module(), and unload_module().

◆ 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.

Referenced by t38_state_get_or_alloc().

◆ t38_framehook_datastore

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

Definition at line 645 of file res_pjsip_t38.c.

Referenced by t38_attach_framehook().

◆ t38_supplement

struct ast_sip_session_supplement t38_supplement
static

Supplement for adding framehook to session channel.

Definition at line 735 of file res_pjsip_t38.c.

Referenced by load_module(), and unload_module().