Asterisk - The Open Source Telephony Project GIT-master-b023714
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_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.
 
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_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.
 
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_statet38_create_media_state (struct ast_sip_session *session)
 Helper function which creates a media state for strictly T.38.
 
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.
 
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_datat38_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_statet38_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_infoast_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 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
static PGconn * conn
Definition cdr_pgsql.c:87
#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.
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:978

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 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: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 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}
#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:2493
@ 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 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}
#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 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:2828

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: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 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: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 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, 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 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: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 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:2357
#define ast_channel_lock(chan)
Definition channel.h:2982
#define ast_channel_unlock(chan)
Definition channel.h:2983
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:2371
#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.

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:1277
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: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.
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:776

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[]
@ 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.
@ 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
enum ast_frame_type frametype
union ast_frame::@239 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:1007
struct ast_sip_endpoint_media_configuration media
Definition res_pjsip.h:1084
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 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.
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 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:715
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:249

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}
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 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.
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 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: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:620
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:691

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

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

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

1114 {
1115 .id = "image",
1116 .defer_incoming_sdp_stream = defer_incoming_sdp_stream,
1117 .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,
1118 .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
1119 .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
1120 .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
1121 .stream_destroy = stream_destroy,
1122};
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 645 of file res_pjsip_t38.c.

645 {
646 .type = "T38 framehook",
647};

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.

735 {
736 .method = "INVITE",
738 .incoming_request = t38_incoming_invite_request,
739 .outgoing_request = t38_outgoing_invite_request,
740};
@ AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL
Definition res_pjsip.h:3339
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().