Asterisk - The Open Source Telephony Project GIT-master-57e2743
Loading...
Searching...
No Matches
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.
 

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.
 
struct ast_module * AST_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.
 
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.
 
static enum ast_sip_session_sdp_stream_defer defer_incoming_sdp_stream (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
 Function which defers an incoming media stream.
 
static int load_module (void)
 Load the module.
 
static struct ast_frame * media_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.
 
static void stream_destroy (struct ast_sip_session_media *session_media)
 Function which destroys the UDPTL instance when session ends.
 
static void t38_attach_framehook (struct ast_sip_session *session)
 Function called to attach T.38 framehook to channel when appropriate.
 
static int t38_automatic_reject (void *obj)
 Task function which rejects a T.38 re-invite and resumes handling it.
 
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 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.
 
static int t38_consume (void *data, enum ast_frame_type type)
 
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.
 
static struct ast_frame * t38_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 Frame hook callback for T.38 related stuff.
 
static unsigned int t38_get_rate (enum ast_control_t38_rate rate)
 Get Max T.38 Transmission rate from T38 capabilities.
 
static int t38_incoming_invite_request (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 Function called when an INVITE arrives.
 
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 int t38_interpret_parameters (void *obj)
 Task for reacting to T.38 control frame.
 
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.
 
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.
 
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 void t38_parameters_task_data_destroy (void *obj)
 Destructor for T.38 data.
 
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 int t38_reinvite_sdp_cb (struct ast_sip_session *session, pjmedia_sdp_session *sdp)
 Callback for when T.38 reinvite SDP is created.
 
static void t38_state_destroy (void *obj)
 Destructor for T.38 state information.
 
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 int unload_module (void)
 Unloads the SIP T.38 module from Asterisk.
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP T.38 UDPTL Support" , .key = ASTERISK_GPL_KEY , .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.
 
static const struct ast_module_info * ast_module_info = &__mod_info
 
static struct ast_sip_session_sdp_handler image_sdp_handler
 SDP handler for 'image' media stream.
 
static const struct ast_datastore_info t38_datastore
 Datastore for attaching T.38 state information.
 
static const struct ast_datastore_info t38_framehook_datastore
 
static struct ast_sip_session_supplement t38_supplement
 Supplement for adding framehook to session channel.
 

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

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

1049{
1050 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
1051 pjmedia_sdp_media *remote_stream = remote->media[index];
1052 char host[NI_MAXHOST];
1053 struct t38_state *state;
1054
1055 if (!session_media->udptl) {
1056 ast_debug(3, "Not applying negotiated SDP stream: no UDTPL session\n");
1057 return 0;
1058 }
1059
1061 return -1;
1062 }
1063
1064 ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
1065
1066 /* Ensure that the address provided is valid */
1067 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
1068 /* The provided host was actually invalid so we error out this negotiation */
1069 ast_debug(3, "Not applying negotiated SDP stream: failed to resolve remote stream host\n");
1070 return -1;
1071 }
1072
1073 ast_sockaddr_set_port(addrs, remote_stream->desc.port);
1074 ast_udptl_set_peer(session_media->udptl, addrs);
1075
1076 t38_interpret_sdp(state, session, session_media, remote_stream);
1077
1079 ast_sip_session_media_add_read_callback(session, session_media, ast_udptl_fd(session_media->udptl),
1081
1082 return 0;
1083}
static struct ast_mansession session
#define ast_free(a)
Definition astmm.h:180
static PGconn * conn
Definition cdr_pgsql.c:87
#define ast_debug(level,...)
Log a DEBUG message.
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_AF_UNSPEC
Definition netsock2.h:54
#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:2221
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.
enum ast_sip_session_t38state state
Current state.
int ast_udptl_fd(const struct ast_udptl *udptl)
Definition udptl.c:755
void ast_udptl_set_peer(struct ast_udptl *udptl, const struct ast_sockaddr *them)
Definition udptl.c:1155
#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:981

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, t38_state::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 1178 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 1086 of file res_pjsip_t38.c.

1087{
1089 char host[NI_MAXHOST];
1090 struct ast_sockaddr our_sdp_addr = { { 0, } };
1091
1092 /* If the stream has been rejected there will be no connection line */
1093 if (!stream->conn || !transport_state) {
1094 return;
1095 }
1096
1097 ast_copy_pj_str(host, &stream->conn->addr, sizeof(host));
1098 ast_sockaddr_parse(&our_sdp_addr, host, PARSE_PORT_FORBID);
1099
1100 /* Reversed check here. We don't check the remote endpoint being
1101 * in our local net, but whether our outgoing session IP is
1102 * local. If it is not, we won't do rewriting. No localnet
1103 * configured? Always rewrite. */
1104 if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) {
1105 return;
1106 }
1107 ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
1108 pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
1109}
#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:210
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:2381
Structure for SIP transport information.
Definition res_pjsip.h:117

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

913{
914 pj_pool_t *pool = session->inv_session->pool_prov;
915 static const pj_str_t STR_IN = { "IN", 2 };
916 static const pj_str_t STR_IP4 = { "IP4", 3};
917 static const pj_str_t STR_IP6 = { "IP6", 3};
918 static const pj_str_t STR_UDPTL = { "udptl", 5 };
919 static const pj_str_t STR_T38 = { "t38", 3 };
920 static const pj_str_t STR_TRANSFERREDTCF = { "transferredTCF", 14 };
921 static const pj_str_t STR_LOCALTCF = { "localTCF", 8 };
922 static const pj_str_t STR_T38UDPFEC = { "t38UDPFEC", 9 };
923 static const pj_str_t STR_T38UDPREDUNDANCY = { "t38UDPRedundancy", 16 };
924 struct t38_state *state;
925 pjmedia_sdp_media *media;
926 const char *hostip = NULL;
927 struct ast_sockaddr addr;
928 char tmp[512];
929 pj_str_t stmp;
930
931 if (!session->endpoint->media.t38.enabled) {
932 ast_debug(3, "Not creating outgoing SDP stream: T.38 not enabled\n");
933 return 1;
934 } else if ((session->t38state != T38_LOCAL_REINVITE) && (session->t38state != T38_PEER_REINVITE) &&
935 (session->t38state != T38_ENABLED)) {
936 ast_debug(3, "Not creating outgoing SDP stream: T.38 not enabled\n");
937 return 1;
938 } else if (!(state = t38_state_get_or_alloc(session))) {
939 return -1;
940 } else if (t38_initialize_session(session, session_media)) {
941 ast_debug(3, "Not creating outgoing SDP stream: Failed to initialize T.38 session\n");
942 return -1;
943 }
944
945 if (!(media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media))) ||
946 !(media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn)))) {
947 return -1;
948 }
949
950 pj_strdup2(pool, &media->desc.media, ast_codec_media_type2str(session_media->type));
951 media->desc.transport = STR_UDPTL;
952
953 if (ast_strlen_zero(session->endpoint->media.address)) {
954 hostip = ast_sip_get_host_ip_string(session->endpoint->media.t38.ipv6 ? pj_AF_INET6() : pj_AF_INET());
955 } else {
956 hostip = session->endpoint->media.address;
957 }
958
959 if (ast_strlen_zero(hostip)) {
960 ast_debug(3, "Not creating outgoing SDP stream: no known host IP\n");
961 return -1;
962 }
963
964 media->conn->net_type = STR_IN;
965 media->conn->addr_type = session->endpoint->media.t38.ipv6 ? STR_IP6 : STR_IP4;
966 pj_strdup2(pool, &media->conn->addr, hostip);
967 ast_udptl_get_us(session_media->udptl, &addr);
968 media->desc.port = (pj_uint16_t) ast_sockaddr_port(&addr);
969 media->desc.port_count = 1;
970 media->desc.fmt[media->desc.fmt_count++] = STR_T38;
971
972 snprintf(tmp, sizeof(tmp), "%u", state->our_parms.version);
973 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxVersion", pj_cstr(&stmp, tmp));
974
975 snprintf(tmp, sizeof(tmp), "%u", t38_get_rate(state->our_parms.rate));
976 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38MaxBitRate", pj_cstr(&stmp, tmp));
977
978 if (state->our_parms.fill_bit_removal) {
979 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxFillBitRemoval", NULL);
980 }
981
982 if (state->our_parms.transcoding_mmr) {
983 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxTranscodingMMR", NULL);
984 }
985
986 if (state->our_parms.transcoding_jbig) {
987 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxTranscodingJBIG", NULL);
988 }
989
990 switch (state->our_parms.rate_management) {
992 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxRateManagement", &STR_TRANSFERREDTCF);
993 break;
995 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxRateManagement", &STR_LOCALTCF);
996 break;
997 }
998
999 snprintf(tmp, sizeof(tmp), "%u", ast_udptl_get_local_max_datagram(session_media->udptl));
1000 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxMaxDatagram", pj_cstr(&stmp, tmp));
1001
1002 switch (ast_udptl_get_error_correction_scheme(session_media->udptl)) {
1004 break;
1006 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxUdpEC", &STR_T38UDPFEC);
1007 break;
1009 media->attr[media->attr_count++] = pjmedia_sdp_attr_create(pool, "T38FaxUdpEC", &STR_T38UDPREDUNDANCY);
1010 break;
1011 }
1012
1013 sdp->media[sdp->media_count++] = media;
1014
1015 return 1;
1016}
#define T38_ENABLED
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:2513
@ T38_PEER_REINVITE
@ T38_LOCAL_REINVITE
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:965
void ast_udptl_get_us(const struct ast_udptl *udptl, struct ast_sockaddr *us)
Definition udptl.c:1165
unsigned int ast_udptl_get_local_max_datagram(struct ast_udptl *udptl)
retrieves local_max_datagram.
Definition udptl.c:1009
@ 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, t38_state::state, T38_ENABLED, t38_get_rate(), t38_initialize_session(), T38_LOCAL_REINVITE, T38_PEER_REINVITE, t38_state_get_or_alloc(), 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 833 of file res_pjsip_t38.c.

836{
837 struct t38_state *state;
838
839 if (!session->endpoint->media.t38.enabled) {
840 ast_debug(3, "Not deferring incoming SDP stream: T.38 not enabled on %s\n", ast_channel_name(session->channel));
842 }
843
844 if (t38_initialize_session(session, session_media)) {
845 ast_debug(3, "Not deferring incoming SDP stream: Failed to initialize UDPTL on %s\n", ast_channel_name(session->channel));
847 }
848
851 }
852
853 t38_interpret_sdp(state, session, session_media, stream);
854
855 /* If they are initiating the re-invite we need to defer responding until later */
856 if (session->t38state == T38_DISABLED) {
858 ast_debug(3, "Deferring incoming SDP stream on %s for peer re-invite\n", ast_channel_name(session->channel));
860 }
861
863}
#define T38_DISABLED
const char * ast_channel_name(const struct ast_channel *chan)
@ 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, t38_state::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 1150 of file res_pjsip_t38.c.

1151{
1152 if (ast_check_ipv6()) {
1153 ast_sockaddr_parse(&address, "::", 0);
1154 } else {
1155 ast_sockaddr_parse(&address, "0.0.0.0", 0);
1156 }
1157
1159
1161 ast_log(LOG_ERROR, "Unable to register SDP handler for image stream type\n");
1162 goto end;
1163 }
1164
1166end:
1167 unload_module();
1168
1170}
#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:2826

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

1019{
1020 struct ast_frame *frame;
1021
1022 if (!session_media->udptl) {
1023 return &ast_null_frame;
1024 }
1025
1026 frame = ast_udptl_read(session_media->udptl);
1027 if (!frame) {
1028 return NULL;
1029 }
1030
1031 frame->stream_num = session_media->stream_num;
1032
1033 return frame;
1034}
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:787

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

1037{
1038 if (!session_media->udptl) {
1039 return 0;
1040 }
1041
1042 return ast_udptl_write(session_media->udptl, frame);
1043}
int ast_udptl_write(struct ast_udptl *udptl, struct ast_frame *f)
Definition udptl.c:1186

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

869{
870 struct t38_state *state;
871 char host[NI_MAXHOST];
872 pjmedia_sdp_media *stream = sdp->media[index];
873 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
874
875 if (!session->endpoint->media.t38.enabled) {
876 ast_debug(3, "Declining; T.38 not enabled on session\n");
877 return 0;
878 }
879
881 return 0;
882 }
883
884 if ((session->t38state == T38_REJECTED) || (session->t38state == T38_DISABLED)) {
885 ast_debug(3, "Declining; T.38 state is rejected or declined\n");
887 return 0;
888 }
889
890 ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
891
892 /* Ensure that the address provided is valid */
893 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
894 /* The provided host was actually invalid so we error out this negotiation */
895 ast_debug(3, "Declining; provided host is invalid\n");
896 return 0;
897 }
898
899 /* Check the address family to make sure it matches configured */
900 if ((ast_sockaddr_is_ipv6(addrs) && !session->endpoint->media.t38.ipv6) ||
901 (ast_sockaddr_is_ipv4(addrs) && session->endpoint->media.t38.ipv6)) {
902 /* The address does not match configured */
903 ast_debug(3, "Declining, provided host does not match configured address family\n");
904 return 0;
905 }
906
907 return 1;
908}
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, t38_state::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 1112 of file res_pjsip_t38.c.

1113{
1114 if (session_media->udptl) {
1115 ast_udptl_destroy(session_media->udptl);
1116 }
1117 session_media->udptl = NULL;
1118}
void ast_udptl_destroy(struct ast_udptl *udptl)
Definition udptl.c:1175

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

658{
659 int framehook_id;
660 struct ast_datastore *datastore = NULL;
661 static struct ast_framehook_interface hook = {
663 .event_cb = t38_framehook,
664 .consume_cb = t38_consume,
665 .chan_fixup_cb = t38_masq,
666 .chan_breakdown_cb = t38_masq,
667 };
668
669 /* If the channel's already gone, bail */
670 if (!session->channel) {
671 return;
672 }
673
674 /* Always attach the framehook so we can quickly reject */
675
676 ast_channel_lock(session->channel);
677
678 /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
680 NULL);
681 if (datastore) {
682 ast_channel_unlock(session->channel);
683 return;
684 }
685
686 framehook_id = ast_framehook_attach(session->channel, &hook);
687 if (framehook_id < 0) {
688 ast_log(LOG_WARNING, "Could not attach T.38 Frame hook, T.38 will be unavailable on '%s'\n",
689 ast_channel_name(session->channel));
690 ast_channel_unlock(session->channel);
691 return;
692 }
693
695 if (!datastore) {
696 ast_log(LOG_ERROR, "Could not alloc T.38 Frame hook datastore, T.38 will be unavailable on '%s'\n",
697 ast_channel_name(session->channel));
698 ast_framehook_detach(session->channel, framehook_id);
699 ast_channel_unlock(session->channel);
700 return;
701 }
702
703 ast_channel_datastore_add(session->channel, datastore);
704 ast_channel_unlock(session->channel);
705}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2376
#define ast_channel_lock(chan)
Definition channel.h:2983
#define ast_channel_unlock(chan)
Definition channel.h:2984
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 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 209 of file res_pjsip_t38.c.

210{
213
214 if (!datastore) {
215 return 0;
216 }
217
218 ast_debug(2, "Automatically rejecting T.38 request on channel '%s'\n",
219 session->channel ? ast_channel_name(session->channel) : "<gone>");
220
221 t38_change_state(session, NULL, datastore->data, T38_REJECTED);
223
224 return 0;
225}
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 228 of file res_pjsip_t38.c.

229{
230 struct ast_sip_session *session = entry->user_data;
231
233 ao2_ref(session, -1);
234 }
235}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
#define ast_sip_push_task(serializer, sip_task, task_data)
Definition res_pjsip.h:2126
static int t38_automatic_reject(void *obj)
Task function which rejects a T.38 re-invite and resumes handling it.

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 /* CHANNEL(pjsip,t38state) reads this under the channel lock. */
141 if (session->channel) {
142 ast_channel_lock(session->channel);
143 }
144 session->t38state = new_state;
145 if (session->channel) {
146 ast_channel_unlock(session->channel);
147 }
148 ast_debug(2, "T.38 state changed to '%u' from '%u' on channel '%s'\n",
149 new_state, old_state,
150 session->channel ? ast_channel_name(session->channel) : "<gone>");
151
152 if (pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
153 &state->timer, 0)) {
154 ast_debug(2, "Automatic T.38 rejection on channel '%s' terminated\n",
155 session->channel ? ast_channel_name(session->channel) : "<gone>");
156 ao2_ref(session, -1);
157 }
158
159 if (!session->channel) {
160 return;
161 }
162
163 switch (new_state) {
165 ao2_ref(session, +1);
166 if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &state->timer, &delay) != PJ_SUCCESS) {
167 ast_log(LOG_WARNING, "Scheduling of automatic T.38 rejection for channel '%s' failed\n",
168 ast_channel_name(session->channel));
169 ao2_ref(session, -1);
170 }
171 parameters = state->their_parms;
172 parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
174 ast_udptl_set_tag(session_media->udptl, "%s", ast_channel_name(session->channel));
175
176 /* Inform the bridge the channel is in that it needs to be reconfigured */
178 break;
179 case T38_ENABLED:
180 parameters = state->their_parms;
181 parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
183 ast_udptl_set_tag(session_media->udptl, "%s", ast_channel_name(session->channel));
184 break;
185 case T38_REJECTED:
186 case T38_DISABLED:
187 if (old_state == T38_ENABLED) {
189 } else if (old_state == T38_LOCAL_REINVITE) {
191 }
192 break;
194 /* Inform the bridge the channel is in that it needs to be reconfigured */
196 break;
197 case T38_MAX_ENUM:
198 /* Well, that shouldn't happen */
199 ast_assert(0);
200 break;
201 }
202
203 if (parameters.request_response) {
204 ast_queue_control_data(session->channel, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
205 }
206}
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:1296
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_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:518
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.
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:1137
unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
retrieves far max ifp
Definition udptl.c:1041
#define ast_assert(a)
Definition utils.h:779

References ao2_ref, ast_assert, ast_channel_lock, ast_channel_name(), ast_channel_set_unbridged(), ast_channel_unlock, 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 647 of file res_pjsip_t38.c.

648{
649 return (type == AST_FRAME_CONTROL) ? 1 : 0;
650}
static const char type[]
@ 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 415 of file res_pjsip_t38.c.

416{
417 struct ast_sip_session_media_state *media_state;
418 struct ast_stream *stream;
419 struct ast_format_cap *caps;
420 struct ast_sip_session_media *session_media;
421
422 media_state = ast_sip_session_media_state_alloc();
423 if (!media_state) {
424 return NULL;
425 }
426
427 media_state->topology = ast_stream_topology_alloc();
428 if (!media_state->topology) {
430 return NULL;
431 }
432
433 stream = ast_stream_alloc("t38", AST_MEDIA_TYPE_IMAGE);
434 if (!stream) {
436 return NULL;
437 }
438
440 if (ast_stream_topology_set_stream(media_state->topology, 0, stream)) {
441 ast_stream_free(stream);
443 return NULL;
444 }
445
447 if (!caps) {
449 return NULL;
450 }
451
452 ast_stream_set_formats(stream, caps);
453 /* stream holds a reference to cap, release the local reference
454 * now so we don't have to deal with it in the error condition. */
455 ao2_ref(caps, -1);
458 return NULL;
459 }
460
461 session_media = ast_sip_session_media_state_add(session, media_state, AST_MEDIA_TYPE_IMAGE, 0);
462 if (!session_media) {
464 return NULL;
465 }
466
467 if (t38_initialize_session(session, session_media)) {
469 return NULL;
470 }
471
472 return media_state;
473}
@ AST_MEDIA_TYPE_IMAGE
Definition codec.h:34
struct ast_format * ast_format_t38
Built-in cached T.38 format.
@ 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 585 of file res_pjsip_t38.c.

587{
588 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
589
591 return f;
592 }
593
596 if (channel->session->endpoint->media.t38.enabled) {
598
600 if (task_data
603 ao2_ref(task_data, -1);
604 }
605 } else {
606 static const struct ast_control_t38_parameters rsp_refused = {
608 };
609 static const struct ast_control_t38_parameters rsp_terminated = {
611 };
612 const struct ast_control_t38_parameters *parameters = f->data.ptr;
613
614 switch (parameters->request_response) {
616 ast_debug(2, "T.38 support not enabled on %s, refusing T.38 negotiation\n",
617 ast_channel_name(chan));
619 &rsp_refused, sizeof(rsp_refused));
620 break;
622 ast_debug(2, "T.38 support not enabled on %s, 'terminating' T.38 session\n",
623 ast_channel_name(chan));
625 &rsp_terminated, sizeof(rsp_terminated));
626 break;
627 default:
628 break;
629 }
630 }
631 }
632
633 return f;
634}
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
enum ast_frame_type frametype
union ast_frame::@237 data
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:1023
struct ast_sip_endpoint_media_configuration media
Definition res_pjsip.h:1100
struct ast_sip_endpoint * endpoint
struct ast_taskprocessor * serializer
Structure for T.38 parameters task data.
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 721 of file res_pjsip_t38.c.

722{
723 switch (rate) {
725 return 2400;
727 return 4800;
729 return 7200;
731 return 9600;
733 return 12000;
735 return 14400;
736 default:
737 return 0;
738 }
739}
@ 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 708 of file res_pjsip_t38.c.

709{
711 return 0;
712}
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 263 of file res_pjsip_t38.c.

264{
265 struct ast_sockaddr temp_media_address;
266 struct ast_sockaddr *media_address = &address;
267
268 if (session_media->udptl) {
269 return 0;
270 }
271
272 if (session->endpoint->media.t38.bind_udptl_to_media_address && !ast_strlen_zero(session->endpoint->media.address)) {
273 if (ast_sockaddr_parse(&temp_media_address, session->endpoint->media.address, 0)) {
274 ast_debug(5, "Endpoint %s: Binding UDPTL media to %s\n",
276 session->endpoint->media.address);
277 media_address = &temp_media_address;
278 } else {
279 ast_debug(5, "Endpoint %s: UDPTL media address invalid: %s\n",
281 session->endpoint->media.address);
282 }
283 } else {
284 struct ast_sip_transport *transport;
285
286 transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport",
287 session->endpoint->transport);
288 if (transport) {
289 struct ast_sip_transport_state *trans_state;
290
292 if (trans_state) {
293 char hoststr[PJ_INET6_ADDRSTRLEN];
294
295 pj_sockaddr_print(&trans_state->host, hoststr, sizeof(hoststr), 0);
296 if (ast_sockaddr_parse(&temp_media_address, hoststr, 0)) {
297 ast_debug(5, "Transport %s bound to %s: Using it for UDPTL media.\n",
298 session->endpoint->transport, hoststr);
299 media_address = &temp_media_address;
300 } else {
301 ast_debug(5, "Transport %s bound to %s: Invalid for UDPTL media.\n",
302 session->endpoint->transport, hoststr);
303 }
304 ao2_ref(trans_state, -1);
305 }
306 ao2_ref(transport, -1);
307 }
308 }
309
310 if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, media_address))) {
311 return -1;
312 }
313
314 ast_udptl_set_error_correction_scheme(session_media->udptl, session->endpoint->media.t38.error_correction);
315 ast_udptl_setnat(session_media->udptl, session->endpoint->media.t38.nat);
316 ast_udptl_set_far_max_datagram(session_media->udptl, session->endpoint->media.t38.maxdatagram);
317 ast_debug(3, "UDPTL initialized on session for %s\n", ast_channel_name(session->channel));
318
319 return 0;
320}
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static struct ast_sockaddr address
Address for UDPTL.
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:1917
struct pjsip_transport * transport
Transport itself.
Definition res_pjsip.h:119
Transport to bind to.
Definition res_pjsip.h:219
void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
Definition udptl.c:770
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:1053
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:1022
void ast_udptl_set_error_correction_scheme(struct ast_udptl *udptl, enum ast_t38_ec_modes ec)
Definition udptl.c:970

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

477{
478 RAII_VAR(struct t38_parameters_task_data *, data, obj, ao2_cleanup);
479 const struct ast_control_t38_parameters *parameters = data->frame->data.ptr;
480 struct t38_state *state = t38_state_get_or_alloc(data->session);
481 struct ast_sip_session_media *session_media = NULL;
482
483 if (!state) {
484 return 0;
485 }
486
487 switch (parameters->request_response) {
489 case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */
490 /* Negotiation can not take place without a valid max_ifp value. */
491 if (!parameters->max_ifp) {
492 if (data->session->t38state == T38_PEER_REINVITE) {
493 t38_change_state(data->session, NULL, state, T38_REJECTED);
494 ast_sip_session_resume_reinvite(data->session);
495 } else if (data->session->t38state == T38_ENABLED) {
496 t38_change_state(data->session, NULL, state, T38_DISABLED);
497 ast_sip_session_refresh(data->session, NULL, NULL, NULL,
499 state->media_state = NULL;
500 }
501 break;
502 } else if (data->session->t38state == T38_PEER_REINVITE) {
503 state->our_parms = *parameters;
504 /* modify our parameters to conform to the peer's parameters,
505 * based on the rules in the ITU T.38 recommendation
506 */
507 if (!state->their_parms.fill_bit_removal) {
508 state->our_parms.fill_bit_removal = 0;
509 }
510 if (!state->their_parms.transcoding_mmr) {
511 state->our_parms.transcoding_mmr = 0;
512 }
513 if (!state->their_parms.transcoding_jbig) {
514 state->our_parms.transcoding_jbig = 0;
515 }
516 state->our_parms.version = MIN(state->our_parms.version, state->their_parms.version);
517 state->our_parms.rate_management = state->their_parms.rate_management;
518 session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
519 if (!session_media) {
520 ast_log(LOG_ERROR, "Failed to negotiate parameters for reinvite on channel '%s' (No pending session media).\n",
521 data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
522 break;
523 }
524 ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
525 t38_change_state(data->session, session_media, state, T38_ENABLED);
526 ast_sip_session_resume_reinvite(data->session);
527 } else if ((data->session->t38state != T38_ENABLED) ||
528 ((data->session->t38state == T38_ENABLED) &&
530 struct ast_sip_session_media_state *media_state;
531
532 media_state = t38_create_media_state(data->session);
533 if (!media_state) {
534 break;
535 }
536 state->our_parms = *parameters;
537 session_media = media_state->default_session[AST_MEDIA_TYPE_IMAGE];
538 if (!session_media) {
539 ast_log(LOG_ERROR, "Failed to negotiate parameters on channel '%s' (No default session media).\n",
540 data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
541 break;
542 }
543 ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
547 }
548 break;
550 case AST_T38_REFUSED:
551 case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */
552 if (data->session->t38state == T38_PEER_REINVITE) {
553 t38_change_state(data->session, NULL, state, T38_REJECTED);
554 ast_sip_session_resume_reinvite(data->session);
555 } else if (data->session->t38state == T38_ENABLED) {
556 t38_change_state(data->session, NULL, state, T38_DISABLED);
558 state->media_state = NULL;
559 }
560 break;
561 case AST_T38_REQUEST_PARMS: { /* Application wants remote's parameters re-sent */
562 struct ast_control_t38_parameters parameters = state->their_parms;
563
564 if (data->session->t38state == T38_PEER_REINVITE) {
565 session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
566 if (!session_media) {
567 ast_log(LOG_ERROR, "Failed to request parameters for reinvite on channel '%s' (No pending session media).\n",
568 data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
569 break;
570 }
571 parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
573 ast_queue_control_data(data->session->channel, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
574 }
575 break;
576 }
577 default:
578 break;
579 }
580
581 return 0;
582}
@ AST_T38_REQUEST_PARMS
@ AST_SIP_SESSION_REFRESH_METHOD_INVITE
Definition res_pjsip.h:717
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:998
#define MIN(a, b)
Definition utils.h:252

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

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

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

638{
639 if (ast_channel_tech(old_chan) == ast_channel_tech(new_chan)) {
640 return;
641 }
642
643 /* This framehook is only applicable to PJSIP channels */
644 ast_framehook_detach(new_chan, framehook_id);
645}
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648

References 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 715 of file res_pjsip_t38.c.

716{
718}

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.
struct ast_sip_session * session
Session itself.
struct ast_frame * frame
T.38 control frame.

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

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

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, t38_state::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 323 of file res_pjsip_t38.c.

324{
325 struct t38_state *state;
326
328 if (!state) {
329 return -1;
330 }
331
332 state->media_state = ast_sip_session_media_state_clone(session->active_media_state);
333
334 return 0;
335}
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, t38_state::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 238 of file res_pjsip_t38.c.

239{
241 struct t38_state *state;
242
243 /* While the datastore refcount is decremented this is operating in the serializer so it will remain valid regardless */
244 if (datastore) {
245 return datastore->data;
246 }
247
248 if (!(datastore = ast_sip_session_alloc_datastore(&t38_datastore, "t38"))
249 || !(datastore->data = ast_calloc(1, sizeof(struct t38_state)))
250 || ast_sip_session_add_datastore(session, datastore)) {
251 return NULL;
252 }
253
254 state = datastore->data;
255
256 /* This will get bumped up before scheduling */
257 pj_timer_entry_init(&state->timer, 0, session, t38_automatic_reject_timer_cb);
258
259 return state;
260}
#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.

References ao2_cleanup, ast_calloc, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_datastore(), NULL, RAII_VAR, session, t38_state::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 1132 of file res_pjsip_t38.c.

1133{
1136
1137 return 0;
1138}
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.

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 = ASTERISK_GPL_KEY , .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 1178 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 1178 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 1121 of file res_pjsip_t38.c.

1121 {
1122 .id = "image",
1123 .defer_incoming_sdp_stream = defer_incoming_sdp_stream,
1124 .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,
1125 .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
1126 .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
1127 .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
1128 .stream_destroy = stream_destroy,
1129};
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.
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.
static void stream_destroy(struct ast_sip_session_media *session_media)
Function which destroys the UDPTL instance when session ends.
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.
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.
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.

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.

Datastore for attaching T.38 state information.

Definition at line 82 of file res_pjsip_t38.c.

82 {
83 .type = "t38",
84 .destroy = t38_state_destroy,
85};

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

652 {
653 .type = "T38 framehook",
654};

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

742 {
743 .method = "INVITE",
745 .incoming_request = t38_incoming_invite_request,
746 .outgoing_request = t38_outgoing_invite_request,
747};
@ AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL
Definition res_pjsip.h:3413
static int t38_incoming_invite_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Function called when an INVITE arrives.
static void t38_outgoing_invite_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
Function called when an INVITE is sent.

Referenced by load_module(), and unload_module().