Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
chan_mgcp.c File Reference

Implementation of Media Gateway Control Protocol. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pickup.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/astdb.h"
#include "asterisk/features.h"
#include "asterisk/app.h"
#include "asterisk/mwi.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/netsock2.h"
#include "asterisk/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/chanvars.h"
#include "asterisk/pktccops.h"
#include "asterisk/stasis.h"
#include "asterisk/bridge.h"
#include "asterisk/features_config.h"
#include "asterisk/parking.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/format_cache.h"
Include dependency graph for chan_mgcp.c:

Go to the source code of this file.

Data Structures

struct  mgcp_endpoint
 
struct  mgcp_gateway
 
struct  mgcp_message
 mgcp_message: MGCP message for queuing up More...
 
struct  mgcp_request
 
struct  mgcp_response
 
struct  mgcp_subchannel
 

Macros

#define DEFAULT_EXPIRY   120
 
#define DEFAULT_MGCP_CA_PORT   2727
 
#define DEFAULT_MGCP_GW_PORT   2427
 
#define DEFAULT_RETRANS   1000
 
#define DIRECTMEDIA   1
 
#define INADDR_NONE   (in_addr_t)(-1)
 
#define MAX_EXPIRY   3600
 
#define MAX_RETRANS   5
 
#define MAX_SUBS   2
 
#define MGCP_CX_CONF   3
 
#define MGCP_CX_CONFERENCE   3
 
#define MGCP_CX_INACTIVE   4
 
#define MGCP_CX_MUTE   4
 
#define MGCP_CX_RECVONLY   1
 
#define MGCP_CX_SENDONLY   0
 
#define MGCP_CX_SENDRECV   2
 
#define MGCP_DTMF_HYBRID   (1 << 2)
 
#define MGCP_DTMF_INBAND   (1 << 1)
 
#define MGCP_DTMF_RFC2833   (1 << 0)
 
#define MGCP_MAX_HEADERS   64
 
#define MGCP_MAX_LINES   64
 
#define MGCP_MAX_PACKET   1500
 
#define MGCP_OFFHOOK   2
 
#define MGCP_ONHOOK   1
 
#define MGCP_SUBCHANNEL_MAGIC   "!978!"
 
#define MGCPDUMPER
 
#define RESPONSE_TIMEOUT   30
 
#define SUB_ALT   1
 
#define SUB_REAL   0
 
#define TYPE_LINE   2
 
#define TYPE_TRUNK   1
 

Enumerations

enum  {
  MGCP_CMD_EPCF, MGCP_CMD_CRCX, MGCP_CMD_MDCX, MGCP_CMD_DLCX,
  MGCP_CMD_RQNT, MGCP_CMD_NTFY, MGCP_CMD_AUEP, MGCP_CMD_AUCX,
  MGCP_CMD_RSIP
}
 

Functions

static char * __get_header (struct mgcp_request *req, char *name, int *start, char *def)
 
static int __mgcp_xmit (struct mgcp_gateway *gw, char *data, int len)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static int acf_channel_read (struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen)
 
static int add_header (struct mgcp_request *req, const char *var, const char *value)
 
static void add_header_offhook (struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone)
 
static int add_line (struct mgcp_request *req, char *line)
 
static int add_sdp (struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
 
static struct ast_variableadd_var (const char *buf, struct ast_variable *list)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int attempt_transfer (struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
 Complete an attended transfer. More...
 
static struct mgcp_gatewaybuild_gateway (char *cat, struct ast_variable *v)
 build_gateway: parse mgcp.conf and create gateway/endpoint structures More...
 
static char * control2str (int ind)
 
static struct ast_variablecopy_vars (struct ast_variable *src)
 duplicate a list of channel variables, More...
 
static void destroy_endpoint (struct mgcp_endpoint *e)
 
static void destroy_gateway (struct mgcp_gateway *g)
 
static void * do_monitor (void *data)
 
static void dump_cmd_queues (struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
 dump_cmd_queues: (SC:) cleanup pending commands More...
 
static void dump_queue (struct mgcp_gateway *gw, struct mgcp_endpoint *p)
 
static int find_and_retrans (struct mgcp_subchannel *sub, struct mgcp_request *req)
 
static struct mgcp_requestfind_command (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request **queue, ast_mutex_t *l, int ident)
 find_command: (SC:) remove command transaction from queue More...
 
static struct mgcp_gatewayfind_realtime_gw (char *name, char *at, struct sockaddr_in *sin)
 
static struct mgcp_subchannelfind_subchannel_and_lock (char *name, int msgid, struct sockaddr_in *sin)
 
static char * get_csv (char *c, int *len, char **next)
 get_csv: (SC:) get comma separated value More...
 
static char * get_header (struct mgcp_request *req, char *name)
 
static char * get_sdp (struct mgcp_request *req, char *name)
 
static char * get_sdp_by_line (char *line, char *name, int nameLen)
 
static char * get_sdp_iterate (int *iterator, struct mgcp_request *req, char *name)
 
static void handle_hd_hf (struct mgcp_subchannel *sub, char *ev)
 
static char * handle_mgcp_audit_endpoint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_mgcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_mgcp_show_endpoints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int handle_request (struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
 
static void handle_response (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp)
 
static int has_voicemail (struct mgcp_endpoint *p)
 
static int init_req (struct mgcp_endpoint *p, struct mgcp_request *req, char *verb, unsigned int oseq)
 
static int init_resp (struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
 
static int load_module (void)
 Load the module. More...
 
static int mgcp_alloc_pktcgate (struct mgcp_subchannel *sub)
 
static int mgcp_answer (struct ast_channel *ast)
 
static int mgcp_call (struct ast_channel *ast, const char *dest, int timeout)
 
static int mgcp_devicestate (const char *data)
 mgcp_devicestate: channel callback for device status monitoring More...
 
static int mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 
static void mgcp_get_codec (struct ast_channel *chan, struct ast_format_cap *result)
 
static enum ast_rtp_glue_result mgcp_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
 
static int mgcp_hangup (struct ast_channel *ast)
 
static int mgcp_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
 
static struct ast_channelmgcp_new (struct mgcp_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
 
static int mgcp_pktcgate_open (struct cops_gate *gate)
 
static int mgcp_pktcgate_remove (struct cops_gate *gate)
 
static int mgcp_postrequest (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno)
 
static int mgcp_prune_realtime_gateway (struct mgcp_gateway *g)
 
static void mgcp_queue_control (struct mgcp_subchannel *sub, int control)
 
static void mgcp_queue_frame (struct mgcp_subchannel *sub, struct ast_frame *f)
 
static void mgcp_queue_hangup (struct mgcp_subchannel *sub)
 
static struct ast_framemgcp_read (struct ast_channel *ast)
 
static char * mgcp_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static struct ast_channelmgcp_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *dest, int *cause)
 
static struct ast_framemgcp_rtp_read (struct mgcp_subchannel *sub)
 
static int mgcp_senddigit_begin (struct ast_channel *ast, char digit)
 
static int mgcp_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
 
static void mgcp_set_owner (struct mgcp_subchannel *sub, struct ast_channel *chan)
 
static int mgcp_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *cap, int nat_active)
 
static void * mgcp_ss (void *data)
 
static int mgcp_write (struct ast_channel *ast, struct ast_frame *frame)
 
static int mgcpsock_read (int *id, int fd, short events, void *ignore)
 
static void parse (struct mgcp_request *req)
 
static int process_sdp (struct mgcp_subchannel *sub, struct mgcp_request *req)
 
static void prune_gateways (void)
 
static int reload (void)
 
static int reload_config (int reload)
 
static int reqprep (struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
 
static int resend_response (struct mgcp_subchannel *sub, struct mgcp_response *resp)
 
static int respprep (struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
 
static int restart_monitor (void)
 
static int retrans_pkt (const void *data)
 
static void sdpLineNum_iterator_init (int *iterator)
 
static int send_request (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
 
static int send_response (struct mgcp_subchannel *sub, struct mgcp_request *req)
 
static void start_rtp (struct mgcp_subchannel *sub)
 
static int transmit_audit_endpoint (struct mgcp_endpoint *p)
 
static int transmit_connect (struct mgcp_subchannel *sub)
 
static int transmit_connect_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
 
static int transmit_connection_del (struct mgcp_subchannel *sub)
 
static int transmit_connection_del_w_params (struct mgcp_endpoint *p, char *callid, char *cxident)
 
static int transmit_modify_request (struct mgcp_subchannel *sub)
 
static int transmit_modify_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs)
 
static int transmit_notify_request (struct mgcp_subchannel *sub, char *tone)
 
static int transmit_notify_request_with_callerid (struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
 
static int transmit_response (struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
 
static int unalloc_sub (struct mgcp_subchannel *sub)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Media Gateway Control Protocol (MGCP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .optional_modules = "res_pktccops", }
 
static struct in_addr __ourip
 
static char accountcode [AST_MAX_ACCOUNT_CODE] = ""
 
static int adsi = 0
 
static int amaflags = 0
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct sockaddr_in bindaddr
 
static int callreturn = 0
 
static int callwaiting = 0
 
static int cancallforward = 0
 
static char cid_name [AST_MAX_EXTENSION] = ""
 
static char cid_num [AST_MAX_EXTENSION] = ""
 
static struct ast_cli_entry cli_mgcp []
 
static const char config [] = "mgcp.conf"
 
static char context [AST_MAX_EXTENSION] = "default"
 
static ast_group_t cur_callergroup = 0
 
static ast_group_t cur_pickupgroup = 0
 
static struct ast_jb_conf default_jbconf
 
static int directmedia = DIRECTMEDIA
 
static int dtmfmode = 0
 
static int firstdigittimeout = 16000
 
static ast_mutex_t gatelock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 gatelock: mutex for gateway/endpoint lists More...
 
static struct mgcp_gatewaygateways = NULL
 
static int gendigittimeout = 8000
 
static struct ast_format_capglobal_capability
 
static struct ast_jb_conf global_jbconf
 
static int hangupongateremove = 0
 
static int immediate = 0
 
static struct io_contextio
 
static char language [MAX_LANGUAGE] = ""
 
static char mailbox [AST_MAX_MAILBOX_UNIQUEID]
 
static int matchdigittimeout = 3000
 
static const char *const mgcp_cxmodes []
 
static ast_mutex_t mgcp_reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static int mgcp_reloading = 0
 
static struct ast_rtp_glue mgcp_rtp_glue
 
static struct ast_channel_tech mgcp_tech
 
static int mgcpdebug = 0
 
static int mgcpsock = -1
 
static int * mgcpsock_read_id = NULL
 
static pthread_t monitor_thread = AST_PTHREADT_NULL
 
static ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static char musicclass [MAX_MUSICCLASS] = ""
 
static int nat = 0
 
static int ncs = 0
 
static ast_mutex_t netlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static int nonCodecCapability = AST_RTP_DTMF
 
static unsigned int oseq_global = 0
 
static ast_mutex_t oseq_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static char ourhost [MAXHOSTNAMELEN]
 
static int ourport
 
static char parkinglot [AST_MAX_CONTEXT]
 
static int pktcgatealloc = 0
 
struct {
   unsigned int   cos
 
   unsigned int   cos_audio
 
   unsigned int   tos
 
   unsigned int   tos_audio
 
qos = { 0, 0, 0, 0 }
 
static struct ast_sched_contextsched
 
static int singlepath = 0
 
static int slowsequence = 0
 
static const char tdesc [] = "Media Gateway Control Protocol (MGCP)"
 
static int threewaycalling = 0
 
static int transfer = 0
 

Detailed Description

Implementation of Media Gateway Control Protocol.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file chan_mgcp.c.

Macro Definition Documentation

◆ DEFAULT_EXPIRY

#define DEFAULT_EXPIRY   120

Definition at line 96 of file chan_mgcp.c.

◆ DEFAULT_MGCP_CA_PORT

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 124 of file chan_mgcp.c.

Referenced by reload_config().

◆ DEFAULT_MGCP_GW_PORT

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 123 of file chan_mgcp.c.

Referenced by build_gateway().

◆ DEFAULT_RETRANS

#define DEFAULT_RETRANS   1000

How frequently to retransmit

Definition at line 126 of file chan_mgcp.c.

Referenced by __sip_reliable_xmit(), mgcp_postrequest(), and retrans_pkt().

◆ DIRECTMEDIA

#define DIRECTMEDIA   1

Definition at line 98 of file chan_mgcp.c.

Referenced by build_gateway().

◆ INADDR_NONE

#define INADDR_NONE   (in_addr_t)(-1)

Definition at line 101 of file chan_mgcp.c.

Referenced by build_gateway().

◆ MAX_EXPIRY

#define MAX_EXPIRY   3600

Definition at line 97 of file chan_mgcp.c.

◆ MAX_RETRANS

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 127 of file chan_mgcp.c.

Referenced by retrans_pkt().

◆ MAX_SUBS

#define MAX_SUBS   2

Definition at line 291 of file chan_mgcp.c.

Referenced by build_gateway(), destroy_endpoint(), and mgcp_prune_realtime_gateway().

◆ MGCP_CX_CONF

#define MGCP_CX_CONF   3

Definition at line 133 of file chan_mgcp.c.

Referenced by handle_request().

◆ MGCP_CX_CONFERENCE

#define MGCP_CX_CONFERENCE   3

Definition at line 134 of file chan_mgcp.c.

◆ MGCP_CX_INACTIVE

#define MGCP_CX_INACTIVE   4

Definition at line 136 of file chan_mgcp.c.

Referenced by build_gateway(), mgcp_hangup(), and unalloc_sub().

◆ MGCP_CX_MUTE

#define MGCP_CX_MUTE   4

Definition at line 135 of file chan_mgcp.c.

Referenced by handle_request().

◆ MGCP_CX_RECVONLY

#define MGCP_CX_RECVONLY   1

Definition at line 131 of file chan_mgcp.c.

Referenced by handle_request(), mgcp_call(), and mgcp_hangup().

◆ MGCP_CX_SENDONLY

#define MGCP_CX_SENDONLY   0

MGCP rtp stream modes {

Definition at line 130 of file chan_mgcp.c.

◆ MGCP_CX_SENDRECV

#define MGCP_CX_SENDRECV   2

Definition at line 132 of file chan_mgcp.c.

Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), and mgcp_call().

◆ MGCP_DTMF_HYBRID

#define MGCP_DTMF_HYBRID   (1 << 2)

◆ MGCP_DTMF_INBAND

#define MGCP_DTMF_INBAND   (1 << 1)

◆ MGCP_DTMF_RFC2833

#define MGCP_DTMF_RFC2833   (1 << 0)

◆ MGCP_MAX_HEADERS

#define MGCP_MAX_HEADERS   64

The private structures of the mgcp channels are linked for selecting outgoing channels

Definition at line 250 of file chan_mgcp.c.

Referenced by add_header(), init_req(), init_resp(), and parse().

◆ MGCP_MAX_LINES

#define MGCP_MAX_LINES   64

Definition at line 251 of file chan_mgcp.c.

Referenced by add_line(), and parse().

◆ MGCP_MAX_PACKET

#define MGCP_MAX_PACKET   1500

Also from RFC 2543, should sub headers tho

Definition at line 125 of file chan_mgcp.c.

◆ MGCP_OFFHOOK

#define MGCP_OFFHOOK   2

◆ MGCP_ONHOOK

#define MGCP_ONHOOK   1

◆ MGCP_SUBCHANNEL_MAGIC

#define MGCP_SUBCHANNEL_MAGIC   "!978!"

subchannel magic string. Needed to prove that any subchannel pointer passed by asterisk really points to a valid subchannel memory area. Ugly.. But serves the purpose for the time being.

Definition at line 302 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_hangup().

◆ MGCPDUMPER

#define MGCPDUMPER

Definition at line 95 of file chan_mgcp.c.

◆ RESPONSE_TIMEOUT

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 281 of file chan_mgcp.c.

Referenced by find_and_retrans().

◆ SUB_ALT

#define SUB_ALT   1

Definition at line 294 of file chan_mgcp.c.

◆ SUB_REAL

#define SUB_REAL   0

Definition at line 293 of file chan_mgcp.c.

◆ TYPE_LINE

#define TYPE_LINE   2

Definition at line 330 of file chan_mgcp.c.

Referenced by build_gateway(), do_monitor(), and mgcp_call().

◆ TYPE_TRUNK

#define TYPE_TRUNK   1

Definition at line 329 of file chan_mgcp.c.

Referenced by build_gateway().

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
MGCP_CMD_EPCF 
MGCP_CMD_CRCX 
MGCP_CMD_MDCX 
MGCP_CMD_DLCX 
MGCP_CMD_RQNT 
MGCP_CMD_NTFY 
MGCP_CMD_AUEP 
MGCP_CMD_AUCX 
MGCP_CMD_RSIP 

Definition at line 147 of file chan_mgcp.c.

Function Documentation

◆ __get_header()

static char* __get_header ( struct mgcp_request req,
char *  name,
int *  start,
char *  def 
)
static

Definition at line 1635 of file chan_mgcp.c.

References mgcp_request::header, mgcp_request::headers, and len().

Referenced by get_header().

1636 {
1637  int x;
1638  int len = strlen(name);
1639  char *r;
1640  for (x = *start; x < req->headers; x++) {
1641  if (!strncasecmp(req->header[x], name, len) &&
1642  (req->header[x][len] == ':')) {
1643  r = req->header[x] + len + 1;
1644  while (*r && (*r < 33)) {
1645  r++;
1646  }
1647  *start = x + 1;
1648  return r;
1649  }
1650  }
1651  /* Don't return NULL, so get_header is always a valid pointer */
1652  return def;
1653 }
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static const char name[]
Definition: cdr_mysql.c:74
char * header[MGCP_MAX_HEADERS]
Definition: chan_mgcp.c:260

◆ __mgcp_xmit()

static int __mgcp_xmit ( struct mgcp_gateway gw,
char *  data,
int  len 
)
static

Definition at line 534 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_log, mgcp_gateway::defaddr, errno, LOG_WARNING, and mgcpsock.

Referenced by mgcp_postrequest(), resend_response(), retrans_pkt(), and send_response().

535 {
536  int res;
537  if (gw->addr.sin_addr.s_addr)
538  res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
539  else
540  res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
541  if (res != len) {
542  ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
543  }
544  return res;
545 }
static int mgcpsock
Definition: chan_mgcp.c:432
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
struct sockaddr_in defaddr
Definition: chan_mgcp.c:404
void * data
Definition: parser.h:103
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
struct sockaddr_in addr
Definition: chan_mgcp.c:403

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 5025 of file chan_mgcp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 5025 of file chan_mgcp.c.

◆ acf_channel_read()

static int acf_channel_read ( struct ast_channel chan,
const char *  funcname,
char *  preparse,
char *  buf,
size_t  buflen 
)
static

Definition at line 4519 of file chan_mgcp.c.

References ast_channel_tech(), ast_channel_tech_pvt(), ast_log, LOG_ERROR, mgcp_endpoint::ncs, mgcp_subchannel::parent, and sub.

4520 {
4521  struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
4522  int res = 0;
4523 
4524  /* Sanity check */
4525  if (!chan || ast_channel_tech(chan) != &mgcp_tech) {
4526  ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n");
4527  return -1;
4528  }
4529 
4530  if (!strcasecmp(args, "ncs")) {
4531  snprintf(buf, buflen, "%s", sub->parent->ncs ? "yes":"no");
4532  } else {
4533  res = -1;
4534  }
4535  return res;
4536 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const char * args
#define ast_log
Definition: astobj2.c:42
static struct ast_channel_tech mgcp_tech
Definition: chan_mgcp.c:472
#define LOG_ERROR
Definition: logger.h:285
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
struct stasis_forward * sub
Definition: res_corosync.c:240
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)

◆ add_header()

static int add_header ( struct mgcp_request req,
const char *  var,
const char *  value 
)
static

Definition at line 2065 of file chan_mgcp.c.

References ast_log, mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_request::len, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_HEADERS.

Referenced by add_header_offhook(), transmit_audit_endpoint(), transmit_connect(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().

2066 {
2067  if (req->len >= sizeof(req->data) - 4) {
2068  ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
2069  return -1;
2070  }
2071  if (req->lines) {
2072  ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
2073  return -1;
2074  }
2075  req->header[req->headers] = req->data + req->len;
2076  snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
2077  req->len += strlen(req->header[req->headers]);
2078  if (req->headers < MGCP_MAX_HEADERS) {
2079  req->headers++;
2080  } else {
2081  ast_log(LOG_WARNING, "Out of header space\n");
2082  return -1;
2083  }
2084  return 0;
2085 }
#define LOG_WARNING
Definition: logger.h:274
#define var
Definition: ast_expr2f.c:614
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
#define MGCP_MAX_HEADERS
Definition: chan_mgcp.c:250
char * header[MGCP_MAX_HEADERS]
Definition: chan_mgcp.c:260
char data[MGCP_MAX_PACKET]
Definition: chan_mgcp.c:263

◆ add_header_offhook()

static void add_header_offhook ( struct mgcp_subchannel sub,
struct mgcp_request resp,
char *  tone 
)
static

Definition at line 2648 of file chan_mgcp.c.

References add_header(), ast_debug, AST_STATE_RINGING, mgcp_endpoint::dtmfmode, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_endpoint::ncs, mgcp_subchannel::owner, mgcp_subchannel::parent, and mgcp_endpoint::sub.

Referenced by transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

2649 {
2650  struct mgcp_endpoint *p = sub->parent;
2651  char tone_indicate_end = 0;
2652 
2653  /* We also should check the tone to indicate, because it have no sense
2654  to request notify D/[0-9#*] (dtmf keys) if we are sending congestion
2655  tone for example G/cg */
2656  if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) {
2657  tone_indicate_end = 1;
2658  }
2659 
2660  if (p && p->sub && p->sub->owner &&
2663  add_header(resp, "R", "L/hu(N),L/hf(N)");
2664 
2665  } else if (!tone_indicate_end){
2666  add_header(resp, "R", (p->ncs ? "L/hu(N),L/hf(N),L/[0-9#*](N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)"));
2667  } else {
2668  ast_debug(1, "We don't want more digits if we will end the call\n");
2669  add_header(resp, "R", "L/hu(N),L/hf(N)");
2670  }
2671 }
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:120
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct ast_channel * owner
Definition: chan_mgcp.c:306
#define MGCP_DTMF_HYBRID
Definition: chan_mgcp.c:121
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ add_line()

static int add_line ( struct mgcp_request req,
char *  line 
)
static

Definition at line 2087 of file chan_mgcp.c.

References ast_copy_string(), ast_log, mgcp_request::data, mgcp_request::len, mgcp_request::line, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_LINES.

Referenced by add_sdp().

2088 {
2089  if (req->len >= sizeof(req->data) - 4) {
2090  ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
2091  return -1;
2092  }
2093  if (!req->lines) {
2094  /* Add extra empty return */
2095  ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
2096  req->len += strlen(req->data + req->len);
2097  }
2098  req->line[req->lines] = req->data + req->len;
2099  snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
2100  req->len += strlen(req->line[req->lines]);
2101  if (req->lines < MGCP_MAX_LINES) {
2102  req->lines++;
2103  } else {
2104  ast_log(LOG_WARNING, "Out of line space\n");
2105  return -1;
2106  }
2107  return 0;
2108 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define MGCP_MAX_LINES
Definition: chan_mgcp.c:251
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char * line[MGCP_MAX_LINES]
Definition: chan_mgcp.c:262
char data[MGCP_MAX_PACKET]
Definition: chan_mgcp.c:263

◆ add_sdp()

static int add_sdp ( struct mgcp_request resp,
struct mgcp_subchannel sub,
struct ast_rtp_instance rtp 
)
static

Definition at line 2201 of file chan_mgcp.c.

References a, add_line(), ao2_ref, ast_copy_string(), ast_debug, ast_format_cap_count(), ast_format_cap_get_format(), ast_format_get_name(), ast_format_get_type(), ast_inet_ntoa(), ast_log, AST_MEDIA_TYPE_AUDIO, ast_rtp_codecs_payload_code(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address, ast_rtp_lookup_mime_subtype2(), AST_RTP_MAX, ast_sockaddr_to_sin, c, mgcp_endpoint::cap, format, len(), LOG_WARNING, mgcp_endpoint::nonCodecCapability, NULL, mgcp_gateway::ourip, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_subchannel::rtp, and mgcp_subchannel::tmpdest.

Referenced by transmit_connect_with_sdp(), transmit_modify_request(), and transmit_modify_with_sdp().

2202 {
2203  int len;
2204  int codec;
2205  char costr[80];
2206  struct sockaddr_in sin;
2207  struct ast_sockaddr sin_tmp;
2208  char v[256];
2209  char s[256];
2210  char o[256];
2211  char c[256];
2212  char t[256];
2213  char m[256] = "";
2214  char a[1024] = "";
2215  int x;
2216  struct sockaddr_in dest = { 0, };
2217  struct ast_sockaddr dest_tmp;
2218  struct mgcp_endpoint *p = sub->parent;
2219  /* XXX We break with the "recommendation" and send our IP, in order that our
2220  peer doesn't have to ast_gethostbyname() us XXX */
2221  len = 0;
2222  if (!sub->rtp) {
2223  ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
2224  return -1;
2225  }
2226  ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp);
2227  ast_sockaddr_to_sin(&sin_tmp, &sin);
2228  if (rtp) {
2229  ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp);
2230  ast_sockaddr_to_sin(&dest_tmp, &dest);
2231  } else {
2232  if (sub->tmpdest.sin_addr.s_addr) {
2233  dest.sin_addr = sub->tmpdest.sin_addr;
2234  dest.sin_port = sub->tmpdest.sin_port;
2235  /* Reset temporary destination */
2236  memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
2237  } else {
2238  dest.sin_addr = p->parent->ourip;
2239  dest.sin_port = sin.sin_port;
2240  }
2241  }
2242  ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
2243  ast_copy_string(v, "v=0\r\n", sizeof(v));
2244  snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
2245  ast_copy_string(s, "s=session\r\n", sizeof(s));
2246  snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
2247  ast_copy_string(t, "t=0 0\r\n", sizeof(t));
2248  snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
2249 
2250  for (x = 0; x < ast_format_cap_count(p->cap); x++) {
2252 
2253  if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) {
2254  ao2_ref(format, -1);
2255  continue;
2256  }
2257 
2258  ast_debug(1, "Answering with capability %s\n", ast_format_get_name(format));
2259  codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, format, 0);
2260  if (codec > -1) {
2261  snprintf(costr, sizeof(costr), " %d", codec);
2262  strncat(m, costr, sizeof(m) - strlen(m) - 1);
2263  snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
2264  strncat(a, costr, sizeof(a) - strlen(a) - 1);
2265  }
2266 
2267  ao2_ref(format, -1);
2268  }
2269 
2270  for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
2271  if (p->nonCodecCapability & x) {
2272  ast_debug(1, "Answering with non-codec capability %d\n", (int) x);
2274  if (codec > -1) {
2275  snprintf(costr, sizeof(costr), " %d", codec);
2276  strncat(m, costr, sizeof(m) - strlen(m) - 1);
2277  snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, NULL, x, 0));
2278  strncat(a, costr, sizeof(a) - strlen(a) - 1);
2279  if (x == AST_RTP_DTMF) {
2280  /* Indicate we support DTMF... Not sure about 16,
2281  but MSN supports it so dang it, we will too... */
2282  snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
2283  strncat(a, costr, sizeof(a) - strlen(a) - 1);
2284  }
2285  }
2286  }
2287  }
2288  strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
2289  len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
2290  snprintf(costr, sizeof(costr), "%d", len);
2291  add_line(resp, v);
2292  add_line(resp, o);
2293  add_line(resp, s);
2294  add_line(resp, c);
2295  add_line(resp, t);
2296  add_line(resp, m);
2297  add_line(resp, a);
2298  return 0;
2299 }
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:727
#define LOG_WARNING
Definition: logger.h:274
Definition of a media format.
Definition: format.c:43
struct sockaddr_in tmpdest
Definition: chan_mgcp.c:309
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
static struct test_val c
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
#define AST_RTP_MAX
Definition: rtp_engine.h:272
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct in_addr ourip
Definition: chan_mgcp.c:405
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const struct ast_format *format, int code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:1992
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code)
Retrieve a rx mapped payload type based on whether it is an Asterisk format and the code...
Definition: rtp_engine.c:1873
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int nonCodecCapability
Definition: chan_mgcp.c:375
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:643
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:769
static int add_line(struct mgcp_request *req, char *line)
Definition: chan_mgcp.c:2087
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
#define AST_RTP_DTMF
Definition: rtp_engine.h:266
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192
static struct test_val a

◆ add_var()

static struct ast_variable * add_var ( const char *  buf,
struct ast_variable list 
)
static

Definition at line 4651 of file chan_mgcp.c.

References ast_strdupa, ast_variable_new, ast_variable::next, and NULL.

Referenced by build_gateway().

4652 {
4653  struct ast_variable *tmpvar = NULL;
4654  char *varname = ast_strdupa(buf), *varval = NULL;
4655 
4656  if ((varval = strchr(varname, '='))) {
4657  *varval++ = '\0';
4658  if ((tmpvar = ast_variable_new(varname, varval, ""))) {
4659  tmpvar->next = list;
4660  list = tmpvar;
4661  }
4662  }
4663  return list;
4664 }
struct ast_variable * next
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Structure for variables, used for configurations and for channel variables.
#define NULL
Definition: resample.c:96
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_variable_new(name, value, filename)

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 5025 of file chan_mgcp.c.

◆ attempt_transfer()

static int attempt_transfer ( struct mgcp_endpoint p,
struct mgcp_subchannel sub 
)
static

Complete an attended transfer.

Parameters
pThe endpoint performing the attended transfer
subThe sub-channel completing the attended transfer
Note
p->sub is the currently active sub-channel (the channel the phone is using)
p->sub->next is the sub-channel not in use, potentially on hold
Return values
0when channel should be hung up
1when channel should not be hung up

Definition at line 3281 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridge_transfer_attended(), AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_softhangup_internal_flag_add(), AST_CONTROL_RINGING, ast_mutex_lock, ast_mutex_unlock, ast_queue_control(), ast_queue_unhold(), AST_SOFTHANGUP_DEV, AST_STATE_RINGING, mgcp_subchannel::lock, mgcp_queue_hangup(), mgcp_subchannel::next, mgcp_subchannel::owner, sub, mgcp_endpoint::sub, and unalloc_sub().

Referenced by handle_request().

3282 {
3283  enum ast_transfer_result res;
3284 
3285  /* Ensure that the other channel goes off hold and that it is indicating properly */
3286  ast_queue_unhold(sub->next->owner);
3287  if (ast_channel_state(sub->owner) == AST_STATE_RINGING) {
3289  }
3290 
3291  ast_mutex_unlock(&p->sub->next->lock);
3292  ast_mutex_unlock(&p->sub->lock);
3293  res = ast_bridge_transfer_attended(sub->owner, sub->next->owner);
3294 
3295  /* Subs are only freed when the endpoint itself is destroyed, so they will continue to exist
3296  * after ast_bridge_transfer_attended returns making this safe without reference counting
3297  */
3298  ast_mutex_lock(&p->sub->lock);
3299  ast_mutex_lock(&p->sub->next->lock);
3300 
3301  if (res != AST_BRIDGE_TRANSFER_SUCCESS) {
3302  /* If transferring fails hang up the other channel if present and us */
3303  if (sub->next->owner) {
3305  mgcp_queue_hangup(sub->next);
3306  }
3307  sub->next->alreadygone = 1;
3308  return 0;
3309  }
3310 
3311  unalloc_sub(sub->next);
3312 
3313  /* If the active sub is NOT the one completing the transfer change it to be, and hang up the other sub */
3314  if (p->sub != sub) {
3315  p->sub = sub;
3316  return 1;
3317  }
3318 
3319  return 0;
3320 }
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4729
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
static int unalloc_sub(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:506
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:621
ast_mutex_t lock
Definition: chan_mgcp.c:304
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define ast_mutex_lock(a)
Definition: lock.h:187
ast_transfer_result
Definition: bridge.h:1115
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
struct ast_channel * owner
Definition: chan_mgcp.c:306
struct stasis_forward * sub
Definition: res_corosync.c:240
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ build_gateway()

static struct mgcp_gateway * build_gateway ( char *  cat,
struct ast_variable v 
)
static

build_gateway: parse mgcp.conf and create gateway/endpoint structures

Definition at line 4016 of file chan_mgcp.c.

References __ourip, accountcode, mgcp_endpoint::accountcode, add_var(), mgcp_gateway::addr, adsi, mgcp_endpoint::adsi, amaflags, mgcp_endpoint::amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_channel_string2amaflag(), ast_copy_string(), ast_format_cap_alloc, ast_format_cap_append_from_cap(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_free, ast_get_group(), ast_get_ip(), ast_log, AST_MEDIA_TYPE_UNKNOWN, ast_mutex_destroy, ast_mutex_init, ast_mwi_subscribe_pool(), ast_ouraddrfor(), ast_random(), AST_SCHED_DEL, ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_strlen_zero, ast_true(), ast_variables_destroy(), ast_verb, mgcp_endpoint::callgroup, callreturn, mgcp_endpoint::callreturn, callwaiting, mgcp_endpoint::callwaiting, cancallforward, mgcp_endpoint::cancallforward, mgcp_endpoint::cap, mgcp_endpoint::chanvars, cid_name, mgcp_endpoint::cid_name, cid_num, mgcp_endpoint::cid_num, mgcp_endpoint::cmd_queue_lock, context, mgcp_endpoint::context, copy_vars(), cur_callergroup, cur_pickupgroup, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, mgcp_gateway::defaddr, DEFAULT_MGCP_GW_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, DIRECTMEDIA, directmedia, mgcp_endpoint::directmedia, dtmfmode, mgcp_endpoint::dtmfmode, mgcp_gateway::dynamic, mgcp_gateway::endpoints, mgcp_gateway::expire, mgcp_subchannel::gate, gateways, mgcp_gateway::ha, hangupongateremove, mgcp_endpoint::hangupongateremove, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, mgcp_subchannel::id, immediate, mgcp_endpoint::immediate, INADDR_NONE, mgcp_gateway::isnamedottedip, language, mgcp_endpoint::language, ast_variable::lineno, mgcp_subchannel::lock, mgcp_endpoint::lock, LOG_ERROR, LOG_WARNING, mgcp_subchannel::magic, mailbox, mgcp_endpoint::mailbox, MAX_SUBS, MGCP_CX_INACTIVE, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_gateway::msgs_lock, mgcp_endpoint::msgstate, musicclass, mgcp_endpoint::musicclass, mgcp_endpoint::mwi_event_sub, ast_variable::name, mgcp_endpoint::name, mgcp_gateway::name, nat, mgcp_subchannel::nat, ncs, mgcp_endpoint::ncs, mgcp_endpoint::needaudit, ast_variable::next, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::next, NULL, mgcp_endpoint::onhooktime, mgcp_gateway::ourip, mgcp_subchannel::parent, mgcp_endpoint::parent, parkinglot, mgcp_endpoint::parkinglot, mgcp_endpoint::pickupgroup, pktcgatealloc, mgcp_endpoint::pktcgatealloc, mgcp_gateway::realtime, mgcp_gateway::retransid, mgcp_endpoint::rqnt_ident, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, singlepath, mgcp_endpoint::singlepath, slowsequence, mgcp_endpoint::slowsequence, stasis_subscription_cb_noop(), sub, mgcp_endpoint::sub, threewaycalling, mgcp_endpoint::threewaycalling, transfer, mgcp_endpoint::transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, and mgcp_gateway::wcardep.

Referenced by find_realtime_gw(), and reload_config().

4017 {
4018  struct mgcp_gateway *gw;
4019  struct mgcp_endpoint *e;
4020  struct mgcp_subchannel *sub;
4021  struct ast_variable *chanvars = NULL;
4022 
4023  /*char txident[80];*/
4024  int i=0, y=0;
4025  int gw_reload = 0;
4026  int ep_reload = 0;
4028 
4029  /* locate existing gateway */
4030  for (gw = gateways; gw; gw = gw->next) {
4031  if (!strcasecmp(cat, gw->name)) {
4032  /* gateway already exists */
4033  gw->delme = 0;
4034  gw_reload = 1;
4035  break;
4036  }
4037  }
4038 
4039  if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) {
4040  return NULL;
4041  }
4042 
4043  if (!gw_reload) {
4044  gw->expire = -1;
4045  gw->realtime = 0;
4046  gw->retransid = -1;
4047  ast_mutex_init(&gw->msgs_lock);
4048  ast_copy_string(gw->name, cat, sizeof(gw->name));
4049  /* check if the name is numeric ip */
4050  if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
4051  gw->isnamedottedip = 1;
4052  }
4053  for (; v; v = v->next) {
4054  if (!strcasecmp(v->name, "host")) {
4055  if (!strcasecmp(v->value, "dynamic")) {
4056  /* They'll register with us */
4057  gw->dynamic = 1;
4058  memset(&gw->addr.sin_addr, 0, 4);
4059  if (gw->addr.sin_port) {
4060  /* If we've already got a port, make it the default rather than absolute */
4061  gw->defaddr.sin_port = gw->addr.sin_port;
4062  gw->addr.sin_port = 0;
4063  }
4064  } else {
4065  /* Non-dynamic. Make sure we become that way if we're not */
4066  AST_SCHED_DEL(sched, gw->expire);
4067  gw->dynamic = 0;
4068  {
4069  struct ast_sockaddr tmp;
4070 
4071  ast_sockaddr_from_sin(&tmp, &gw->addr);
4072  if (ast_get_ip(&tmp, v->value)) {
4073  if (!gw_reload) {
4075  ast_free(gw);
4076  }
4077  return NULL;
4078  }
4079  ast_sockaddr_to_sin(&tmp, &gw->addr);
4080  }
4081  }
4082  } else if (!strcasecmp(v->name, "defaultip")) {
4083  struct ast_sockaddr tmp;
4084 
4086  if (ast_get_ip(&tmp, v->value)) {
4087  if (!gw_reload) {
4089  ast_free(gw);
4090  }
4091  return NULL;
4092  }
4094  } else if (!strcasecmp(v->name, "permit") ||
4095  !strcasecmp(v->name, "deny")) {
4096  int acl_error = 0;
4097  gw->ha = ast_append_ha(v->name, v->value, gw->ha, &acl_error);
4098  if (acl_error) {
4099  ast_log(LOG_ERROR, "Invalid ACL '%s' specified for MGCP gateway '%s' on line %d. Not creating.\n",
4100  v->value, cat, v->lineno);
4101  if (!gw_reload) {
4103  ast_free(gw);
4104  } else {
4105  gw->delme = 1;
4106  }
4107  return NULL;
4108  }
4109  } else if (!strcasecmp(v->name, "port")) {
4110  gw->addr.sin_port = htons(atoi(v->value));
4111  } else if (!strcasecmp(v->name, "context")) {
4112  ast_copy_string(context, v->value, sizeof(context));
4113  } else if (!strcasecmp(v->name, "dtmfmode")) {
4114  if (!strcasecmp(v->value, "inband"))
4116  else if (!strcasecmp(v->value, "rfc2833"))
4118  else if (!strcasecmp(v->value, "hybrid"))
4120  else if (!strcasecmp(v->value, "none"))
4121  dtmfmode = 0;
4122  else
4123  ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
4124  } else if (!strcasecmp(v->name, "nat")) {
4125  nat = ast_true(v->value);
4126  } else if (!strcasecmp(v->name, "ncs")) {
4127  ncs = ast_true(v->value);
4128  } else if (!strcasecmp(v->name, "hangupongateremove")) {
4130  } else if (!strcasecmp(v->name, "pktcgatealloc")) {
4132  } else if (!strcasecmp(v->name, "callerid")) {
4133  if (!strcasecmp(v->value, "asreceived")) {
4134  cid_num[0] = '\0';
4135  cid_name[0] = '\0';
4136  } else {
4137  ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
4138  }
4139  } else if (!strcasecmp(v->name, "language")) {
4140  ast_copy_string(language, v->value, sizeof(language));
4141  } else if (!strcasecmp(v->name, "accountcode")) {
4143  } else if (!strcasecmp(v->name, "amaflags")) {
4145  if (y < 0) {
4146  ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
4147  } else {
4148  amaflags = y;
4149  }
4150  } else if (!strcasecmp(v->name, "setvar")) {
4151  chanvars = add_var(v->value, chanvars);
4152  } else if (!strcasecmp(v->name, "clearvars")) {
4153  if (chanvars) {
4154  ast_variables_destroy(chanvars);
4155  chanvars = NULL;
4156  }
4157  } else if (!strcasecmp(v->name, "musiconhold")) {
4159  } else if (!strcasecmp(v->name, "parkinglot")) {
4161  } else if (!strcasecmp(v->name, "callgroup")) {
4163  } else if (!strcasecmp(v->name, "pickupgroup")) {
4165  } else if (!strcasecmp(v->name, "immediate")) {
4166  immediate = ast_true(v->value);
4167  } else if (!strcasecmp(v->name, "cancallforward")) {
4169  } else if (!strcasecmp(v->name, "singlepath")) {
4170  singlepath = ast_true(v->value);
4171  } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
4172  directmedia = ast_true(v->value);
4173  } else if (!strcasecmp(v->name, "mailbox")) {
4174  ast_copy_string(mailbox, v->value, sizeof(mailbox));
4175  } else if (!strcasecmp(v->name, "hasvoicemail")) {
4176  if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
4177  /*
4178  * hasvoicemail is a users.conf legacy voicemail enable method.
4179  * hasvoicemail is only going to work for app_voicemail mailboxes.
4180  */
4181  if (strchr(gw->name, '@')) {
4182  ast_copy_string(mailbox, gw->name, sizeof(mailbox));
4183  } else {
4184  snprintf(mailbox, sizeof(mailbox), "%s@default", gw->name);
4185  }
4186  }
4187  } else if (!strcasecmp(v->name, "adsi")) {
4188  adsi = ast_true(v->value);
4189  } else if (!strcasecmp(v->name, "callreturn")) {
4190  callreturn = ast_true(v->value);
4191  } else if (!strcasecmp(v->name, "callwaiting")) {
4192  callwaiting = ast_true(v->value);
4193  } else if (!strcasecmp(v->name, "slowsequence")) {
4194  slowsequence = ast_true(v->value);
4195  } else if (!strcasecmp(v->name, "transfer")) {
4196  transfer = ast_true(v->value);
4197  } else if (!strcasecmp(v->name, "threewaycalling")) {
4199  } else if (!strcasecmp(v->name, "wcardep")) {
4200  /* locate existing endpoint */
4201  for (e = gw->endpoints; e; e = e->next) {
4202  if (!strcasecmp(v->value, e->name)) {
4203  /* endpoint already exists */
4204  e->delme = 0;
4205  ep_reload = 1;
4206  break;
4207  }
4208  }
4209 
4210  if (!e) {
4211  /* Allocate wildcard endpoint */
4212  e = ast_calloc(1, sizeof(*e));
4213  ep_reload = 0;
4214  }
4215 
4216  if (e) {
4217  if (!ep_reload) {
4218  memset(e, 0, sizeof(struct mgcp_endpoint));
4219  ast_mutex_init(&e->lock);
4223  ast_copy_string(e->name, v->value, sizeof(e->name));
4224  e->needaudit = 1;
4225  }
4226  ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
4227  /* XXX Should we really check for uniqueness?? XXX */
4229  ast_copy_string(e->context, context, sizeof(e->context));
4230  ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
4231  ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
4232  ast_copy_string(e->language, language, sizeof(e->language));
4234  ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
4236  if (!ast_strlen_zero(e->mailbox)) {
4237  /* This module does not handle MWI in an event-based manner. However, it
4238  * subscribes to MWI for each mailbox that is configured so that the core
4239  * knows that we care about it. Then, chan_mgcp will get the MWI from the
4240  * event cache instead of checking the mailbox directly. */
4242  }
4243  snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", (unsigned long)ast_random());
4244  e->msgstate = -1;
4245  e->amaflags = amaflags;
4247  e->parent = gw;
4248  e->ncs = ncs;
4249  e->dtmfmode = dtmfmode;
4250  if (!ep_reload && e->sub && e->sub->rtp) {
4251  e->dtmfmode |= MGCP_DTMF_INBAND;
4252  }
4253  e->adsi = adsi;
4254  e->type = TYPE_LINE;
4255  e->immediate = immediate;
4258  e->callreturn = callreturn;
4260  e->singlepath = singlepath;
4261  e->directmedia = directmedia;
4262  e->callwaiting = callwaiting;
4265  e->transfer = transfer;
4267  e->onhooktime = time(NULL);
4268  /* ASSUME we're onhook */
4269  e->hookstate = MGCP_ONHOOK;
4270  e->chanvars = copy_vars(chanvars);
4271  if (!ep_reload) {
4272  /*snprintf(txident, sizeof(txident), "%08lx", (unsigned long)ast_random());*/
4273  for (i = 0; i < MAX_SUBS; i++) {
4274  sub = ast_calloc(1, sizeof(*sub));
4275  if (sub) {
4276  ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
4277  ast_mutex_init(&sub->lock);
4279  sub->parent = e;
4280  sub->id = i;
4281  snprintf(sub->txident, sizeof(sub->txident), "%08lx", (unsigned long)ast_random());
4282  /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/
4283  sub->cxmode = MGCP_CX_INACTIVE;
4284  sub->nat = nat;
4285  sub->gate = NULL;
4286  sub->sdpsent = 0;
4287  sub->next = e->sub;
4288  e->sub = sub;
4289  } else {
4290  /* XXX Should find a way to clean up our memory */
4291  ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
4292  return NULL;
4293  }
4294  }
4295  /* Make out subs a circular linked list so we can always sping through the whole bunch */
4296  /* find the end of the list */
4297  for (sub = e->sub; sub && sub->next; sub = sub->next);
4298  /* set the last sub->next to the first sub */
4299  sub->next = e->sub;
4300 
4301  e->next = gw->endpoints;
4302  gw->endpoints = e;
4303  }
4304  }
4305  } else if (!strcasecmp(v->name, "trunk") ||
4306  !strcasecmp(v->name, "line")) {
4307 
4308  /* locate existing endpoint */
4309  for (e = gw->endpoints; e; e = e->next) {
4310  if (!strcasecmp(v->value, e->name)) {
4311  /* endpoint already exists */
4312  e->delme = 0;
4313  ep_reload = 1;
4314  break;
4315  }
4316  }
4317 
4318  if (!e) {
4319  e = ast_calloc(1, sizeof(*e));
4320  ep_reload = 0;
4321  }
4322 
4323  if (e) {
4324  if (!ep_reload) {
4325  ast_mutex_init(&e->lock);
4329  ast_copy_string(e->name, v->value, sizeof(e->name));
4330  e->needaudit = 1;
4331  }
4332  /* XXX Should we really check for uniqueness?? XXX */
4334  ast_copy_string(e->context, context, sizeof(e->context));
4335  ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
4336  ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
4337  ast_copy_string(e->language, language, sizeof(e->language));
4339  ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
4341  if (!ast_strlen_zero(mailbox)) {
4342  ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
4343  }
4344  if (!ep_reload) {
4345  /* XXX potential issue due to reload */
4346  e->msgstate = -1;
4347  e->parent = gw;
4348  }
4349  e->amaflags = amaflags;
4351  e->dtmfmode = dtmfmode;
4352  e->ncs = ncs;
4355  e->adsi = adsi;
4356  e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE;
4357  e->immediate = immediate;
4360  e->callreturn = callreturn;
4362  e->directmedia = directmedia;
4363  e->singlepath = singlepath;
4364  e->callwaiting = callwaiting;
4367  e->transfer = transfer;
4369 
4370  /* If we already have a valid chanvars, it's not a new endpoint (it's a reload),
4371  so first, free previous mem
4372  */
4373  if (e->chanvars) {
4375  e->chanvars = NULL;
4376  }
4377  e->chanvars = copy_vars(chanvars);
4378 
4379  if (!ep_reload) {
4380  e->onhooktime = time(NULL);
4381  /* ASSUME we're onhook */
4382  e->hookstate = MGCP_ONHOOK;
4383  snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", (unsigned long)ast_random());
4384  }
4385 
4386  for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
4387  if (!ep_reload) {
4388  sub = ast_calloc(1, sizeof(*sub));
4389  } else {
4390  if (!sub) {
4391  sub = e->sub;
4392  } else {
4393  sub = sub->next;
4394  }
4395  }
4396 
4397  if (sub) {
4398  if (!ep_reload) {
4399  ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
4400  ast_mutex_init(&sub->lock);
4402  ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
4403  sub->parent = e;
4404  sub->id = i;
4405  snprintf(sub->txident, sizeof(sub->txident), "%08lx", (unsigned long)ast_random());
4406  sub->cxmode = MGCP_CX_INACTIVE;
4407  sub->next = e->sub;
4408  e->sub = sub;
4409  }
4410  sub->nat = nat;
4411  } else {
4412  /* XXX Should find a way to clean up our memory */
4413  ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
4414  return NULL;
4415  }
4416  }
4417  if (!ep_reload) {
4418  /* Make out subs a circular linked list so we can always sping through the whole bunch */
4419  /* find the end of the list */
4420  for (sub = e->sub; sub && sub->next; sub = sub->next);
4421  /* set the last sub->next to the first sub */
4422  sub->next = e->sub;
4423 
4424  e->next = gw->endpoints;
4425  gw->endpoints = e;
4426  }
4427  }
4428  } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) {
4429  /* just eliminate realtime warnings */
4430  } else {
4431  ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
4432  }
4433  }
4434  if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
4435  ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
4436  if (!gw_reload) {
4438  ast_free(gw);
4439  }
4440 
4441  /* Return NULL */
4442  gw_reload = 1;
4443  } else {
4444  gw->defaddr.sin_family = AF_INET;
4445  gw->addr.sin_family = AF_INET;
4446  if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) {
4447  gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
4448  }
4449  if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) {
4450  gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
4451  }
4452  {
4453  struct ast_sockaddr tmp1, tmp2;
4454  struct sockaddr_in tmp3 = {0,};
4455 
4456  tmp3.sin_addr = gw->ourip;
4457  ast_sockaddr_from_sin(&tmp1, &gw->addr);
4458  ast_sockaddr_from_sin(&tmp2, &tmp3);
4459  if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) {
4460  memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
4461  } else {
4462  ast_sockaddr_to_sin(&tmp2, &tmp3);
4463  gw->ourip = tmp3.sin_addr;
4464  }
4465  }
4466  }
4467 
4468  if (chanvars) {
4469  ast_variables_destroy(chanvars);
4470  chanvars = NULL;
4471  }
4472  return (gw_reload ? NULL : gw);
4473 }
static char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:162
struct ast_variable * next
#define TYPE_LINE
Definition: chan_mgcp.c:330
static int adsi
Definition: chan_mgcp.c:208
static int slowsequence
Definition: chan_mgcp.c:189
struct cops_gate * gate
Definition: chan_mgcp.c:322
static int dtmfmode
Definition: chan_mgcp.c:167
struct ast_mwi_subscriber * mwi_event_sub
Definition: chan_mgcp.c:349
char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:340
static ast_group_t cur_pickupgroup
Definition: chan_mgcp.c:174
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:163
char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:341
int hascallwaiting
Definition: chan_mgcp.c:353
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1092
#define TYPE_TRUNK
Definition: chan_mgcp.c:329
ast_mutex_t cmd_queue_lock
Definition: chan_mgcp.c:385
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
int slowsequence
Definition: chan_mgcp.c:369
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
#define MAX_SUBS
Definition: chan_mgcp.c:291
#define DEFAULT_MGCP_GW_PORT
Definition: chan_mgcp.c:123
static int callwaiting
Definition: chan_mgcp.c:185
char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:345
#define MGCP_DTMF_RFC2833
Definition: chan_mgcp.c:119
#define LOG_WARNING
Definition: logger.h:274
static int nat
Definition: chan_mgcp.c:168
static struct ast_format_cap * global_capability
Definition: chan_mgcp.c:235
static int tmp()
Definition: bt_open.c:389
Structure for variables, used for configurations and for channel variables.
int cancallforward
Definition: chan_mgcp.c:357
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:120
Definition: sched.c:76
ast_mutex_t lock
Definition: chan_mgcp.c:304
static int callreturn
Definition: chan_mgcp.c:187
ast_group_t pickupgroup
Definition: chan_mgcp.c:351
char rqnt_ident[80]
Definition: chan_mgcp.c:381
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
#define NULL
Definition: resample.c:96
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
Socket address structure.
Definition: netsock2.h:97
ast_mutex_t msgs_lock
Definition: chan_mgcp.c:418
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
#define ast_verb(level,...)
Definition: logger.h:463
static int transfer
Definition: chan_mgcp.c:194
static int threewaycalling
Definition: chan_mgcp.c:191
#define ast_strlen_zero(foo)
Definition: strings.h:52
int hangupongateremove
Definition: chan_mgcp.c:367
static int cancallforward
Definition: chan_mgcp.c:196
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4405
char language[MAX_LANGUAGE]
Definition: chan_mgcp.c:339
char wcardep[30]
Definition: chan_mgcp.c:416
char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:348
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
Definition: acl.c:1005
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: chan_mgcp.c:334
static int immediate
Definition: chan_mgcp.c:183
struct in_addr ourip
Definition: chan_mgcp.c:405
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:782
struct sockaddr_in defaddr
Definition: chan_mgcp.c:404
struct ast_variable * chanvars
Definition: chan_mgcp.c:394
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
#define MGCP_DTMF_HYBRID
Definition: chan_mgcp.c:121
long int ast_random(void)
Definition: main/utils.c:2064
static int amaflags
Definition: chan_mgcp.c:206
char name[80]
Definition: chan_mgcp.c:401
#define DIRECTMEDIA
Definition: chan_mgcp.c:98
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7718
int isnamedottedip
Definition: chan_mgcp.c:402
char context[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:338
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
ast_group_t callgroup
Definition: chan_mgcp.c:350
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_mgcp.c:336
int threewaycalling
Definition: chan_mgcp.c:355
static char language[MAX_LANGUAGE]
Definition: chan_mgcp.c:161
static struct ast_variable * add_var(const char *buf, struct ast_variable *list)
Definition: chan_mgcp.c:4651
#define LOG_ERROR
Definition: logger.h:285
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
ast_mutex_t cx_queue_lock
Definition: chan_mgcp.c:316
int pktcgatealloc
Definition: chan_mgcp.c:366
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
#define INADDR_NONE
Definition: chan_mgcp.c:101
ast_mutex_t lock
Definition: chan_mgcp.c:333
static int singlepath
Definition: chan_mgcp.c:198
struct sockaddr_in addr
Definition: chan_mgcp.c:403
static int ncs
Definition: chan_mgcp.c:169
int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
Get the IP address given a hostname.
Definition: acl.c:1000
void stasis_subscription_cb_noop(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Stasis subscription callback function that does nothing.
Definition: stasis.c:811
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
ast_mutex_t rqnt_queue_lock
Definition: chan_mgcp.c:383
static ast_group_t cur_callergroup
Definition: chan_mgcp.c:173
struct ast_ha * ha
Definition: chan_mgcp.c:409
char txident[80]
Definition: chan_mgcp.c:310
static int pktcgatealloc
Definition: chan_mgcp.c:170
static struct mgcp_gateway * gateways
char magic[6]
Definition: chan_mgcp.c:303
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
static int directmedia
Definition: chan_mgcp.c:200
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_mgcp.c:202
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static struct ast_variable * copy_vars(struct ast_variable *src)
duplicate a list of channel variables,
Definition: chan_mgcp.c:4669
static int hangupongateremove
Definition: chan_mgcp.c:171
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:159
struct stasis_forward * sub
Definition: res_corosync.c:240
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
Definition: acl.c:713
#define MGCP_CX_INACTIVE
Definition: chan_mgcp.c:136
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:769
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
#define ast_mutex_init(pmutex)
Definition: lock.h:184
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
#define ast_mutex_destroy(a)
Definition: lock.h:186
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
#define MGCP_SUBCHANNEL_MAGIC
Definition: chan_mgcp.c:302
static struct in_addr __ourip
Definition: chan_mgcp.c:239
char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:347
struct ast_mwi_subscriber * ast_mwi_subscribe_pool(const char *mailbox, stasis_subscription_cb callback, void *data)
Add an MWI state subscriber, and stasis subscription to the mailbox.
Definition: mwi.c:230

◆ control2str()

static char* control2str ( int  ind)
static

Definition at line 1406 of file chan_mgcp.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_TAKEOFFHOOK, and AST_CONTROL_WINK.

Referenced by mgcp_indicate().

1406  {
1407  switch (ind) {
1408  case AST_CONTROL_HANGUP:
1409  return "Other end has hungup";
1410  case AST_CONTROL_RING:
1411  return "Local ring";
1412  case AST_CONTROL_RINGING:
1413  return "Remote end is ringing";
1414  case AST_CONTROL_ANSWER:
1415  return "Remote end has answered";
1416  case AST_CONTROL_BUSY:
1417  return "Remote end is busy";
1419  return "Make it go off hook";
1420  case AST_CONTROL_OFFHOOK:
1421  return "Line is off hook";
1423  return "Congestion (circuits busy)";
1424  case AST_CONTROL_FLASH:
1425  return "Flash hook";
1426  case AST_CONTROL_WINK:
1427  return "Wink";
1428  case AST_CONTROL_OPTION:
1429  return "Set a low-level option";
1430  case AST_CONTROL_RADIO_KEY:
1431  return "Key Radio";
1433  return "Un-Key Radio";
1434  }
1435  return "UNKNOWN";
1436 }

◆ copy_vars()

static struct ast_variable * copy_vars ( struct ast_variable src)
static

duplicate a list of channel variables,

Returns
the copy.

Definition at line 4669 of file chan_mgcp.c.

References ast_variable_new, ast_variable::next, NULL, and tmp().

Referenced by build_gateway().

4670 {
4671  struct ast_variable *res = NULL, *tmp, *v = NULL;
4672 
4673  for (v = src ; v ; v = v->next) {
4674  if ((tmp = ast_variable_new(v->name, v->value, v->file))) {
4675  tmp->next = res;
4676  res = tmp;
4677  }
4678  }
4679  return res;
4680 }
struct ast_variable * next
static int tmp()
Definition: bt_open.c:389
Structure for variables, used for configurations and for channel variables.
#define NULL
Definition: resample.c:96
#define ast_variable_new(name, value, filename)

◆ destroy_endpoint()

static void destroy_endpoint ( struct mgcp_endpoint e)
static

Definition at line 4539 of file chan_mgcp.c.

References ao2_ref, ast_dsp_free(), ast_free, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_mwi_unsubscribe(), ast_rtp_instance_destroy(), ast_strlen_zero, ast_variables_destroy(), mgcp_endpoint::cap, mgcp_endpoint::chanvars, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cxident, mgcp_endpoint::dsp, dump_cmd_queues(), dump_queue(), mgcp_subchannel::gate, cops_gate::gate_open, cops_gate::gate_remove, cops_gate::got_dq_gi, mgcp_subchannel::lock, mgcp_endpoint::lock, mgcp_subchannel::magic, MAX_SUBS, mgcp_queue_hangup(), mgcp_endpoint::mwi_event_sub, mgcp_subchannel::next, NULL, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, sub, mgcp_endpoint::sub, cops_gate::tech_pvt, and transmit_connection_del().

Referenced by prune_gateways().

4540 {
4541  struct mgcp_subchannel *sub = e->sub->next, *s;
4542  int i;
4543 
4544  for (i = 0; i < MAX_SUBS; i++) {
4545  ast_mutex_lock(&sub->lock);
4546  if (!ast_strlen_zero(sub->cxident)) {
4548  }
4549  if (sub->rtp) {
4551  sub->rtp = NULL;
4552  }
4553  memset(sub->magic, 0, sizeof(sub->magic));
4554  mgcp_queue_hangup(sub);
4555  dump_cmd_queues(NULL, sub);
4556  if(sub->gate) {
4557  sub->gate->tech_pvt = NULL;
4558  sub->gate->got_dq_gi = NULL;
4559  sub->gate->gate_remove = NULL;
4560  sub->gate->gate_open = NULL;
4561  }
4562  ast_mutex_unlock(&sub->lock);
4563  sub = sub->next;
4564  }
4565 
4566  if (e->dsp) {
4567  ast_dsp_free(e->dsp);
4568  }
4569 
4570  dump_queue(e->parent, e);
4571  dump_cmd_queues(e, NULL);
4572 
4573  sub = e->sub;
4574  for (i = 0; (i < MAX_SUBS) && sub; i++) {
4575  s = sub;
4576  sub = sub->next;
4577  ast_mutex_destroy(&s->lock);
4578  ast_mutex_destroy(&s->cx_queue_lock);
4579  ast_free(s);
4580  }
4581 
4582  if (e->mwi_event_sub) {
4584  }
4585 
4586  if (e->chanvars) {
4588  e->chanvars = NULL;
4589  }
4590 
4591  ast_mutex_destroy(&e->lock);
4594  ao2_ref(e->cap, -1);
4595  ast_free(e);
4596 }
struct cops_gate * gate
Definition: chan_mgcp.c:322
struct ast_mwi_subscriber * mwi_event_sub
Definition: chan_mgcp.c:349
void * ast_mwi_unsubscribe(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic and MWI.
Definition: mwi.c:249
ast_mutex_t cmd_queue_lock
Definition: chan_mgcp.c:385
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
#define MAX_SUBS
Definition: chan_mgcp.c:291
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:621
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
void * tech_pvt
Definition: pktccops.h:67
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
struct ast_variable * chanvars
Definition: chan_mgcp.c:394
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int transmit_connection_del(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2690
struct ast_dsp * dsp
Definition: chan_mgcp.c:388
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
ast_mutex_t lock
Definition: chan_mgcp.c:333
int(* gate_open)(struct cops_gate *gate)
Definition: pktccops.h:66
char cxident[80]
Definition: chan_mgcp.c:312
#define ast_free(a)
Definition: astmm.h:182
ast_mutex_t rqnt_queue_lock
Definition: chan_mgcp.c:383
int(* gate_remove)(struct cops_gate *gate)
Definition: pktccops.h:65
char magic[6]
Definition: chan_mgcp.c:303
static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
dump_cmd_queues: (SC:) cleanup pending commands
Definition: chan_mgcp.c:2734
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:458
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct stasis_forward * sub
Definition: res_corosync.c:240
#define ast_mutex_destroy(a)
Definition: lock.h:186
static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
Definition: chan_mgcp.c:570
int(* got_dq_gi)(struct cops_gate *gate)
Definition: pktccops.h:64
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ destroy_gateway()

static void destroy_gateway ( struct mgcp_gateway g)
static

Definition at line 4598 of file chan_mgcp.c.

References ast_free, ast_free_ha(), dump_queue(), mgcp_gateway::ha, and NULL.

Referenced by prune_gateways().

4599 {
4600  if (g->ha)
4601  ast_free_ha(g->ha);
4602 
4603  dump_queue(g, NULL);
4604 
4605  ast_free(g);
4606 }
#define NULL
Definition: resample.c:96
#define ast_free(a)
Definition: astmm.h:182
struct ast_ha * ha
Definition: chan_mgcp.c:409
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
Definition: chan_mgcp.c:570

◆ do_monitor()

static void* do_monitor ( void *  data)
static

Definition at line 3818 of file chan_mgcp.c.

References ast_free, ast_io_add(), AST_IO_IN, ast_io_wait(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_sched_runq(), ast_sched_wait(), ast_verb, mgcp_gateway::endpoints, gatelock, gateways, has_voicemail(), MGCP_ONHOOK, mgcp_prune_realtime_gateway(), mgcp_reload_lock, mgcp_reloading, mgcpsock, mgcpsock_read(), mgcpsock_read_id, monlock, mgcp_gateway::msgs_lock, netlock, mgcp_gateway::next, NULL, mgcp_gateway::realtime, reload_config(), transmit_notify_request(), and TYPE_LINE.

Referenced by restart_monitor().

3819 {
3820  int res;
3821  int reloading;
3822  struct mgcp_gateway *g, *gprev;
3823  /*struct mgcp_gateway *g;*/
3824  /*struct mgcp_endpoint *e;*/
3825  /*time_t thispass = 0, lastpass = 0;*/
3826  time_t lastrun = 0;
3827 
3828  /* Add an I/O event to our UDP socket */
3829  if (mgcpsock > -1) {
3831  }
3832  /* This thread monitors all the frame relay interfaces which are not yet in use
3833  (and thus do not have a separate thread) indefinitely */
3834  /* From here on out, we die whenever asked */
3835  for (;;) {
3836  /* Check for a reload request */
3838  reloading = mgcp_reloading;
3839  mgcp_reloading = 0;
3841  if (reloading) {
3842  ast_verb(1, "Reloading MGCP\n");
3843  reload_config(1);
3844  /* Add an I/O event to our UDP socket */
3845  if (mgcpsock > -1 && !mgcpsock_read_id) {
3847  }
3848  }
3849 
3850  /* Check for interfaces needing to be killed */
3851  /* Don't let anybody kill us right away. Nobody should lock the interface list
3852  and wait for the monitor list, but the other way around is okay. */
3854  /* Lock the network interface */
3856 
3857 #if 0
3858  /* XXX THIS IS COMPLETELY HOSED */
3859  /* The gateway goes into a state of panic */
3860  /* If the vmwi indicator is sent while it is reseting interfaces */
3861  lastpass = thispass;
3862  thispass = time(NULL);
3863  g = gateways;
3864  while(g) {
3865  if (thispass != lastpass) {
3866  e = g->endpoints;
3867  while(e) {
3868  if (e->type == TYPE_LINE) {
3869  res = has_voicemail(e);
3870  if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
3871  if (res) {
3872  transmit_notify_request(e, "L/vmwi(+)");
3873  } else {
3874  transmit_notify_request(e, "L/vmwi(-)");
3875  }
3876  e->msgstate = res;
3877  e->onhooktime = thispass;
3878  }
3879  }
3880  e = e->next;
3881  }
3882  }
3883  g = g->next;
3884  }
3885 #endif
3886  /* pruning unused realtime gateways, running in every 60 seconds*/
3887  if(time(NULL) > (lastrun + 60)) {
3889  g = gateways;
3890  gprev = NULL;
3891  while(g) {
3892  if(g->realtime) {
3894  if(gprev) {
3895  gprev->next = g->next;
3896  } else {
3897  gateways = g->next;
3898  }
3901  ast_free(g);
3902  } else {
3904  gprev = g;
3905  }
3906  } else {
3907  gprev = g;
3908  }
3909  g = g->next;
3910  }
3912  lastrun = time(NULL);
3913  }
3914  /* Okay, now that we know what to do, release the network lock */
3916  /* And from now on, we're okay to be killed, so release the monitor lock as well */
3918  pthread_testcancel();
3919  /* Wait for sched or io */
3920  res = ast_sched_wait(sched);
3921  /* copied from chan_sip.c */
3922  if ((res < 0) || (res > 1000)) {
3923  res = 1000;
3924  }
3925  res = ast_io_wait(io, res);
3927  if (res >= 0) {
3929  }
3931  }
3932  /* Never reached */
3933  return NULL;
3934 }
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:278
#define TYPE_LINE
Definition: chan_mgcp.c:330
static int mgcpsock
Definition: chan_mgcp.c:432
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:430
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
static int * mgcpsock_read_id
Definition: chan_mgcp.c:3758
#define AST_IO_IN
Definition: io.h:34
Definition: sched.c:76
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
Definition: io.c:162
#define ast_mutex_lock(a)
Definition: lock.h:187
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
#define NULL
Definition: resample.c:96
ast_mutex_t msgs_lock
Definition: chan_mgcp.c:418
#define ast_verb(level,...)
Definition: logger.h:463
static ast_mutex_t netlock
Definition: chan_mgcp.c:224
static int mgcp_prune_realtime_gateway(struct mgcp_gateway *g)
Definition: chan_mgcp.c:3760
static int reload_config(int reload)
Definition: chan_mgcp.c:4683
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
static struct io_context * io
Definition: chan_mgcp.c:245
static ast_mutex_t monlock
Definition: chan_mgcp.c:226
static int mgcp_reloading
Definition: chan_mgcp.c:427
#define ast_free(a)
Definition: astmm.h:182
static struct mgcp_gateway * gateways
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
static int has_voicemail(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:490
static ast_mutex_t mgcp_reload_lock
Definition: chan_mgcp.c:426
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:431
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
#define ast_mutex_destroy(a)
Definition: lock.h:186
static int mgcpsock_read(int *id, int fd, short events, void *ignore)
Definition: chan_mgcp.c:3669
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ dump_cmd_queues()

static void dump_cmd_queues ( struct mgcp_endpoint p,
struct mgcp_subchannel sub 
)
static

dump_cmd_queues: (SC:) cleanup pending commands

Definition at line 2734 of file chan_mgcp.c.

References ast_free, ast_mutex_lock, ast_mutex_unlock, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_request::next, mgcp_subchannel::next, NULL, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::sub.

Referenced by destroy_endpoint(), handle_request(), handle_response(), and unalloc_sub().

2735 {
2736  struct mgcp_request *t, *q;
2737 
2738  if (p) {
2740  for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
2741  p->rqnt_queue = NULL;
2743 
2745  for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
2746  p->cmd_queue = NULL;
2748 
2750  for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
2751  p->sub->cx_queue = NULL;
2753 
2755  for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
2756  p->sub->next->cx_queue = NULL;
2758  } else if (sub) {
2760  for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
2761  sub->cx_queue = NULL;
2763  }
2764 }
struct mgcp_request * cx_queue
Definition: chan_mgcp.c:315
ast_mutex_t cmd_queue_lock
Definition: chan_mgcp.c:385
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
struct mgcp_request * next
Definition: chan_mgcp.c:266
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
struct mgcp_request * rqnt_queue
Definition: chan_mgcp.c:382
ast_mutex_t cx_queue_lock
Definition: chan_mgcp.c:316
#define ast_free(a)
Definition: astmm.h:182
ast_mutex_t rqnt_queue_lock
Definition: chan_mgcp.c:383
struct mgcp_request * cmd_queue
Definition: chan_mgcp.c:384
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ dump_queue()

static void dump_queue ( struct mgcp_gateway gw,
struct mgcp_endpoint p 
)
static

Definition at line 570 of file chan_mgcp.c.

References ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, LOG_NOTICE, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, NULL, mgcp_message::owner_ep, and mgcp_message::seqno.

Referenced by destroy_endpoint(), destroy_gateway(), and handle_request().

571 {
572  struct mgcp_message *cur, *q = NULL, *w, *prev;
573 
575  for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
576  if (!p || cur->owner_ep == p) {
577  if (prev) {
578  prev->next = cur->next;
579  } else {
580  gw->msgs = cur->next;
581  }
582 
583  ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
584  gw->name, cur->seqno);
585 
586  w = cur;
587  if (q) {
588  w->next = q;
589  } else {
590  w->next = NULL;
591  }
592  q = w;
593  }
594  }
596 
597  while (q) {
598  cur = q;
599  q = q->next;
600  ast_free(cur);
601  }
602 }
struct mgcp_endpoint * owner_ep
Definition: chan_mgcp.c:271
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
ast_mutex_t msgs_lock
Definition: chan_mgcp.c:418
mgcp_message: MGCP message for queuing up
Definition: chan_mgcp.c:270
#define ast_log
Definition: astobj2.c:42
struct mgcp_message * msgs
Definition: chan_mgcp.c:417
char name[80]
Definition: chan_mgcp.c:401
#define LOG_NOTICE
Definition: logger.h:263
#define ast_free(a)
Definition: astmm.h:182
struct mgcp_message * next
Definition: chan_mgcp.c:277
unsigned int seqno
Definition: chan_mgcp.c:275
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ find_and_retrans()

static int find_and_retrans ( struct mgcp_subchannel sub,
struct mgcp_request req 
)
static

Definition at line 3639 of file chan_mgcp.c.

References answer(), ast_free, mgcp_request::identifier, mgcp_response::next, NULL, mgcp_subchannel::parent, mgcp_endpoint::parent, resend_response(), RESPONSE_TIMEOUT, and mgcp_gateway::responses.

Referenced by mgcpsock_read().

3640 {
3641  int seqno=0;
3642  time_t now;
3643  struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL;
3644  time(&now);
3645  if (sscanf(req->identifier, "%30d", &seqno) != 1) {
3646  seqno = 0;
3647  }
3648  for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) {
3649  if (now - cur->whensent > RESPONSE_TIMEOUT) {
3650  /* Delete this entry */
3651  if (prev)
3652  prev->next = next;
3653  else
3654  sub->parent->parent->responses = next;
3655  ast_free(cur);
3656  } else {
3657  if (seqno == cur->seqno)
3658  answer = cur;
3659  prev = cur;
3660  }
3661  }
3662  if (answer) {
3663  resend_response(sub, answer);
3664  return 1;
3665  }
3666  return 0;
3667 }
char * identifier
Definition: chan_mgcp.c:256
#define NULL
Definition: resample.c:96
struct mgcp_response * responses
Definition: chan_mgcp.c:422
static int answer(void *data)
Definition: chan_pjsip.c:682
static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
Definition: chan_mgcp.c:547
struct mgcp_response * next
Definition: chan_mgcp.c:287
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
#define RESPONSE_TIMEOUT
Definition: chan_mgcp.c:281
#define ast_free(a)
Definition: astmm.h:182
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
unsigned int seqno
Definition: chan_mgcp.c:275

◆ find_command()

static struct mgcp_request* find_command ( struct mgcp_endpoint p,
struct mgcp_subchannel sub,
struct mgcp_request **  queue,
ast_mutex_t l,
int  ident 
)
static

find_command: (SC:) remove command transaction from queue

Definition at line 2768 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), ast_mutex_lock, ast_mutex_unlock, mgcp_postrequest(), mgcp_request::next, NULL, and mgcp_endpoint::parent.

Referenced by handle_response().

2770 {
2771  struct mgcp_request *prev, *req;
2772 
2773  ast_mutex_lock(l);
2774  for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
2775  if (req->trid == ident) {
2776  /* remove from queue */
2777  if (!prev)
2778  *queue = req->next;
2779  else
2780  prev->next = req->next;
2781 
2782  /* send next pending command */
2783  if (*queue) {
2784  ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
2785  ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
2786 
2787  mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
2788  }
2789  break;
2790  }
2791  }
2792  ast_mutex_unlock(l);
2793  return req;
2794 }
struct mgcp_request * next
Definition: chan_mgcp.c:266
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno)
Definition: chan_mgcp.c:699
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
struct sockaddr_in addr
Definition: chan_mgcp.c:403
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ find_realtime_gw()

static struct mgcp_gateway* find_realtime_gw ( char *  name,
char *  at,
struct sockaddr_in *  sin 
)
static
Note
This is a fairly odd way of instantiating lines. Instead of each line created by virtue of being in the database (and loaded via ast_load_realtime_multientry), this code forces a specific order with a "lines" entry in the "mgcpgw" record. This has benefits, because as with chan_dahdi, values are inherited across definitions. The downside is that it's not as clear what the values will be simply by looking at a single row in the database, and it's probable that the sanest configuration should have the first column in the "mgcpep" table be "clearvars", with a static value of "all", if any variables are set at all. It may be worth making this assumption explicit in the code in the future, and then just using ast_load_realtime_multientry for the "mgcpep" records.

Definition at line 1686 of file chan_mgcp.c.

References args, AST_APP_ARG, ast_check_realtime(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_load_realtime(), AST_STANDARD_APP_ARGS, ast_strlen_zero, ast_variables_destroy(), build_gateway(), mgcp_gateway::endpoints, gateways, ast_variable::name, mgcp_endpoint::needaudit, ast_variable::next, mgcp_endpoint::next, mgcp_gateway::next, NULL, mgcp_gateway::realtime, transmit_audit_endpoint(), and ast_variable::value.

Referenced by find_subchannel_and_lock().

1687 {
1688  struct mgcp_gateway *g = NULL;
1689  struct ast_variable *mgcpgwconfig = NULL;
1690  struct ast_variable *gwv, *epname = NULL;
1691  struct mgcp_endpoint *e;
1692  char lines[256];
1693  int i, j;
1694 
1695  ast_debug(1, "*** find Realtime MGCPGW\n");
1696 
1697  if (!(i = ast_check_realtime("mgcpgw")) || !(j = ast_check_realtime("mgcpep"))) {
1698  return NULL;
1699  }
1700 
1701  if (ast_strlen_zero(at)) {
1702  ast_debug(1, "null gw name\n");
1703  return NULL;
1704  }
1705 
1706  if (!(mgcpgwconfig = ast_load_realtime("mgcpgw", "name", at, NULL))) {
1707  return NULL;
1708  }
1709 
1710  /*!
1711  * \note This is a fairly odd way of instantiating lines. Instead of each
1712  * line created by virtue of being in the database (and loaded via
1713  * ast_load_realtime_multientry), this code forces a specific order with a
1714  * "lines" entry in the "mgcpgw" record. This has benefits, because as with
1715  * chan_dahdi, values are inherited across definitions. The downside is
1716  * that it's not as clear what the values will be simply by looking at a
1717  * single row in the database, and it's probable that the sanest configuration
1718  * should have the first column in the "mgcpep" table be "clearvars", with a
1719  * static value of "all", if any variables are set at all. It may be worth
1720  * making this assumption explicit in the code in the future, and then just
1721  * using ast_load_realtime_multientry for the "mgcpep" records.
1722  */
1723  lines[0] = '\0';
1724  for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
1725  if (!strcasecmp(gwv->name, "lines")) {
1726  ast_copy_string(lines, gwv->value, sizeof(lines));
1727  break;
1728  }
1729  }
1730  /* Position gwv at the end of the list */
1731  for (gwv = gwv && gwv->next ? gwv : mgcpgwconfig; gwv->next; gwv = gwv->next);
1732 
1733  if (!ast_strlen_zero(lines)) {
1735  AST_APP_ARG(line)[100];
1736  );
1737  AST_STANDARD_APP_ARGS(args, lines);
1738  for (i = 0; i < args.argc; i++) {
1739  gwv->next = ast_load_realtime("mgcpep", "name", at, "line", args.line[i], NULL);
1740 
1741  /* Remove "line" AND position gwv at the end of the list. */
1742  for (epname = NULL; gwv->next; gwv = gwv->next) {
1743  if (!strcasecmp(gwv->next->name, "line")) {
1744  /* Remove it from the list */
1745  epname = gwv->next;
1746  gwv->next = gwv->next->next;
1747  }
1748  }
1749  /* Since "line" instantiates the configuration, we have to move it to the end. */
1750  if (epname) {
1751  gwv->next = epname;
1752  epname->next = NULL;
1753  gwv = gwv->next;
1754  }
1755  }
1756  }
1757  for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
1758  ast_debug(1, "MGCP Realtime var: %s => %s\n", gwv->name, gwv->value);
1759  }
1760 
1761  if (mgcpgwconfig) {
1762  g = build_gateway(at, mgcpgwconfig);
1763  ast_variables_destroy(mgcpgwconfig);
1764  }
1765  if (g) {
1766  g->next = gateways;
1767  g->realtime = 1;
1768  gateways = g;
1769  for (e = g->endpoints; e; e = e->next) {
1771  e->needaudit = 0;
1772  }
1773  }
1774  return g;
1775 }
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3339
struct ast_variable * next
static struct mgcp_gateway * build_gateway(char *cat, struct ast_variable *v)
build_gateway: parse mgcp.conf and create gateway/endpoint structures
Definition: chan_mgcp.c:4016
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
Structure for variables, used for configurations and for channel variables.
const char * args
#define NULL
Definition: resample.c:96
static int transmit_audit_endpoint(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:2676
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
static struct mgcp_gateway * gateways
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ find_subchannel_and_lock()

static struct mgcp_subchannel* find_subchannel_and_lock ( char *  name,
int  msgid,
struct sockaddr_in *  sin 
)
static

Definition at line 1777 of file chan_mgcp.c.

References __ourip, mgcp_gateway::addr, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_ouraddrfor(), ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_verb, c, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, find_realtime_gw(), gatelock, gateways, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, NULL, mgcp_gateway::ourip, sub, mgcp_endpoint::sub, and tmp().

Referenced by mgcp_request(), and mgcpsock_read().

1778 {
1779  struct mgcp_endpoint *p = NULL;
1780  struct mgcp_subchannel *sub = NULL;
1781  struct mgcp_gateway *g;
1782  char tmp[256] = "";
1783  char *at = NULL, *c;
1784  int found = 0;
1785  if (name) {
1786  ast_copy_string(tmp, name, sizeof(tmp));
1787  at = strchr(tmp, '@');
1788  if (!at) {
1789  ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
1790  return NULL;
1791  }
1792  *at++ = '\0';
1793  }
1795  if (at && (at[0] == '[')) {
1796  at++;
1797  c = strrchr(at, ']');
1798  if (c) {
1799  *c = '\0';
1800  }
1801  }
1802  for (g = gateways ? gateways : find_realtime_gw(name, at, sin); g; g = g->next ? g->next : find_realtime_gw(name, at, sin)) {
1803  if ((!name || !strcasecmp(g->name, at)) &&
1804  (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
1805  /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */
1806  if (sin && g->dynamic && name) {
1807  if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1808  (g->addr.sin_port != sin->sin_port)) {
1809  memcpy(&g->addr, sin, sizeof(g->addr));
1810  {
1811  struct ast_sockaddr tmp1, tmp2;
1812  struct sockaddr_in tmp3 = {0,};
1813 
1814  tmp3.sin_addr = g->ourip;
1815  ast_sockaddr_from_sin(&tmp1, &g->addr);
1816  ast_sockaddr_from_sin(&tmp2, &tmp3);
1817  if (ast_ouraddrfor(&tmp1, &tmp2)) {
1818  memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
1819  }
1820  ast_sockaddr_to_sin(&tmp2, &tmp3);
1821  g->ourip = tmp3.sin_addr;
1822  }
1823  ast_verb(3, "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
1824  }
1825  /* not dynamic, check if the name matches */
1826  } else if (name) {
1827  if (strcasecmp(g->name, at)) {
1828  continue;
1829  }
1830  /* not dynamic, no name, check if the addr matches */
1831  } else if (!name && sin) {
1832  if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1833  (g->addr.sin_port != sin->sin_port)) {
1834  continue;
1835  }
1836  } else {
1837  continue;
1838  }
1839  for (p = g->endpoints; p; p = p->next) {
1840  ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name);
1841  if (msgid) {
1842  sub = p->sub;
1843  found = 1;
1844  break;
1845  } else if (name && !strcasecmp(p->name, tmp)) {
1846  ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
1847  p->name, g->name, p->sub->id);
1848  sub = p->sub;
1849  found = 1;
1850  break;
1851  }
1852  }
1853  if (sub && found) {
1854  ast_mutex_lock(&sub->lock);
1855  break;
1856  }
1857  }
1858  }
1860  if (!sub) {
1861  if (name) {
1862  if (g) {
1863  ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
1864  } else {
1865  ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
1866  }
1867  }
1868  }
1869  return sub;
1870 }
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:430
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
static int tmp()
Definition: bt_open.c:389
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
static struct test_val c
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
#define ast_verb(level,...)
Definition: logger.h:463
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
Definition: acl.c:1005
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: chan_mgcp.c:334
struct in_addr ourip
Definition: chan_mgcp.c:405
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:782
struct sockaddr_in defaddr
Definition: chan_mgcp.c:404
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
char name[80]
Definition: chan_mgcp.c:401
struct sockaddr_in addr
Definition: chan_mgcp.c:403
#define LOG_NOTICE
Definition: logger.h:263
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
static const char name[]
Definition: cdr_mysql.c:74
static struct mgcp_gateway * gateways
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct stasis_forward * sub
Definition: res_corosync.c:240
static struct mgcp_gateway * find_realtime_gw(char *name, char *at, struct sockaddr_in *sin)
Definition: chan_mgcp.c:1686
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:769
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
static struct in_addr __ourip
Definition: chan_mgcp.c:239
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ get_csv()

static char* get_csv ( char *  c,
int *  len,
char **  next 
)
static

get_csv: (SC:) get comma separated value

Definition at line 1662 of file chan_mgcp.c.

References c, and NULL.

Referenced by handle_response().

1663 {
1664  char *s;
1665 
1666  *next = NULL, *len = 0;
1667  if (!c) return NULL;
1668 
1669  while (*c && (*c < 33 || *c == ',')) {
1670  c++;
1671  }
1672 
1673  s = c;
1674  while (*c && (*c >= 33 && *c != ',')) {
1675  c++, (*len)++;
1676  }
1677  *next = c;
1678 
1679  if (*len == 0) {
1680  s = NULL, *next = NULL;
1681  }
1682 
1683  return s;
1684 }
static struct test_val c
#define NULL
Definition: resample.c:96
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ get_header()

static char* get_header ( struct mgcp_request req,
char *  name 
)
static

Definition at line 1655 of file chan_mgcp.c.

References __get_header().

Referenced by handle_request(), and handle_response().

1656 {
1657  int start = 0;
1658  return __get_header(req, name, &start, "");
1659 }
static const char name[]
Definition: cdr_mysql.c:74
static char * __get_header(struct mgcp_request *req, char *name, int *start, char *def)
Definition: chan_mgcp.c:1635

◆ get_sdp()

static char* get_sdp ( struct mgcp_request req,
char *  name 
)
static

Definition at line 1606 of file chan_mgcp.c.

References get_sdp_by_line(), len(), mgcp_request::line, and mgcp_request::lines.

Referenced by process_sdp().

1607 {
1608  int x;
1609  int len = strlen(name);
1610  char *r;
1611 
1612  for (x = 0; x < req->lines; x++) {
1613  r = get_sdp_by_line(req->line[x], name, len);
1614  if (r[0] != '\0') return r;
1615  }
1616  return "";
1617 }
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static char * get_sdp_by_line(char *line, char *name, int nameLen)
Definition: chan_mgcp.c:1596
static const char name[]
Definition: cdr_mysql.c:74
char * line[MGCP_MAX_LINES]
Definition: chan_mgcp.c:262

◆ get_sdp_by_line()

static char* get_sdp_by_line ( char *  line,
char *  name,
int  nameLen 
)
static

Definition at line 1596 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

1597 {
1598  if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
1599  char *r = line + nameLen + 1;
1600  while (*r && (*r < 33)) ++r;
1601  return r;
1602  }
1603  return "";
1604 }
static const char name[]
Definition: cdr_mysql.c:74

◆ get_sdp_iterate()

static char* get_sdp_iterate ( int *  iterator,
struct mgcp_request req,
char *  name 
)
static

Definition at line 1624 of file chan_mgcp.c.

References get_sdp_by_line(), len(), and mgcp_request::line.

Referenced by process_sdp().

1625 {
1626  int len = strlen(name);
1627  char *r;
1628  while (*iterator < req->lines) {
1629  r = get_sdp_by_line(req->line[(*iterator)++], name, len);
1630  if (r[0] != '\0') return r;
1631  }
1632  return "";
1633 }
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static char * get_sdp_by_line(char *line, char *name, int nameLen)
Definition: chan_mgcp.c:1596
static const char name[]
Definition: cdr_mysql.c:74
char * line[MGCP_MAX_LINES]
Definition: chan_mgcp.c:262

◆ handle_hd_hf()

static void handle_hd_hf ( struct mgcp_subchannel sub,
char *  ev 
)
static

Definition at line 3322 of file chan_mgcp.c.

References AST_CONTROL_ANSWER, ast_hangup(), ast_log, ast_pthread_create_detached, ast_queue_unhold(), AST_STATE_DOWN, AST_STATE_RING, c, mgcp_subchannel::cxmode, errno, has_voicemail(), mgcp_endpoint::hookstate, mgcp_endpoint::immediate, LOG_WARNING, MGCP_CX_SENDRECV, mgcp_new(), MGCP_OFFHOOK, mgcp_queue_control(), mgcp_ss(), mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::ncs, NULL, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_subchannel::rtp, start_rtp(), transmit_modify_request(), and transmit_notify_request().

Referenced by handle_request().

3323 {
3324  struct mgcp_endpoint *p = sub->parent;
3325  struct ast_channel *c;
3326  pthread_t t;
3327 
3328  /* Off hook / answer */
3329  if (sub->outgoing) {
3330  /* Answered */
3331  if (sub->owner) {
3332  ast_queue_unhold(sub->owner);
3333  sub->cxmode = MGCP_CX_SENDRECV;
3334  if (!sub->rtp) {
3335  start_rtp(sub);
3336  } else {
3338  }
3339  /*transmit_notify_request(sub, "aw");*/
3340  transmit_notify_request(sub, "");
3342  }
3343  } else {
3344  /* Start switch */
3345  /*sub->cxmode = MGCP_CX_SENDRECV;*/
3346  if (!sub->owner) {
3347  if (!sub->rtp) {
3348  start_rtp(sub);
3349  } else {
3351  }
3352  if (p->immediate) {
3353  /* The channel is immediately up. Start right away */
3354 #ifdef DLINK_BUGGY_FIRMWARE
3355  transmit_notify_request(sub, "rt");
3356 #else
3357  transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt");
3358 #endif
3359  c = mgcp_new(sub, AST_STATE_RING, NULL, NULL);
3360  if (!c) {
3361  ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
3362  transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
3363  ast_hangup(c);
3364  }
3365  } else {
3366  if (has_voicemail(p)) {
3367  transmit_notify_request(sub, "L/sl");
3368  } else {
3369  transmit_notify_request(sub, "L/dl");
3370  }
3371  c = mgcp_new(sub, AST_STATE_DOWN, NULL, NULL);
3372  if (c) {
3373  if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) {
3374  ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
3375  ast_hangup(c);
3376  }
3377  } else {
3378  ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
3379  }
3380  }
3381  } else {
3382  if (p->hookstate == MGCP_OFFHOOK) {
3383  ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
3384  } else {
3385  ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
3386  ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
3387  }
3388  ast_queue_unhold(sub->owner);
3389  sub->cxmode = MGCP_CX_SENDRECV;
3390  if (!sub->rtp) {
3391  start_rtp(sub);
3392  } else {
3394  }
3395  /*transmit_notify_request(sub, "aw");*/
3396  transmit_notify_request(sub, "");
3397  /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
3398  }
3399  }
3400 }
static void start_rtp(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2967
Main Channel structure associated with a channel.
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:563
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
#define LOG_WARNING
Definition: logger.h:274
static struct test_val c
#define NULL
Definition: resample.c:96
static struct ast_channel * mgcp_new(struct mgcp_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
Definition: chan_mgcp.c:1494
static void * mgcp_ss(void *data)
Definition: chan_mgcp.c:3000
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: chan_mgcp.c:334
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:327
#define MGCP_CX_SENDRECV
Definition: chan_mgcp.c:132
struct ast_channel * owner
Definition: chan_mgcp.c:306
char name[80]
Definition: chan_mgcp.c:401
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
int errno
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
static int has_voicemail(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:490
static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
Definition: chan_mgcp.c:638
static int transmit_modify_request(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2572

◆ handle_mgcp_audit_endpoint()

static char* handle_mgcp_audit_endpoint ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1060 of file chan_mgcp.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, ast_strdupa, c, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, mgcpdebug, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, NULL, transmit_audit_endpoint(), and ast_cli_entry::usage.

1061 {
1062  struct mgcp_gateway *mg;
1063  struct mgcp_endpoint *me;
1064  int found = 0;
1065  char *ename,*gname, *c;
1066 
1067  switch (cmd) {
1068  case CLI_INIT:
1069  e->command = "mgcp audit endpoint";
1070  e->usage =
1071  "Usage: mgcp audit endpoint <endpointid>\n"
1072  " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
1073  " mgcp debug MUST be on to see the results of this command.\n";
1074  return NULL;
1075  case CLI_GENERATE:
1076  return NULL;
1077  }
1078 
1079  if (!mgcpdebug) {
1080  return CLI_SHOWUSAGE;
1081  }
1082  if (a->argc != 4)
1083  return CLI_SHOWUSAGE;
1084  /* split the name into parts by null */
1085  ename = ast_strdupa(a->argv[3]);
1086  for (gname = ename; *gname; gname++) {
1087  if (*gname == '@') {
1088  *gname = 0;
1089  gname++;
1090  break;
1091  }
1092  }
1093  if (gname[0] == '[') {
1094  gname++;
1095  }
1096  if ((c = strrchr(gname, ']'))) {
1097  *c = '\0';
1098  }
1100  for (mg = gateways; mg; mg = mg->next) {
1101  if (!strcasecmp(mg->name, gname)) {
1102  for (me = mg->endpoints; me; me = me->next) {
1103  if (!strcasecmp(me->name, ename)) {
1104  found = 1;
1106  break;
1107  }
1108  }
1109  if (found) {
1110  break;
1111  }
1112  }
1113  }
1114  if (!found) {
1115  ast_cli(a->fd, " << Could not find endpoint >> ");
1116  }
1118  return CLI_SUCCESS;
1119 }
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:430
const int argc
Definition: cli.h:160
Definition: cli.h:152
static int mgcpdebug
Definition: chan_mgcp.c:242
#define ast_mutex_lock(a)
Definition: lock.h:187
static struct test_val c
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static int transmit_audit_endpoint(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:2676
char name[80]
Definition: chan_mgcp.c:334
const int fd
Definition: cli.h:159
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char name[80]
Definition: chan_mgcp.c:401
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
static struct mgcp_gateway * gateways
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ handle_mgcp_set_debug()

static char* handle_mgcp_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1121 of file chan_mgcp.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, mgcpdebug, NULL, and ast_cli_entry::usage.

1122 {
1123  switch (cmd) {
1124  case CLI_INIT:
1125  e->command = "mgcp set debug {on|off}";
1126  e->usage =
1127  "Usage: mgcp set debug {on|off}\n"
1128  " Enables/Disables dumping of MGCP packets for debugging purposes\n";
1129  return NULL;
1130  case CLI_GENERATE:
1131  return NULL;
1132  }
1133 
1134  if (a->argc != e->args)
1135  return CLI_SHOWUSAGE;
1136 
1137  if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
1138  mgcpdebug = 1;
1139  ast_cli(a->fd, "MGCP Debugging Enabled\n");
1140  } else if (!strncasecmp(a->argv[3], "off", 3)) {
1141  mgcpdebug = 0;
1142  ast_cli(a->fd, "MGCP Debugging Disabled\n");
1143  } else {
1144  return CLI_SHOWUSAGE;
1145  }
1146  return CLI_SUCCESS;
1147 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
static int mgcpdebug
Definition: chan_mgcp.c:242
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ handle_mgcp_show_endpoints()

static char* handle_mgcp_show_endpoints ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1018 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock, ast_mutex_unlock, mgcp_endpoint::chanvars, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_endpoint::context, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, ast_variable::name, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::next, mgcp_endpoint::next, mgcp_gateway::next, NULL, mgcp_subchannel::owner, mgcp_gateway::realtime, mgcp_endpoint::sub, ast_cli_entry::usage, and ast_variable::value.

1019 {
1020  struct mgcp_gateway *mg;
1021  struct mgcp_endpoint *me;
1022  int hasendpoints = 0;
1023  struct ast_variable * v = NULL;
1024 
1025  switch (cmd) {
1026  case CLI_INIT:
1027  e->command = "mgcp show endpoints";
1028  e->usage =
1029  "Usage: mgcp show endpoints\n"
1030  " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
1031  return NULL;
1032  case CLI_GENERATE:
1033  return NULL;
1034  }
1035 
1036  if (a->argc != 3) {
1037  return CLI_SHOWUSAGE;
1038  }
1040  for (mg = gateways; mg; mg = mg->next) {
1041  ast_cli(a->fd, "Gateway '%s' at %s (%s%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->realtime ? "Realtime, " : "", mg->dynamic ? "Dynamic" : "Static");
1042  for (me = mg->endpoints; me; me = me->next) {
1043  ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
1044  if (me->chanvars) {
1045  ast_cli(a->fd, " Variables:\n");
1046  for (v = me->chanvars ; v ; v = v->next) {
1047  ast_cli(a->fd, " %s = '%s'\n", v->name, v->value);
1048  }
1049  }
1050  hasendpoints = 1;
1051  }
1052  if (!hasendpoints) {
1053  ast_cli(a->fd, " << No Endpoints Defined >> ");
1054  }
1055  }
1057  return CLI_SUCCESS;
1058 }
struct ast_variable * next
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:430
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
const int argc
Definition: cli.h:160
Structure for variables, used for configurations and for channel variables.
Definition: cli.h:152
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char name[80]
Definition: chan_mgcp.c:334
const int fd
Definition: cli.h:159
struct sockaddr_in defaddr
Definition: chan_mgcp.c:404
struct ast_variable * chanvars
Definition: chan_mgcp.c:394
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
struct ast_channel * owner
Definition: chan_mgcp.c:306
char name[80]
Definition: chan_mgcp.c:401
char context[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:338
#define CLI_SHOWUSAGE
Definition: cli.h:45
struct sockaddr_in addr
Definition: chan_mgcp.c:403
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
char * command
Definition: cli.h:186
static struct mgcp_gateway * gateways
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ handle_request()

static int handle_request ( struct mgcp_subchannel sub,
struct mgcp_request req,
struct sockaddr_in *  sin 
)
static

Definition at line 3402 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_debug, AST_FRAME_DTMF, ast_inet_ntoa(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_queue_hold(), ast_queue_unhold(), AST_STATE_DOWN, AST_STATE_UP, ast_verb, attempt_transfer(), mgcp_endpoint::callwaiting, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::dtmf_buf, dump_cmd_queues(), dump_queue(), mgcp_gateway::endpoints, ast_frame::frametype, get_header(), handle_hd_hf(), has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::id, ast_frame_subclass::integer, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_CONF, MGCP_CX_MUTE, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_frame(), mgcp_queue_hangup(), mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::ncs, mgcp_subchannel::next, mgcp_endpoint::next, NULL, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_subchannel::rtp, ast_frame::src, sub, mgcp_endpoint::sub, ast_frame::subclass, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, transmit_audit_endpoint(), transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_response(), mgcp_request::verb, and mgcp_gateway::wcardep.

Referenced by mgcpsock_read().

3403 {
3404  char *ev, *s;
3405  struct ast_frame f = { 0, };
3406  struct mgcp_endpoint *p = sub->parent;
3407  struct mgcp_gateway *g = NULL;
3408  int res;
3409 
3410  ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
3411  /* Clear out potential response */
3412  if (!strcasecmp(req->verb, "RSIP")) {
3413  /* Test if this RSIP request is just a keepalive */
3414  if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
3415  ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name);
3416  transmit_response(sub, "200", req, "OK");
3417  } else {
3418  dump_queue(p->parent, p);
3419  dump_cmd_queues(p, NULL);
3420 
3421  if ((strcmp(p->name, p->parent->wcardep) != 0)) {
3422  ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name);
3423  }
3424  /* For RSIP on wildcard we reset all endpoints */
3425  if (!strcmp(p->name, p->parent->wcardep)) {
3426  /* Reset all endpoints */
3427  struct mgcp_endpoint *tmp_ep;
3428 
3429  g = p->parent;
3430  for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) {
3431  /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/
3432  if (strcmp(tmp_ep->name, g->wcardep) != 0) {
3433  struct mgcp_subchannel *tmp_sub, *first_sub;
3434  ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
3435 
3436  first_sub = tmp_ep->sub;
3437  tmp_sub = tmp_ep->sub;
3438  while (tmp_sub) {
3439  mgcp_queue_hangup(tmp_sub);
3440  tmp_sub = tmp_sub->next;
3441  if (tmp_sub == first_sub)
3442  break;
3443  }
3444  }
3445  }
3446  } else if (sub->owner) {
3447  mgcp_queue_hangup(sub);
3448  }
3449  transmit_response(sub, "200", req, "OK");
3450  /* We don't send NTFY or AUEP to wildcard ep */
3451  if (strcmp(p->name, p->parent->wcardep) != 0) {
3452  transmit_notify_request(sub, "");
3453  /* Audit endpoint.
3454  Idea is to prevent lost lines due to race conditions
3455  */
3457  }
3458  }
3459  } else if (!strcasecmp(req->verb, "NTFY")) {
3460  /* Acknowledge and be sure we keep looking for the same things */
3461  transmit_response(sub, "200", req, "OK");
3462  /* Notified of an event */
3463  ev = get_header(req, "O");
3464  s = strchr(ev, '/');
3465  if (s) ev = s + 1;
3466  ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
3467  /* Keep looking for events unless this was a hangup */
3468  if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
3470  }
3471  if (!strcasecmp(ev, "hd")) {
3472  p->hookstate = MGCP_OFFHOOK;
3473  sub->cxmode = MGCP_CX_SENDRECV;
3474 
3475  if (p) {
3476  /* When the endpoint have a Off hook transition we allways
3477  starts without any previous dtmfs */
3478  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3479  }
3480 
3481  handle_hd_hf(sub, ev);
3482  } else if (!strcasecmp(ev, "hf")) {
3483  /* We can assume we are offhook if we received a hookflash */
3484  /* First let's just do call wait and ignore threeway */
3485  /* We're currently in charge */
3486  if (p->hookstate != MGCP_OFFHOOK) {
3487  /* Cisco c7940 sends hf even if the phone is onhook */
3488  /* Thanks to point on IRC for pointing this out */
3489  return -1;
3490  }
3491  /* do not let * conference two down channels */
3492  if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_DOWN && !sub->next->owner)
3493  return -1;
3494 
3495  if (p->callwaiting || p->transfer || p->threewaycalling) {
3496  ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
3497  p->sub = p->sub->next;
3498 
3499  /* transfer control to our next subchannel */
3500  if (!sub->next->owner) {
3501  /* plave the first call on hold and start up a new call */
3502  sub->cxmode = MGCP_CX_MUTE;
3503  ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3505  if (sub->owner) {
3506  ast_queue_hold(sub->owner, NULL);
3507  }
3508  sub->next->cxmode = MGCP_CX_RECVONLY;
3509  handle_hd_hf(sub->next, ev);
3510  } else if (sub->owner && sub->next->owner) {
3511  /* We've got two active calls lets decide whether or not to conference or just flip flop */
3512  if ((!sub->outgoing) && (!sub->next->outgoing)) {
3513  /* We made both calls lets conference */
3514  ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n",
3515  sub->id, sub->next->id, p->name, p->parent->name);
3516  sub->cxmode = MGCP_CX_CONF;
3517  sub->next->cxmode = MGCP_CX_CONF;
3518  ast_queue_unhold(sub->next->owner);
3521  } else {
3522  /* Let's flipflop between calls */
3523  /* XXX Need to check for state up ??? */
3524  /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
3525  ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
3526  sub->id, sub->next->id, p->name, p->parent->name);
3527  sub->cxmode = MGCP_CX_MUTE;
3528  ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3530 
3531  ast_queue_hold(sub->owner, NULL);
3532  ast_queue_hold(sub->next->owner, NULL);
3533 
3534  handle_hd_hf(sub->next, ev);
3535  }
3536  } else {
3537  /* We've most likely lost one of our calls find an active call and bring it up */
3538  if (sub->owner) {
3539  p->sub = sub;
3540  } else if (sub->next->owner) {
3541  p->sub = sub->next;
3542  } else {
3543  /* We seem to have lost both our calls */
3544  /* XXX - What do we do now? */
3545  return -1;
3546  }
3547  ast_queue_unhold(p->sub->owner);
3548  p->sub->cxmode = MGCP_CX_SENDRECV;
3550  }
3551  } else {
3552  ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
3553  p->name, p->parent->name);
3554  }
3555  } else if (!strcasecmp(ev, "hu")) {
3556  p->hookstate = MGCP_ONHOOK;
3557  sub->cxmode = MGCP_CX_RECVONLY;
3558  ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
3559  /* Do we need to send MDCX before a DLCX ?
3560  if (sub->rtp) {
3561  transmit_modify_request(sub);
3562  }
3563  */
3564  if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
3565  /* We're allowed to transfer, we have two avtive calls and */
3566  /* we made at least one of the calls. Let's try and transfer */
3567  ast_mutex_lock(&p->sub->next->lock);
3568  res = attempt_transfer(p, sub);
3569  if (res) {
3570  ast_log(LOG_WARNING, "Transfer attempt failed\n");
3571  ast_mutex_unlock(&p->sub->next->lock);
3572  return -1;
3573  }
3574  ast_mutex_unlock(&p->sub->next->lock);
3575  } else {
3576  /* Hangup the current call */
3577  /* If there is another active call, mgcp_hangup will ring the phone with the other call */
3578  if (sub->owner) {
3579  sub->alreadygone = 1;
3580  mgcp_queue_hangup(sub);
3581  } else {
3582  ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
3583  p->name, p->parent->name, sub->id);
3584  /* Instruct the other side to remove the connection since it apparently *
3585  * still thinks the channel is active. *
3586  * For Cisco IAD2421 /BAK/ */
3588  }
3589  }
3590  if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
3591  p->hidecallerid = 0;
3592  if (p->hascallwaiting && !p->callwaiting) {
3593  ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
3594  p->callwaiting = -1;
3595  }
3596  if (has_voicemail(p)) {
3597  ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
3598  transmit_notify_request(sub, "L/vmwi(+)");
3599  } else {
3600  ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
3601  transmit_notify_request(sub, "L/vmwi(-)");
3602  }
3603  }
3604  } else if ((strlen(ev) == 1) &&
3605  (((ev[0] >= '0') && (ev[0] <= '9')) ||
3606  ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
3607  (ev[0] == '*') || (ev[0] == '#'))) {
3608  if (sub && sub->owner && (ast_channel_state(sub->owner) >= AST_STATE_UP)) {
3610  f.subclass.integer = ev[0];
3611  f.src = "mgcp";
3612  /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
3613  mgcp_queue_frame(sub, &f);
3614  ast_mutex_lock(&sub->next->lock);
3615  if (sub->next->owner)
3616  mgcp_queue_frame(sub->next, &f);
3617  ast_mutex_unlock(&sub->next->lock);
3618  if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) {
3619  memset(p->curtone, 0, sizeof(p->curtone));
3620  }
3621  } else {
3622  p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
3623  p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
3624  }
3625  } else if (!strcasecmp(ev, "T")) {
3626  /* Digit timeout -- unimportant */
3627  } else if (!strcasecmp(ev, "ping")) {
3628  /* ping -- unimportant */
3629  } else {
3630  ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
3631  }
3632  } else {
3633  ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
3634  transmit_response(sub, "510", req, "Unknown verb");
3635  }
3636  return 0;
3637 }
static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
Definition: chan_mgcp.c:604
int hascallwaiting
Definition: chan_mgcp.c:353
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
int hidecallerid
Definition: chan_mgcp.c:362
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
static char * get_header(struct mgcp_request *req, char *name)
Definition: chan_mgcp.c:1655
#define LOG_WARNING
Definition: logger.h:274
static int attempt_transfer(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
Complete an attended transfer.
Definition: chan_mgcp.c:3281
char dtmf_buf[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:343
static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:621
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define MGCP_CX_MUTE
Definition: chan_mgcp.c:135
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define ast_mutex_lock(a)
Definition: lock.h:187
char curtone[80]
Definition: chan_mgcp.c:346
char * verb
Definition: chan_mgcp.c:255
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
#define NULL
Definition: resample.c:96
static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
Definition: chan_mgcp.c:2174
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
#define AST_FRAME_DTMF
#define ast_verb(level,...)
Definition: logger.h:463
static int transmit_audit_endpoint(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:2676
struct ast_frame_subclass subclass
static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
Definition: chan_mgcp.c:3322
char wcardep[30]
Definition: chan_mgcp.c:416
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: chan_mgcp.c:334
const char * src
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:327
#define MGCP_CX_SENDRECV
Definition: chan_mgcp.c:132
struct ast_channel * owner
Definition: chan_mgcp.c:306
char name[80]
Definition: chan_mgcp.c:401
static int transmit_connection_del(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2690
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1191
int threewaycalling
Definition: chan_mgcp.c:355
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
#define LOG_NOTICE
Definition: logger.h:263
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
dump_cmd_queues: (SC:) cleanup pending commands
Definition: chan_mgcp.c:2734
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
static int has_voicemail(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:490
struct stasis_forward * sub
Definition: res_corosync.c:240
Data structure associated with a single frame of data.
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
enum ast_frame_type frametype
#define MGCP_CX_CONF
Definition: chan_mgcp.c:133
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
static int transmit_modify_request(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2572
#define MGCP_CX_RECVONLY
Definition: chan_mgcp.c:131
static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
Definition: chan_mgcp.c:570
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ handle_response()

static void handle_response ( struct mgcp_endpoint p,
struct mgcp_subchannel sub,
int  result,
unsigned int  ident,
struct mgcp_request resp 
)
static

Definition at line 2797 of file chan_mgcp.c.

References AST_CONTROL_RINGING, ast_copy_string(), ast_free, ast_log, ast_queue_control(), AST_STATE_RINGING, ast_strlen_zero, ast_verb, c, mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, dump_cmd_queues(), find_command(), get_csv(), get_header(), mgcp_endpoint::hookstate, mgcp_subchannel::id, len(), mgcp_request::lines, LOG_NOTICE, LOG_WARNING, MGCP_CMD_AUEP, MGCP_CMD_CRCX, MGCP_CMD_MDCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_hangup(), mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::next, NULL, mgcp_subchannel::owner, mgcp_endpoint::parent, process_sdp(), mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::slowsequence, start_rtp(), mgcp_endpoint::sub, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_response().

Referenced by mgcpsock_read(), and retrans_pkt().

2799 {
2800  char *c;
2801  struct mgcp_request *req;
2802  struct mgcp_gateway *gw = p->parent;
2803 
2804  if (result < 200) {
2805  /* provisional response */
2806  return;
2807  }
2808 
2809  if (p->slowsequence)
2810  req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2811  else if (sub)
2812  req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
2813  else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
2814  req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2815 
2816  if (!req) {
2817  ast_verb(3, "No command found on [%s] for transaction %u. Ignoring...\n",
2818  gw->name, ident);
2819  return;
2820  }
2821 
2822  if (p && (result >= 400) && (result <= 599)) {
2823  switch (result) {
2824  case 401:
2825  p->hookstate = MGCP_OFFHOOK;
2826  break;
2827  case 402:
2828  p->hookstate = MGCP_ONHOOK;
2829  break;
2830  case 406:
2831  ast_log(LOG_NOTICE, "Transaction %u timed out\n", ident);
2832  break;
2833  case 407:
2834  ast_log(LOG_NOTICE, "Transaction %u aborted\n", ident);
2835  break;
2836  }
2837  if (sub) {
2838  if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) {
2839  ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result);
2841  }
2842  if (sub->owner) {
2843  ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2844  result, p->name, p->parent->name, sub ? sub->id:-1);
2845  mgcp_queue_hangup(sub);
2846  }
2847  } else {
2848  if (p->sub->next->owner) {
2849  ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2850  result, p->name, p->parent->name, sub ? sub->id:-1);
2851  mgcp_queue_hangup(p->sub);
2852  }
2853 
2854  if (p->sub->owner) {
2855  ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2856  result, p->name, p->parent->name, sub ? sub->id:-1);
2857  mgcp_queue_hangup(p->sub);
2858  }
2859 
2860  dump_cmd_queues(p, NULL);
2861  }
2862  }
2863 
2864  if (resp) {
2865  /* responseAck: */
2866  if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) {
2867  if (sub) {
2868  transmit_response(sub, "000", resp, "OK");
2869  if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_RINGING) {
2871  }
2872  }
2873  }
2874  if (req->cmd == MGCP_CMD_CRCX) {
2875  if ((c = get_header(resp, "I"))) {
2876  if (!ast_strlen_zero(c) && sub) {
2877  /* if we are hanging up do not process this conn. */
2878  if (sub->owner) {
2879  if (!ast_strlen_zero(sub->cxident)) {
2880  if (strcasecmp(c, sub->cxident)) {
2881  ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
2882  }
2883  }
2884  ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
2885  if (sub->tmpdest.sin_addr.s_addr) {
2886  transmit_modify_with_sdp(sub, NULL, 0);
2887  }
2888  } else {
2889  /* XXX delete this one
2890  callid and conn id may already be lost.
2891  so the following del conn may have a side effect of
2892  cleaning up the next subchannel */
2894  }
2895  }
2896  }
2897  }
2898 
2899  if (req->cmd == MGCP_CMD_AUEP) {
2900  /* check stale connection ids */
2901  if ((c = get_header(resp, "I"))) {
2902  char *v, *n;
2903  int len;
2904  while ((v = get_csv(c, &len, &n))) {
2905  if (len) {
2906  if (strncasecmp(v, p->sub->cxident, len) &&
2907  strncasecmp(v, p->sub->next->cxident, len)) {
2908  /* connection id not found. delete it */
2909  char cxident[80] = "";
2910 
2911  if (len > (sizeof(cxident) - 1))
2912  len = sizeof(cxident) - 1;
2913  ast_copy_string(cxident, v, len);
2914  ast_verb(3, "Non existing connection id %s on %s@%s \n",
2915  cxident, p->name, gw->name);
2917  }
2918  }
2919  c = n;
2920  }
2921  }
2922 
2923  /* Try to determine the hookstate returned from an audit endpoint command */
2924  if ((c = get_header(resp, "ES"))) {
2925  if (!ast_strlen_zero(c)) {
2926  if (strstr(c, "hu")) {
2927  if (p->hookstate != MGCP_ONHOOK) {
2928  /* XXX cleanup if we think we are offhook XXX */
2929  if ((p->sub->owner || p->sub->next->owner ) &&
2930  p->hookstate == MGCP_OFFHOOK)
2931  mgcp_queue_hangup(sub);
2932  p->hookstate = MGCP_ONHOOK;
2933 
2934  /* update the requested events according to the new hookstate */
2935  transmit_notify_request(p->sub, "");
2936 
2937  ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
2938  }
2939  } else if (strstr(c, "hd")) {
2940  if (p->hookstate != MGCP_OFFHOOK) {
2941  p->hookstate = MGCP_OFFHOOK;
2942 
2943  /* update the requested events according to the new hookstate */
2944  transmit_notify_request(p->sub, "");
2945 
2946  ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
2947  }
2948  }
2949  }
2950  }
2951  }
2952 
2953  if (resp && resp->lines) {
2954  /* do not process sdp if we are hanging up. this may be a late response */
2955  if (sub && sub->owner) {
2956  if (!sub->rtp)
2957  start_rtp(sub);
2958  if (sub->rtp)
2959  process_sdp(sub, resp);
2960  }
2961  }
2962  }
2963 
2964  ast_free(req);
2965 }
static void start_rtp(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2967
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
struct mgcp_request * cx_queue
Definition: chan_mgcp.c:315
ast_mutex_t cmd_queue_lock
Definition: chan_mgcp.c:385
int slowsequence
Definition: chan_mgcp.c:369
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
static char * get_csv(char *c, int *len, char **next)
get_csv: (SC:) get comma separated value
Definition: chan_mgcp.c:1662
static char * get_header(struct mgcp_request *req, char *name)
Definition: chan_mgcp.c:1655
#define LOG_WARNING
Definition: logger.h:274
static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:621
ast_channel_state
ast_channel states
Definition: channelstate.h:35
struct sockaddr_in tmpdest
Definition: chan_mgcp.c:309
static struct test_val c
static struct mgcp_request * find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request **queue, ast_mutex_t *l, int ident)
find_command: (SC:) remove command transaction from queue
Definition: chan_mgcp.c:2768
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
#define NULL
Definition: resample.c:96
static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
Definition: chan_mgcp.c:2174
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
Definition: chan_mgcp.c:2713
static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs)
Definition: chan_mgcp.c:2301
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: chan_mgcp.c:334
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:327
struct ast_channel * owner
Definition: chan_mgcp.c:306
struct mgcp_request * rqnt_queue
Definition: chan_mgcp.c:382
static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
Definition: chan_mgcp.c:1970
char name[80]
Definition: chan_mgcp.c:401
static int transmit_connection_del(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2690
ast_mutex_t cx_queue_lock
Definition: chan_mgcp.c:316
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char cxident[80]
Definition: chan_mgcp.c:312
#define LOG_NOTICE
Definition: logger.h:263
#define ast_free(a)
Definition: astmm.h:182
ast_mutex_t rqnt_queue_lock
Definition: chan_mgcp.c:383
struct mgcp_request * cmd_queue
Definition: chan_mgcp.c:384
static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
dump_cmd_queues: (SC:) cleanup pending commands
Definition: chan_mgcp.c:2734
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static PGresult * result
Definition: cel_pgsql.c:88

◆ has_voicemail()

static int has_voicemail ( struct mgcp_endpoint p)
static

Definition at line 490 of file chan_mgcp.c.

References ao2_cleanup, ast_app_has_voicemail(), ast_mwi_state_cache(), ast_mwi_state_type(), mgcp_endpoint::mailbox, ast_mwi_state::new_msgs, NULL, RAII_VAR, stasis_cache_get(), and stasis_message_data().

Referenced by do_monitor(), handle_hd_hf(), handle_request(), mgcp_hangup(), and mgcp_request().

491 {
492  int new_msgs;
493  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
494 
496  if (msg) {
497  struct ast_mwi_state *mwi_state = stasis_message_data(msg);
498  new_msgs = mwi_state->new_msgs;
499  } else {
500  new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
501  }
502 
503  return new_msgs;
504 }
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
Definition: mwi.c:90
#define NULL
Definition: resample.c:96
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
Definition: main/app.c:655
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int new_msgs
Definition: mwi.h:461
struct stasis_message * stasis_cache_get(struct stasis_cache *cache, struct stasis_message_type *type, const char *id)
Retrieve an item from the cache for the ast_eid_default entity.
Definition: stasis_cache.c:686
The structure that contains MWI state.
Definition: mwi.h:457
char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:347

◆ init_req()

static int init_req ( struct mgcp_endpoint p,
struct mgcp_request req,
char *  verb,
unsigned int  oseq 
)
static

Definition at line 2128 of file chan_mgcp.c.

References ast_log, mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_gateway::isnamedottedip, mgcp_request::len, LOG_WARNING, MGCP_MAX_HEADERS, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::ncs, and mgcp_endpoint::parent.

Referenced by reqprep().

2129 {
2130  /* Initialize a response */
2131  if (req->headers || req->len) {
2132  ast_log(LOG_WARNING, "Request already initialized?!?\n");
2133  return -1;
2134  }
2135  req->header[req->headers] = req->data + req->len;
2136  /* check if we need brackets around the gw name */
2137  if (p->parent->isnamedottedip) {
2138  snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %u %s@[%s] MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : "");
2139  } else {
2140 + snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %u %s@%s MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : "");
2141  }
2142  req->len += strlen(req->header[req->headers]);
2143  if (req->headers < MGCP_MAX_HEADERS) {
2144  req->headers++;
2145  } else {
2146  ast_log(LOG_WARNING, "Out of header space\n");
2147  }
2148  return 0;
2149 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: chan_mgcp.c:334
char name[80]
Definition: chan_mgcp.c:401
int isnamedottedip
Definition: chan_mgcp.c:402
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
#define MGCP_MAX_HEADERS
Definition: chan_mgcp.c:250
char * header[MGCP_MAX_HEADERS]
Definition: chan_mgcp.c:260
char data[MGCP_MAX_PACKET]
Definition: chan_mgcp.c:263

◆ init_resp()

static int init_resp ( struct mgcp_request req,
char *  resp,
struct mgcp_request orig,
char *  resprest 
)
static

Definition at line 2110 of file chan_mgcp.c.

References ast_log, mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_request::identifier, mgcp_request::len, LOG_WARNING, and MGCP_MAX_HEADERS.

Referenced by respprep().

2111 {
2112  /* Initialize a response */
2113  if (req->headers || req->len) {
2114  ast_log(LOG_WARNING, "Request already initialized?!?\n");
2115  return -1;
2116  }
2117  req->header[req->headers] = req->data + req->len;
2118  snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
2119  req->len += strlen(req->header[req->headers]);
2120  if (req->headers < MGCP_MAX_HEADERS) {
2121  req->headers++;
2122  } else {
2123  ast_log(LOG_WARNING, "Out of header space\n");
2124  }
2125  return 0;
2126 }
#define LOG_WARNING
Definition: logger.h:274
char * identifier
Definition: chan_mgcp.c:256
#define ast_log
Definition: astobj2.c:42
#define MGCP_MAX_HEADERS
Definition: chan_mgcp.c:250
char * header[MGCP_MAX_HEADERS]
Definition: chan_mgcp.c:260
char data[MGCP_MAX_PACKET]
Definition: chan_mgcp.c:263

◆ 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 4856 of file chan_mgcp.c.

References ao2_ref, ast_channel_register(), ast_cli_register_multiple, ast_format_alaw, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_ulaw, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, ast_sched_context_create(), ast_sched_context_destroy(), ast_channel_tech::capabilities, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, reload_config(), and restart_monitor().

Referenced by unload_module().

4857 {
4859  return AST_MODULE_LOAD_DECLINE;
4860  }
4863  return AST_MODULE_LOAD_DECLINE;
4864  }
4868  if (!(sched = ast_sched_context_create())) {
4869  ast_log(LOG_WARNING, "Unable to create schedule context\n");
4872  return AST_MODULE_LOAD_DECLINE;
4873  }
4874 
4875  if (!(io = io_context_create())) {
4876  ast_log(LOG_WARNING, "Unable to create I/O context\n");
4880  return AST_MODULE_LOAD_DECLINE;
4881  }
4882 
4883  if (reload_config(0)) {
4886  return AST_MODULE_LOAD_DECLINE;
4887  }
4888 
4889  /* Make sure we can register our mgcp channel type */
4891  ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
4896  return AST_MODULE_LOAD_DECLINE;
4897  }
4898 
4900  ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
4901 
4902  /* And start the monitor for the first time */
4903  restart_monitor();
4904 
4905  return AST_MODULE_LOAD_SUCCESS;
4906 }
static int restart_monitor(void)
Definition: chan_mgcp.c:3936
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
descriptor for a cli entry.
Definition: cli.h:171
#define LOG_WARNING
Definition: logger.h:274
static struct ast_format_cap * global_capability
Definition: chan_mgcp.c:235
#define ast_rtp_glue_register(glue)
Definition: rtp_engine.h:847
Definition: sched.c:76
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
#define ast_log
Definition: astobj2.c:42
void io_context_destroy(struct io_context *ioc)
Destroys a context.
Definition: io.c:107
static int reload_config(int reload)
Definition: chan_mgcp.c:4683
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct io_context * io
Definition: chan_mgcp.c:245
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
static struct ast_channel_tech mgcp_tech
Definition: chan_mgcp.c:472
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236
#define LOG_ERROR
Definition: logger.h:285
struct ast_format_cap * capabilities
Definition: channel.h:633
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct ast_cli_entry cli_mgcp[]
Definition: chan_mgcp.c:1149
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
static struct ast_rtp_glue mgcp_rtp_glue
Definition: chan_mgcp.c:4511
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...
Definition: io.c:81

◆ mgcp_alloc_pktcgate()

static int mgcp_alloc_pktcgate ( struct mgcp_subchannel sub)
static

Definition at line 2448 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_pktccops_gate_alloc(), mgcp_subchannel::gate, cops_gate::gate_open, GATE_SET, mgcp_pktcgate_open(), mgcp_pktcgate_remove(), NULL, mgcp_subchannel::parent, mgcp_endpoint::parent, sub, and cops_gate::tech_pvt.

Referenced by start_rtp().

2449 {
2450  struct mgcp_endpoint *p = sub->parent;
2451  sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr),
2452  8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove);
2453 
2454  if (!sub->gate) {
2455  return 0;
2456  }
2457  sub->gate->tech_pvt = sub;
2459  return 1;
2460 }
struct cops_gate * gate
Definition: chan_mgcp.c:322
struct cops_gate * ast_pktccops_gate_alloc(int cmd, struct cops_gate *gate, uint32_t mta, uint32_t actcount, float bitrate, uint32_t psize, uint32_t ssip, uint16_t ssport, int(*const got_dq_gi)(struct cops_gate *gate), int(*const gate_remove)(struct cops_gate *gate))
Definition: res_pktccops.c:468
#define NULL
Definition: resample.c:96
void * tech_pvt
Definition: pktccops.h:67
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
int(* gate_open)(struct cops_gate *gate)
Definition: pktccops.h:66
struct sockaddr_in addr
Definition: chan_mgcp.c:403
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
struct stasis_forward * sub
Definition: res_corosync.c:240
static int mgcp_pktcgate_open(struct cops_gate *gate)
Definition: chan_mgcp.c:2435
static int mgcp_pktcgate_remove(struct cops_gate *gate)
Definition: chan_mgcp.c:2412

◆ mgcp_answer()

static int mgcp_answer ( struct ast_channel ast)
static

Definition at line 1156 of file chan_mgcp.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, ast_verb, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_subchannel::lock, MGCP_CX_SENDRECV, mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_subchannel::rtp, start_rtp(), sub, transmit_modify_request(), and transmit_notify_request().

1157 {
1158  int res = 0;
1159  struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
1160  struct mgcp_endpoint *p = sub->parent;
1161 
1162  ast_mutex_lock(&sub->lock);
1163  sub->cxmode = MGCP_CX_SENDRECV;
1164  if (!sub->rtp) {
1165  start_rtp(sub);
1166  } else {
1168  }
1169  ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n",
1170  ast_channel_name(ast), p->name, p->parent->name, sub->id);
1171  if (ast_channel_state(ast) != AST_STATE_UP) {
1172  ast_setstate(ast, AST_STATE_UP);
1173  ast_debug(1, "mgcp_answer(%s)\n", ast_channel_name(ast));
1174  transmit_notify_request(sub, "");
1176  }
1177  ast_mutex_unlock(&sub->lock);
1178  return res;
1179 }
static void start_rtp(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2967
void * ast_channel_tech_pvt(const struct ast_channel *chan)
ast_mutex_t lock
Definition: chan_mgcp.c:304
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char name[80]
Definition: chan_mgcp.c:334
#define MGCP_CX_SENDRECV
Definition: chan_mgcp.c:132
char name[80]
Definition: chan_mgcp.c:401
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
const char * ast_channel_name(const struct ast_channel *chan)
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
struct stasis_forward * sub
Definition: res_corosync.c:240
static int transmit_modify_request(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2572
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_call()

static int mgcp_call ( struct ast_channel ast,
const char *  dest,
int  timeout 
)
static

Definition at line 826 of file chan_mgcp.c.

References ast_channel_connected(), ast_channel_name(), ast_channel_tech_pvt(), ast_copy_string(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero, mgcp_subchannel::callid, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, name, mgcp_endpoint::ncs, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, pbx_builtin_getvar_helper(), mgcp_subchannel::rtp, S_COR, start_rtp(), sub, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, and TYPE_LINE.

827 {
828  int res;
829  struct mgcp_endpoint *p;
830  struct mgcp_subchannel *sub;
831  char tone[50] = "";
832  const char *distinctive_ring = pbx_builtin_getvar_helper(ast, "ALERT_INFO");
833 
834  ast_debug(3, "MGCP mgcp_call(%s)\n", ast_channel_name(ast));
835  sub = ast_channel_tech_pvt(ast);
836  p = sub->parent;
837 
838  ast_mutex_lock(&sub->lock);
839  switch (p->hookstate) {
840  case MGCP_OFFHOOK:
841  if (!ast_strlen_zero(distinctive_ring)) {
842  snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
843  ast_debug(3, "MGCP distinctive callwait %s\n", tone);
844  } else {
845  ast_copy_string(tone, (p->ncs ? "L/wt1" : "L/wt"), sizeof(tone));
846  ast_debug(3, "MGCP normal callwait %s\n", tone);
847  }
848  break;
849  case MGCP_ONHOOK:
850  default:
851  if (!ast_strlen_zero(distinctive_ring)) {
852  snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
853  ast_debug(3, "MGCP distinctive ring %s\n", tone);
854  } else {
855  ast_copy_string(tone, "L/rg", sizeof(tone));
856  ast_debug(3, "MGCP default ring\n");
857  }
858  break;
859  }
860 
862  ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
863  ast_mutex_unlock(&sub->lock);
864  return -1;
865  }
866 
867  res = 0;
868  sub->outgoing = 1;
869  sub->cxmode = MGCP_CX_RECVONLY;
871  if (p->type == TYPE_LINE) {
872  if (!sub->rtp) {
873  start_rtp(sub);
874  } else {
876  }
877 
878  if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
879  /* try to prevent a callwait from disturbing the other connection */
880  sub->next->cxmode = MGCP_CX_RECVONLY;
882  }
883 
885  S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, ""),
886  S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, ""));
888 
889  if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
890  /* Put the connection back in sendrecv */
891  sub->next->cxmode = MGCP_CX_SENDRECV;
893  }
894  } else {
895  ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
896  res = -1;
897  }
898  ast_mutex_unlock(&sub->lock);
899  return res;
900 }
#define TYPE_LINE
Definition: chan_mgcp.c:330
static void start_rtp(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2967
char callid[80]
Definition: chan_mgcp.c:313
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define LOG_WARNING
Definition: logger.h:274
ast_mutex_t lock
Definition: chan_mgcp.c:304
ast_channel_state
ast_channel states
Definition: channelstate.h:35
static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
Definition: chan_mgcp.c:2527
#define ast_mutex_lock(a)
Definition: lock.h:187
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:327
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
#define MGCP_CX_SENDRECV
Definition: chan_mgcp.c:132
struct ast_channel * owner
Definition: chan_mgcp.c:306
char cxident[80]
Definition: chan_mgcp.c:312
#define LOG_NOTICE
Definition: logger.h:263
static const char name[]
Definition: cdr_mysql.c:74
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
struct stasis_forward * sub
Definition: res_corosync.c:240
static int transmit_modify_request(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2572
#define MGCP_CX_RECVONLY
Definition: chan_mgcp.c:131
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_devicestate()

static int mgcp_devicestate ( const char *  data)
static

mgcp_devicestate: channel callback for device status monitoring

Parameters
datatech/resource name of MGCP device to query

Callback for device state management in channel subsystem to obtain device status (up/down) of a specific MGCP endpoint

Returns
device status result (from devicestate.h) AST_DEVICE_INVALID (not available) or AST_DEVICE_UNKNOWN (available but unknown state)

Definition at line 1360 of file chan_mgcp.c.

References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_mutex_lock, ast_mutex_unlock, ast_strdupa, mgcp_gateway::endpoints, error(), gatelock, gateways, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, NULL, and tmp().

1361 {
1362  struct mgcp_gateway *g;
1363  struct mgcp_endpoint *e = NULL;
1364  char *tmp, *endpt, *gw;
1365  int ret = AST_DEVICE_INVALID;
1366 
1367  endpt = ast_strdupa(data);
1368  if ((tmp = strchr(endpt, '@'))) {
1369  *tmp++ = '\0';
1370  gw = tmp;
1371  } else
1372  goto error;
1373 
1375  for (g = gateways; g; g = g->next) {
1376  if (strcasecmp(g->name, gw) == 0) {
1377  e = g->endpoints;
1378  break;
1379  }
1380  }
1381 
1382  if (!e)
1383  goto error;
1384 
1385  for (; e; e = e->next) {
1386  if (strcasecmp(e->name, endpt) == 0) {
1387  break;
1388  }
1389  }
1390 
1391  if (!e)
1392  goto error;
1393 
1394  /*
1395  * As long as the gateway/endpoint is valid, we'll
1396  * assume that the device is available and its state
1397  * can be tracked.
1398  */
1399  ret = AST_DEVICE_UNKNOWN;
1400 
1401 error:
1403  return ret;
1404 }
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:430
static int tmp()
Definition: bt_open.c:389
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
char name[80]
Definition: chan_mgcp.c:334
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char name[80]
Definition: chan_mgcp.c:401
static struct mgcp_gateway * gateways
int error(const char *format,...)
Definition: utils/frame.c:999
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_fixup()

static int mgcp_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
)
static

Definition at line 1282 of file chan_mgcp.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_log, ast_mutex_lock, ast_mutex_unlock, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_set_owner(), mgcp_subchannel::owner, and sub.

1283 {
1284  struct mgcp_subchannel *sub = ast_channel_tech_pvt(newchan);
1285 
1286  ast_mutex_lock(&sub->lock);
1287  ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", ast_channel_name(oldchan), ast_channel_name(newchan));
1288  if (sub->owner != oldchan) {
1289  ast_mutex_unlock(&sub->lock);
1290  ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
1291  return -1;
1292  }
1293  mgcp_set_owner(sub, newchan);
1294  ast_mutex_unlock(&sub->lock);
1295  return 0;
1296 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
static void mgcp_set_owner(struct mgcp_subchannel *sub, struct ast_channel *chan)
Definition: chan_mgcp.c:1222
#define LOG_WARNING
Definition: logger.h:274
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_log
Definition: astobj2.c:42
struct ast_channel * owner
Definition: chan_mgcp.c:306
#define LOG_NOTICE
Definition: logger.h:263
const char * ast_channel_name(const struct ast_channel *chan)
struct stasis_forward * sub
Definition: res_corosync.c:240
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_get_codec()

static void mgcp_get_codec ( struct ast_channel chan,
struct ast_format_cap result 
)
static

Definition at line 4503 of file chan_mgcp.c.

References ast_channel_tech_pvt(), ast_format_cap_append_from_cap(), AST_MEDIA_TYPE_UNKNOWN, mgcp_endpoint::cap, mgcp_subchannel::parent, and sub.

4504 {
4505  struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
4506  struct mgcp_endpoint *p = sub->parent;
4507 
4509 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
struct stasis_forward * sub
Definition: res_corosync.c:240
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269

◆ mgcp_get_rtp_peer()

static enum ast_rtp_glue_result mgcp_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp_instance **  instance 
)
static

Definition at line 4475 of file chan_mgcp.c.

References ao2_ref, ast_channel_tech_pvt(), AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, mgcp_endpoint::directmedia, NULL, mgcp_subchannel::parent, mgcp_subchannel::rtp, and sub.

4476 {
4477  struct mgcp_subchannel *sub = NULL;
4478 
4479  if (!(sub = ast_channel_tech_pvt(chan)) || !(sub->rtp))
4481 
4482  ao2_ref(sub->rtp, +1);
4483  *instance = sub->rtp;
4484 
4485  if (sub->parent->directmedia)
4487  else
4489 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
struct stasis_forward * sub
Definition: res_corosync.c:240

◆ mgcp_hangup()

static int mgcp_hangup ( struct ast_channel ast)
static

Definition at line 902 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_channel_bridge_peer(), ast_channel_caller(), ast_channel_cleanup, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), ast_debug, ast_dsp_free(), ast_module_unref, ast_mutex_lock, ast_mutex_unlock, ast_pktccops_gate_alloc(), ast_rtp_instance_destroy(), ast_strlen_zero, ast_verb, mgcp_subchannel::callid, mgcp_endpoint::callwaiting, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, cops_gate::deltimer, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, mgcp_subchannel::gate, GATE_ALLOC_PROGRESS, GATE_ALLOCATED, GATE_DEL, cops_gate::gate_open, cops_gate::gate_remove, cops_gate::got_dq_gi, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::lock, mgcp_subchannel::magic, MGCP_CX_INACTIVE, MGCP_CX_RECVONLY, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_set_owner(), MGCP_SUBCHANNEL_MAGIC, name, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::ncs, mgcp_subchannel::next, NULL, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_endpoint::pktcgatealloc, RAII_VAR, mgcp_subchannel::rtp, S_COR, ast_module_info::self, cops_gate::state, sub, mgcp_endpoint::sub, cops_gate::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

903 {
905  struct mgcp_endpoint *p = sub->parent;
906 
907  ast_debug(1, "mgcp_hangup(%s)\n", ast_channel_name(ast));
908  if (!ast_channel_tech_pvt(ast)) {
909  ast_debug(1, "Asked to hangup channel not connected\n");
910  return 0;
911  }
912  if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
913  ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n");
914  return 0;
915  }
916  ast_mutex_lock(&sub->lock);
917  ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast_channel_name(ast), p->name, p->parent->name);
918 
919  if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
920  /* check whether other channel is active. */
921  if (!sub->next->owner) {
922  if (p->dtmfmode & MGCP_DTMF_HYBRID) {
923  p->dtmfmode &= ~MGCP_DTMF_INBAND;
924  }
925  ast_debug(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
926  ast_dsp_free(p->dsp);
927  p->dsp = NULL;
928  }
929  }
930 
931  mgcp_set_owner(sub, NULL);
932 
933  /* for deleting gate */
934  if (p->pktcgatealloc && sub->gate) {
935  sub->gate->gate_open = NULL;
936  sub->gate->gate_remove = NULL;
937  sub->gate->got_dq_gi = NULL;
938  sub->gate->tech_pvt = NULL;
939  if (sub->gate->state == GATE_ALLOC_PROGRESS || sub->gate->state == GATE_ALLOCATED) {
940  ast_pktccops_gate_alloc(GATE_DEL, sub->gate, 0, 0, 0, 0, 0, 0, NULL, NULL);
941  } else {
942  sub->gate->deltimer = time(NULL) + 5;
943  }
944  sub->gate = NULL;
945  }
946 
947  if (!ast_strlen_zero(sub->cxident)) {
949  }
950  sub->cxident[0] = '\0';
951  if ((sub == p->sub) && sub->next->owner) {
953 
954  if (p->hookstate == MGCP_OFFHOOK) {
955  if (sub->next->owner && bridged) {
956  /* ncs fix! */
957  transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"),
958  S_COR(ast_channel_caller(bridged)->id.number.valid, ast_channel_caller(bridged)->id.number.str, ""),
959  S_COR(ast_channel_caller(bridged)->id.name.valid, ast_channel_caller(bridged)->id.name.str, ""));
960  }
961  } else {
962  /* set our other connection as the primary and swith over to it */
963  p->sub = sub->next;
966  if (sub->next->owner && bridged) {
968  S_COR(ast_channel_caller(bridged)->id.number.valid, ast_channel_caller(bridged)->id.number.str, ""),
969  S_COR(ast_channel_caller(bridged)->id.name.valid, ast_channel_caller(bridged)->id.name.str, ""));
970  }
971  }
972 
973  } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
974  transmit_notify_request(sub, p->ncs ? "" : "L/v");
975  } else if (p->hookstate == MGCP_OFFHOOK) {
976  transmit_notify_request(sub, "L/ro");
977  } else {
978  transmit_notify_request(sub, "");
979  }
980 
982  sub->alreadygone = 0;
983  sub->outgoing = 0;
984  sub->cxmode = MGCP_CX_INACTIVE;
985  sub->callid[0] = '\0';
986  if (p) {
987  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
988  }
989  /* Reset temporary destination */
990  memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
991  if (sub->rtp) {
993  sub->rtp = NULL;
994  }
995 
997 
998  if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
999  p->hidecallerid = 0;
1000  if (p->hascallwaiting && !p->callwaiting) {
1001  ast_verb(3, "Enabling call waiting on %s\n", ast_channel_name(ast));
1002  p->callwaiting = -1;
1003  }
1004  if (has_voicemail(p)) {
1005  ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
1006  ast_channel_name(ast), p->name, p->parent->name);
1007  transmit_notify_request(sub, "L/vmwi(+)");
1008  } else {
1009  ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
1010  ast_channel_name(ast), p->name, p->parent->name);
1011  transmit_notify_request(sub, "L/vmwi(-)");
1012  }
1013  }
1014  ast_mutex_unlock(&sub->lock);
1015  return 0;
1016 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
Main Channel structure associated with a channel.
struct cops_gate * gate
Definition: chan_mgcp.c:322
char callid[80]
Definition: chan_mgcp.c:313
int hascallwaiting
Definition: chan_mgcp.c:353
int state
Definition: pktccops.h:59
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct cops_gate * ast_pktccops_gate_alloc(int cmd, struct cops_gate *gate, uint32_t mta, uint32_t actcount, float bitrate, uint32_t psize, uint32_t ssip, uint16_t ssport, int(*const got_dq_gi)(struct cops_gate *gate), int(*const gate_remove)(struct cops_gate *gate))
Definition: res_pktccops.c:468
static void mgcp_set_owner(struct mgcp_subchannel *sub, struct ast_channel *chan)
Definition: chan_mgcp.c:1222
int hidecallerid
Definition: chan_mgcp.c:362
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
char dtmf_buf[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:343
time_t deltimer
Definition: pktccops.h:62
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:120
ast_mutex_t lock
Definition: chan_mgcp.c:304
static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
Definition: chan_mgcp.c:2527
struct sockaddr_in tmpdest
Definition: chan_mgcp.c:309
#define ast_mutex_lock(a)
Definition: lock.h:187
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
#define NULL
Definition: resample.c:96
void * tech_pvt
Definition: pktccops.h:67
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
#define ast_strlen_zero(foo)
Definition: strings.h:52
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char name[80]
Definition: chan_mgcp.c:334
struct ast_module * self
Definition: module.h:342
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:327
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
struct ast_channel * owner
Definition: chan_mgcp.c:306
#define MGCP_DTMF_HYBRID
Definition: chan_mgcp.c:121
char name[80]
Definition: chan_mgcp.c:401
static int transmit_connection_del(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2690
struct ast_dsp * dsp
Definition: chan_mgcp.c:388
int pktcgatealloc
Definition: chan_mgcp.c:366
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
int(* gate_open)(struct cops_gate *gate)
Definition: pktccops.h:66
char cxident[80]
Definition: chan_mgcp.c:312
static const char name[]
Definition: cdr_mysql.c:74
int(* gate_remove)(struct cops_gate *gate)
Definition: pktccops.h:65
char magic[6]
Definition: chan_mgcp.c:303
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:458
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
static int has_voicemail(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:490
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: channel.c:10765
const char * ast_channel_name(const struct ast_channel *chan)
struct stasis_forward * sub
Definition: res_corosync.c:240
#define MGCP_CX_INACTIVE
Definition: chan_mgcp.c:136
#define MGCP_SUBCHANNEL_MAGIC
Definition: chan_mgcp.c:302
static int transmit_modify_request(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2572
#define MGCP_CX_RECVONLY
Definition: chan_mgcp.c:131
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
int(* got_dq_gi)(struct cops_gate *gate)
Definition: pktccops.h:64
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_indicate()

static int mgcp_indicate ( struct ast_channel ast,
int  ind,
const void *  data,
size_t  datalen 
)
static

Definition at line 1438 of file chan_mgcp.c.

References ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log, ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_change_source(), ast_rtp_instance_update_source(), control2str(), mgcp_subchannel::lock, LOG_WARNING, mgcp_endpoint::ncs, NULL, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, sub, transmit_modify_request(), and transmit_notify_request().

1439 {
1440  struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
1441  int res = 0;
1442 
1443  ast_debug(3, "MGCP asked to indicate %d '%s' condition on channel %s\n",
1444  ind, control2str(ind), ast_channel_name(ast));
1445  ast_mutex_lock(&sub->lock);
1446  switch(ind) {
1447  case AST_CONTROL_RINGING:
1448 #ifdef DLINK_BUGGY_FIRMWARE
1449  transmit_notify_request(sub, "rt");
1450 #else
1451  if (!sub->sdpsent) { /* will hide the inband progress!!! */
1452  transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt");
1453  }
1454 #endif
1455  break;
1456  case AST_CONTROL_BUSY:
1457  transmit_notify_request(sub, "L/bz");
1458  break;
1460  /* We do not currently support resetting of the Interdigit Timer, so treat
1461  * Incomplete control frames as a congestion response
1462  */
1464  transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg");
1465  break;
1466  case AST_CONTROL_HOLD:
1467  ast_moh_start(ast, data, NULL);
1468  break;
1469  case AST_CONTROL_UNHOLD:
1470  ast_moh_stop(ast);
1471  break;
1472  case AST_CONTROL_SRCUPDATE:
1474  break;
1475  case AST_CONTROL_SRCCHANGE:
1477  break;
1478  case AST_CONTROL_PROGRESS:
1481  case -1:
1482  transmit_notify_request(sub, "");
1483  break;
1484  default:
1485  ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
1486  /* fallthrough */
1488  res = -1;
1489  }
1490  ast_mutex_unlock(&sub->lock);
1491  return res;
1492 }
void ast_rtp_instance_change_source(struct ast_rtp_instance *instance)
Indicate a new source of audio has dropped in and the ssrc should change.
Definition: rtp_engine.c:2160
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define LOG_WARNING
Definition: logger.h:274
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7876
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7866
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
const char * ast_channel_name(const struct ast_channel *chan)
struct stasis_forward * sub
Definition: res_corosync.c:240
static char * control2str(int ind)
Definition: chan_mgcp.c:1406
static int transmit_modify_request(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2572
void ast_rtp_instance_update_source(struct ast_rtp_instance *instance)
Indicate that the RTP marker bit should be set on an RTP stream.
Definition: rtp_engine.c:2151
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_new()

static struct ast_channel* mgcp_new ( struct mgcp_subchannel sub,
int  state,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor 
)
static

Definition at line 1494 of file chan_mgcp.c.

References mgcp_endpoint::accountcode, mgcp_endpoint::adsi, mgcp_endpoint::amaflags, ast_party_caller::ani, ao2_ref, AST_ADSI_UNAVAILABLE, ast_channel_adsicpe_set(), ast_channel_alloc, ast_channel_amaflags_set(), ast_channel_caller(), ast_channel_callgroup_set(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_nativeformats_set(), ast_channel_pickupgroup_set(), ast_channel_priority_set(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_writeformat(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_unlock, ast_dsp_new(), ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_format_cap_alloc, ast_format_cap_append_from_cap(), ast_format_cap_count(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_format(), ast_get_encoded_str(), ast_hangup(), ast_jb_configure(), ast_log, AST_MEDIA_TYPE_UNKNOWN, ast_module_ref, ast_pbx_start(), ast_rtp_instance_fd(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero, ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callgroup, mgcp_endpoint::cap, mgcp_endpoint::chanvars, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, mgcp_endpoint::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DIGIT_DETECT, mgcp_endpoint::dtmfmode, mgcp_endpoint::exten, global_jbconf, mgcp_subchannel::id, mgcp_endpoint::language, LOG_ERROR, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_set_owner(), ast_variable::name, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::next, NULL, ast_party_id::number, mgcp_subchannel::parent, mgcp_endpoint::parent, pbx_builtin_setvar_helper(), mgcp_endpoint::pickupgroup, mgcp_subchannel::rtp, ast_module_info::self, ast_party_number::str, tmp(), ast_party_number::valid, and ast_variable::value.

Referenced by handle_hd_hf(), and mgcp_request().

1495 {
1496  struct ast_format_cap *caps = NULL;
1497  struct ast_channel *tmp;
1498  struct ast_variable *v = NULL;
1499  struct mgcp_endpoint *i = sub->parent;
1500  struct ast_format *tmpfmt;
1501 
1503  if (!caps) {
1504  ast_log(LOG_ERROR, "Format capabilities could not be created\n");
1505  return NULL;
1506  }
1507  tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
1508  if (!tmp) {
1509  ast_log(LOG_WARNING, "Channel could not be created\n");
1510  ao2_ref(caps, -1);
1511  return NULL;
1512  }
1513 
1516  if (ast_format_cap_count(i->cap)) {
1518  } else {
1520  }
1521  ast_channel_nativeformats_set(tmp, caps);
1522  ao2_ref(caps, -1);
1523  if (sub->rtp) {
1524  ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
1525  }
1527  i->dsp = ast_dsp_new();
1529  /* this is to prevent clipping of dtmf tones during dsp processing */
1531  } else {
1532  i->dsp = NULL;
1533  }
1534  if (state == AST_STATE_RING) {
1535  ast_channel_rings_set(tmp, 1);
1536  }
1537 
1539  ast_channel_set_writeformat(tmp, tmpfmt);
1540  ast_channel_set_rawwriteformat(tmp, tmpfmt);
1541  ast_channel_set_readformat(tmp, tmpfmt);
1542  ast_channel_set_rawreadformat(tmp, tmpfmt);
1543  ao2_ref(tmpfmt, -1);
1544  ast_channel_tech_pvt_set(tmp, sub);
1545  if (!ast_strlen_zero(i->language))
1546  ast_channel_language_set(tmp, i->language);
1547  if (!ast_strlen_zero(i->accountcode))
1548  ast_channel_accountcode_set(tmp, i->accountcode);
1549  if (i->amaflags)
1551  mgcp_set_owner(sub, tmp);
1555  ast_channel_call_forward_set(tmp, i->call_forward);
1557  ast_channel_exten_set(tmp, i->exten);
1558  /* Don't use ast_set_callerid() here because it will
1559  * generate a needless NewCallerID event */
1560  if (!ast_strlen_zero(i->cid_num)) {
1561  ast_channel_caller(tmp)->ani.number.valid = 1;
1563  }
1564 
1565  if (!i->adsi) {
1567  }
1568  ast_channel_priority_set(tmp, 1);
1569 
1570  /* Set channel variables for this call from configuration */
1571  for (v = i->chanvars ; v ; v = v->next) {
1572  char valuebuf[1024];
1573  pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
1574  }
1575 
1576  if (sub->rtp) {
1578  }
1579 
1581  ast_channel_unlock(tmp);
1582 
1583  if (state != AST_STATE_DOWN) {
1584  if (ast_pbx_start(tmp)) {
1585  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
1586  ast_hangup(tmp);
1587  tmp = NULL;
1588  }
1589  }
1590  ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
1592 
1593  return tmp;
1594 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
struct ast_variable * next
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
Main Channel structure associated with a channel.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:340
char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:341
char * ast_get_encoded_str(const char *stream, char *result, size_t result_len)
Decode a stream of encoded control or extended ASCII characters.
Definition: main/app.c:3002
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
static void mgcp_set_owner(struct mgcp_subchannel *sub, struct ast_channel *chan)
Definition: chan_mgcp.c:1222
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
#define LOG_WARNING
Definition: logger.h:274
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
static struct ast_format_cap * global_capability
Definition: chan_mgcp.c:235
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
static int tmp()
Definition: bt_open.c:389
Structure for variables, used for configurations and for channel variables.
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:120
char call_forward[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:344
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
Definition of a media format.
Definition: format.c:43
ast_group_t pickupgroup
Definition: chan_mgcp.c:351
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
const char * ast_state2str(enum ast_channel_state)
Gives the string form of a given channel state.
Definition: channel.c:642
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
char language[MAX_LANGUAGE]
Definition: chan_mgcp.c:339
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
#define ast_log
Definition: astobj2.c:42
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
char name[80]
Definition: chan_mgcp.c:334
struct ast_module * self
Definition: module.h:342
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:428
void ast_channel_rings_set(struct ast_channel *chan, int value)
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
struct ast_variable * chanvars
Definition: chan_mgcp.c:394
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define MGCP_DTMF_HYBRID
Definition: chan_mgcp.c:121
char name[80]
Definition: chan_mgcp.c:401
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
static struct ast_channel_tech mgcp_tech
Definition: chan_mgcp.c:472
char context[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:338
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
ast_group_t callgroup
Definition: chan_mgcp.c:350
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_mgcp.c:336
struct ast_dsp * dsp
Definition: chan_mgcp.c:388
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
char exten[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:337
#define LOG_ERROR
Definition: logger.h:285
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
static struct ast_jb_conf global_jbconf
Definition: chan_mgcp.c:114
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1755
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
Definition: rtp_engine.c:2192
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2431
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:593
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_channel_context_set(struct ast_channel *chan, const char *value)
const char * ast_channel_name(const struct ast_channel *chan)
#define DSP_DIGITMODE_NOQUELCH
Definition: dsp.h:34
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
void ast_channel_priority_set(struct ast_channel *chan, int value)
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1844
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:443

◆ mgcp_pktcgate_open()

static int mgcp_pktcgate_open ( struct cops_gate gate)
static

Definition at line 2435 of file chan_mgcp.c.

References ast_debug, ast_mutex_lock, ast_mutex_unlock, cops_gate::gateid, mgcp_subchannel::lock, NULL, mgcp_subchannel::sdpsent, sub, cops_gate::tech_pvt, and transmit_modify_with_sdp().

Referenced by mgcp_alloc_pktcgate().

2436 {
2437  struct mgcp_subchannel *sub = gate->tech_pvt;
2438  if (!sub) {
2439  return 1;
2440  }
2441  ast_mutex_lock(&sub->lock);
2442  ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid);
2443  if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0);
2444  ast_mutex_unlock(&sub->lock);
2445  return 1;
2446 }
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
void * tech_pvt
Definition: pktccops.h:67
static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs)
Definition: chan_mgcp.c:2301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
uint32_t gateid
Definition: pktccops.h:55
struct stasis_forward * sub
Definition: res_corosync.c:240
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_pktcgate_remove()

static int mgcp_pktcgate_remove ( struct cops_gate gate)
static

Definition at line 2412 of file chan_mgcp.c.

References AST_CAUSE_REQUESTED_CHAN_UNAVAIL, ast_channel_unlock, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), mgcp_subchannel::gate, GATE_CLOSED, cops_gate::gateid, mgcp_endpoint::hangupongateremove, mgcp_subchannel::lock, NULL, mgcp_subchannel::owner, mgcp_subchannel::parent, cops_gate::state, sub, and cops_gate::tech_pvt.

Referenced by mgcp_alloc_pktcgate().

2413 {
2414  struct mgcp_subchannel *sub = gate->tech_pvt;
2415 
2416  if (!sub) {
2417  return 1;
2418  }
2419 
2420  ast_mutex_lock(&sub->lock);
2421  ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid);
2422  if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) {
2423  sub->gate = NULL;
2424  if (sub->owner) {
2426  ast_channel_unlock(sub->owner);
2427  }
2428  } else {
2429  sub->gate = NULL;
2430  }
2431  ast_mutex_unlock(&sub->lock);
2432  return 1;
2433 }
struct cops_gate * gate
Definition: chan_mgcp.c:322
int state
Definition: pktccops.h:59
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
void * tech_pvt
Definition: pktccops.h:67
int hangupongateremove
Definition: chan_mgcp.c:367
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
struct ast_channel * owner
Definition: chan_mgcp.c:306
uint32_t gateid
Definition: pktccops.h:55
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
#define AST_CAUSE_REQUESTED_CHAN_UNAVAIL
Definition: causes.h:124
struct stasis_forward * sub
Definition: res_corosync.c:240
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_postrequest()

static int mgcp_postrequest ( struct mgcp_endpoint p,
struct mgcp_subchannel sub,
char *  data,
int  len,
unsigned int  seqno 
)
static

Definition at line 699 of file chan_mgcp.c.

References __mgcp_xmit(), ast_free, ast_malloc, ast_mutex_lock, ast_mutex_unlock, ast_sched_add(), ast_tvnow(), mgcp_message::buf, DEFAULT_RETRANS, mgcp_message::expire, mgcp_message::len, len(), mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_message::next, NULL, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_endpoint::parent, mgcp_message::retrans, retrans_pkt(), mgcp_gateway::retransid, mgcp_message::seqno, and sub.

Referenced by find_command(), and send_request().

701 {
702  struct mgcp_message *msg;
703  struct mgcp_message *cur;
704  struct mgcp_gateway *gw;
705  struct timeval now;
706 
707  if (!(msg = ast_malloc(sizeof(*msg) + len))) {
708  return -1;
709  }
710  if (!(gw = ((p && p->parent) ? p->parent : NULL))) {
711  ast_free(msg);
712  return -1;
713  }
714 
715  msg->owner_sub = sub;
716  msg->owner_ep = p;
717  msg->seqno = seqno;
718  msg->next = NULL;
719  msg->len = len;
720  msg->retrans = 0;
721  memcpy(msg->buf, data, msg->len);
722 
724  for (cur = gw->msgs; cur && cur->next; cur = cur->next);
725  if (cur) {
726  cur->next = msg;
727  } else {
728  gw->msgs = msg;
729  }
730 
731  now = ast_tvnow();
732  msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS;
733 
734  if (gw->retransid == -1)
737  __mgcp_xmit(gw, msg->buf, msg->len);
738  /* XXX Should schedule retransmission XXX */
739  return 0;
740 }
static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
Definition: chan_mgcp.c:534
struct mgcp_endpoint * owner_ep
Definition: chan_mgcp.c:271
Definition: sched.c:76
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
ast_mutex_t msgs_lock
Definition: chan_mgcp.c:418
mgcp_message: MGCP message for queuing up
Definition: chan_mgcp.c:270
char buf[0]
Definition: chan_mgcp.c:278
struct mgcp_message * msgs
Definition: chan_mgcp.c:417
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define DEFAULT_RETRANS
Definition: chan_mgcp.c:126
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_free(a)
Definition: astmm.h:182
unsigned long expire
Definition: chan_mgcp.c:274
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:565
struct stasis_forward * sub
Definition: res_corosync.c:240
struct mgcp_message * next
Definition: chan_mgcp.c:277
unsigned int seqno
Definition: chan_mgcp.c:275
static int retrans_pkt(const void *data)
Definition: chan_mgcp.c:644
#define ast_mutex_unlock(a)
Definition: lock.h:188
struct mgcp_subchannel * owner_sub
Definition: chan_mgcp.c:272

◆ mgcp_prune_realtime_gateway()

static int mgcp_prune_realtime_gateway ( struct mgcp_gateway g)
static

Definition at line 3760 of file chan_mgcp.c.

References ast_debug, ast_free, ast_mutex_destroy, ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_strlen_zero, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, mgcp_endpoint::dsp, mgcp_gateway::endpoints, mgcp_subchannel::gate, mgcp_gateway::ha, mgcp_subchannel::lock, mgcp_endpoint::lock, MAX_SUBS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::realtime, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, sub, and mgcp_endpoint::sub.

Referenced by do_monitor().

3761 {
3762  struct mgcp_endpoint *enext, *e;
3763  struct mgcp_subchannel *s, *sub;
3764  int i, prune = 1;
3765 
3766  if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) {
3768  return 0;
3769  }
3770 
3771  for (e = g->endpoints; e; e = e->next) {
3772  ast_mutex_lock(&e->lock);
3774  prune = 0;
3775  } else if (e->rqnt_queue || e->cmd_queue) {
3776  prune = 0;
3777  }
3778  s = e->sub;
3779  for (i = 0; (i < MAX_SUBS) && s; i++) {
3780  ast_mutex_lock(&s->lock);
3781  if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) {
3782  prune = 0;
3783  } else if (s->cx_queue) {
3784  prune = 0;
3785  }
3786  s = s->next;
3787  }
3788  }
3789 
3790  for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) {
3791  for (i = 0; (i < MAX_SUBS) && sub; i++) {
3792  s = sub;
3793  sub = sub->next;
3794  ast_mutex_unlock(&s->lock);
3796  if (prune) {
3797  ast_mutex_destroy(&s->lock);
3799  ast_free(s);
3800  }
3801  }
3802  ast_mutex_unlock(&e->lock);
3805  if (prune) {
3806  ast_mutex_destroy(&e->lock);
3809  ast_free(e);
3810  }
3811  }
3812  if (prune) {
3813  ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name);
3814  }
3815  return prune;
3816 }
struct cops_gate * gate
Definition: chan_mgcp.c:322
struct mgcp_request * cx_queue
Definition: chan_mgcp.c:315
ast_mutex_t cmd_queue_lock
Definition: chan_mgcp.c:385
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
#define MAX_SUBS
Definition: chan_mgcp.c:291
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
ast_mutex_t msgs_lock
Definition: chan_mgcp.c:418
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_mutex_trylock(a)
Definition: lock.h:189
struct mgcp_request * rqnt_queue
Definition: chan_mgcp.c:382
struct mgcp_message * msgs
Definition: chan_mgcp.c:417
char name[80]
Definition: chan_mgcp.c:401
struct ast_dsp * dsp
Definition: chan_mgcp.c:388
ast_mutex_t cx_queue_lock
Definition: chan_mgcp.c:316
ast_mutex_t lock
Definition: chan_mgcp.c:333
char cxident[80]
Definition: chan_mgcp.c:312
#define ast_free(a)
Definition: astmm.h:182
ast_mutex_t rqnt_queue_lock
Definition: chan_mgcp.c:383
struct ast_ha * ha
Definition: chan_mgcp.c:409
struct mgcp_request * cmd_queue
Definition: chan_mgcp.c:384
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct stasis_forward * sub
Definition: res_corosync.c:240
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
#define ast_mutex_destroy(a)
Definition: lock.h:186
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_queue_control()

static void mgcp_queue_control ( struct mgcp_subchannel sub,
int  control 
)
static

Definition at line 638 of file chan_mgcp.c.

References AST_FRAME_CONTROL, and mgcp_queue_frame().

Referenced by handle_hd_hf().

639 {
640  struct ast_frame f = { AST_FRAME_CONTROL, { control } };
641  return mgcp_queue_frame(sub, &f);
642 }
static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
Definition: chan_mgcp.c:604
Data structure associated with a single frame of data.

◆ mgcp_queue_frame()

static void mgcp_queue_frame ( struct mgcp_subchannel sub,
struct ast_frame f 
)
static

Definition at line 604 of file chan_mgcp.c.

References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, mgcp_subchannel::lock, and mgcp_subchannel::owner.

Referenced by handle_request(), and mgcp_queue_control().

605 {
606  for (;;) {
607  if (sub->owner) {
608  if (!ast_channel_trylock(sub->owner)) {
609  ast_queue_frame(sub->owner, f);
611  break;
612  } else {
613  DEADLOCK_AVOIDANCE(&sub->lock);
614  }
615  } else {
616  break;
617  }
618  }
619 }
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:374
ast_mutex_t lock
Definition: chan_mgcp.c:304
struct ast_channel * owner
Definition: chan_mgcp.c:306
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1139
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_channel_trylock(chan)
Definition: channel.h:2947

◆ mgcp_queue_hangup()

static void mgcp_queue_hangup ( struct mgcp_subchannel sub)
static

Definition at line 621 of file chan_mgcp.c.

References ast_channel_trylock, ast_channel_unlock, ast_queue_hangup(), DEADLOCK_AVOIDANCE, mgcp_subchannel::lock, and mgcp_subchannel::owner.

Referenced by attempt_transfer(), destroy_endpoint(), handle_request(), handle_response(), and start_rtp().

622 {
623  for (;;) {
624  if (sub->owner) {
625  if (!ast_channel_trylock(sub->owner)) {
626  ast_queue_hangup(sub->owner);
628  break;
629  } else {
630  DEADLOCK_AVOIDANCE(&sub->lock);
631  }
632  } else {
633  break;
634  }
635  }
636 }
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1150
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:374
ast_mutex_t lock
Definition: chan_mgcp.c:304
struct ast_channel * owner
Definition: chan_mgcp.c:306
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_channel_trylock(chan)
Definition: channel.h:2947

◆ mgcp_read()

static struct ast_frame * mgcp_read ( struct ast_channel ast)
static

Definition at line 1230 of file chan_mgcp.c.

References ast_channel_tech_pvt(), ast_mutex_lock, ast_mutex_unlock, mgcp_subchannel::lock, mgcp_rtp_read(), and sub.

1231 {
1232  struct ast_frame *f;
1233  struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
1234  ast_mutex_lock(&sub->lock);
1235  f = mgcp_rtp_read(sub);
1236  ast_mutex_unlock(&sub->lock);
1237  return f;
1238 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
static struct ast_frame * mgcp_rtp_read(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:1181
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
struct stasis_forward * sub
Definition: res_corosync.c:240
Data structure associated with a single frame of data.
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_reload()

static char * mgcp_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4908 of file chan_mgcp.c.

References ast_cli_args::argc, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_verbose(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, LOG_WARNING, mgcp_reload_lock, mgcp_reloading, NULL, restart_monitor(), and ast_cli_entry::usage.

Referenced by reload(), and unload_module().

4909 {
4910  static int deprecated = 0;
4911 
4912  if (e) {
4913  switch (cmd) {
4914  case CLI_INIT:
4915  e->command = "mgcp reload";
4916  e->usage =
4917  "Usage: mgcp reload\n"
4918  " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n";
4919  return NULL;
4920  case CLI_GENERATE:
4921  return NULL;
4922  }
4923  }
4924 
4925  if (!deprecated && a && a->argc > 0) {
4926  ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n");
4927  deprecated = 1;
4928  }
4929 
4931  if (mgcp_reloading) {
4932  ast_verbose("Previous mgcp reload not yet done\n");
4933  } else {
4934  mgcp_reloading = 1;
4935  }
4937  restart_monitor();
4938  return CLI_SUCCESS;
4939 }
static int restart_monitor(void)
Definition: chan_mgcp.c:3936
const int argc
Definition: cli.h:160
#define LOG_WARNING
Definition: logger.h:274
Definition: cli.h:152
#define ast_mutex_lock(a)
Definition: lock.h:187
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
static int mgcp_reloading
Definition: chan_mgcp.c:427
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static ast_mutex_t mgcp_reload_lock
Definition: chan_mgcp.c:426
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_request()

static struct ast_channel * mgcp_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor,
const char *  dest,
int *  cause 
)
static

Definition at line 3965 of file chan_mgcp.c.

References AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_copy_string(), ast_format_cap_get_names(), ast_format_cap_iscompatible(), AST_FORMAT_CAP_NAMES_LEN, ast_log, ast_mutex_unlock, AST_STATE_DOWN, ast_str_alloca, ast_strlen_zero, ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callwaiting, mgcp_endpoint::dnd, find_subchannel_and_lock(), has_voicemail(), mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_new(), MGCP_ONHOOK, mgcp_subchannel::next, NULL, mgcp_subchannel::owner, mgcp_subchannel::parent, restart_monitor(), sub, tmp(), and transmit_notify_request().

3966 {
3967  struct mgcp_subchannel *sub;
3968  struct ast_channel *tmpc = NULL;
3969  char tmp[256];
3970 
3972  struct ast_str *cap_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
3973  ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n",
3974  ast_format_cap_get_names(cap, &cap_buf));
3975  /*return NULL;*/
3976  }
3977  ast_copy_string(tmp, dest, sizeof(tmp));
3978  if (ast_strlen_zero(tmp)) {
3979  ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
3980  return NULL;
3981  }
3982  if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) {
3983  ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
3984  *cause = AST_CAUSE_UNREGISTERED;
3985  return NULL;
3986  }
3987 
3988  ast_verb(3, "MGCP mgcp_request(%s)\n", tmp);
3989  ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
3990  sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
3991  /* Must be busy */
3992  if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
3993  ((!sub->parent->callwaiting) && (sub->owner)) ||
3994  (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
3995  if (sub->parent->hookstate == MGCP_ONHOOK) {
3996  if (has_voicemail(sub->parent)) {
3997  transmit_notify_request(sub,"L/vmwi(+)");
3998  } else {
3999  transmit_notify_request(sub,"L/vmwi(-)");
4000  }
4001  }
4002  *cause = AST_CAUSE_BUSY;
4003  ast_mutex_unlock(&sub->lock);
4004  return NULL;
4005  }
4006  tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, assignedids, requestor);
4007  ast_mutex_unlock(&sub->lock);
4008  if (!tmpc)
4009  ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
4010  restart_monitor();
4011  return tmpc;
4012 }
Main Channel structure associated with a channel.
static int restart_monitor(void)
Definition: chan_mgcp.c:3936
#define LOG_WARNING
Definition: logger.h:274
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
static struct ast_format_cap * global_capability
Definition: chan_mgcp.c:235
static int tmp()
Definition: bt_open.c:389
char call_forward[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:344
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_str_alloca(init_len)
Definition: strings.h:800
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
#define NULL
Definition: resample.c:96
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
static struct ast_channel * mgcp_new(struct mgcp_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
Definition: chan_mgcp.c:1494
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
struct ast_channel * owner
Definition: chan_mgcp.c:306
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define LOG_NOTICE
Definition: logger.h:263
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:736
#define AST_CAUSE_UNREGISTERED
Definition: causes.h:153
static struct mgcp_subchannel * find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
Definition: chan_mgcp.c:1777
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
static int has_voicemail(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:490
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define AST_CAUSE_BUSY
Definition: causes.h:148
struct stasis_forward * sub
Definition: res_corosync.c:240
#define ast_mutex_unlock(a)
Definition: lock.h:188
int ast_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if any joint capabilities exist between two capabilities structures.
Definition: format_cap.c:655

◆ mgcp_rtp_read()

static struct ast_frame* mgcp_rtp_read ( struct mgcp_subchannel sub)
static

Definition at line 1181 of file chan_mgcp.c.

References ao2_ref, ast_channel_nativeformats(), ast_channel_nativeformats_set(), ast_channel_readformat(), ast_channel_writeformat(), ast_debug, ast_dsp_process(), ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_iscompatible_format(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log, ast_null_frame, ast_rtp_instance_read(), ast_set_read_format(), ast_set_write_format(), mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, ast_frame_subclass::format, ast_frame::frametype, LOG_NOTICE, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_frame::subclass.

Referenced by mgcp_read().

1182 {
1183  /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
1184  struct ast_frame *f;
1185 
1186  f = ast_rtp_instance_read(sub->rtp, 0);
1187  /* Don't send RFC2833 if we're not supposed to */
1188  if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
1189  return &ast_null_frame;
1190  if (sub->owner) {
1191  /* We already hold the channel lock */
1192  if (f->frametype == AST_FRAME_VOICE) {
1194  struct ast_format_cap *caps;
1195 
1196  ast_debug(1, "Oooh, format changed to %s\n", ast_format_get_name(f->subclass.format));
1197 
1199  if (caps) {
1200  ast_format_cap_append(caps, f->subclass.format, 0);
1202  ao2_ref(caps, -1);
1203  } else {
1204  return &ast_null_frame;
1205  }
1206 
1209  }
1210  /* Courtesy fearnor aka [email protected] */
1211  if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
1212 #if 0
1213  ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
1214 #endif
1215  f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
1216  }
1217  }
1218  }
1219  return f;
1220 }
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Definition: dsp.c:1494
#define MGCP_DTMF_RFC2833
Definition: chan_mgcp.c:119
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:120
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define AST_FRAME_DTMF
struct ast_frame_subclass subclass
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if ast_format is within the capabilities of the ast_format_cap object.
Definition: format_cap.c:583
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_channel * owner
Definition: chan_mgcp.c:306
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5890
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
struct ast_dsp * dsp
Definition: chan_mgcp.c:388
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define LOG_NOTICE
Definition: logger.h:263
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
struct ast_frame ast_null_frame
Definition: main/frame.c:79
Data structure associated with a single frame of data.
enum ast_frame_type frametype
struct ast_format * format
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:578

◆ mgcp_senddigit_begin()

static int mgcp_senddigit_begin ( struct ast_channel ast,
char  digit 
)
static

Definition at line 1298 of file chan_mgcp.c.

References ast_channel_tech_pvt(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_begin(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, and sub.

1299 {
1300  struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
1301  struct mgcp_endpoint *p = sub->parent;
1302  int res = 0;
1303 
1304  ast_mutex_lock(&sub->lock);
1306  ast_debug(1, "Sending DTMF using inband/hybrid\n");
1307  res = -1; /* Let asterisk play inband indications */
1308  } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
1309  ast_debug(1, "Sending DTMF using RFC2833\n");
1311  } else {
1312  ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
1313  }
1314  ast_mutex_unlock(&sub->lock);
1315 
1316  return res;
1317 }
char digit
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define MGCP_DTMF_RFC2833
Definition: chan_mgcp.c:119
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:120
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define MGCP_DTMF_HYBRID
Definition: chan_mgcp.c:121
#define LOG_ERROR
Definition: logger.h:285
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
Begin sending a DTMF digit.
Definition: rtp_engine.c:2081
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
struct stasis_forward * sub
Definition: res_corosync.c:240
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcp_senddigit_end()

static int mgcp_senddigit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
)
static

Definition at line 1319 of file chan_mgcp.c.

References ast_channel_tech_pvt(), ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_end(), digit, mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_endpoint::ncs, mgcp_subchannel::parent, mgcp_subchannel::rtp, sub, tmp(), and transmit_notify_request().

1320 {
1321  struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
1322  struct mgcp_endpoint *p = sub->parent;
1323  int res = 0;
1324  char tmp[4];
1325 
1326  ast_mutex_lock(&sub->lock);
1328  ast_debug(1, "Stopping DTMF using inband/hybrid\n");
1329  res = -1; /* Tell Asterisk to stop inband indications */
1330  } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
1331  ast_debug(1, "Stopping DTMF using RFC2833\n");
1332  if (sub->parent->ncs) {
1333  tmp[0] = digit;
1334  tmp[1] = '\0';
1335  } else {
1336  tmp[0] = 'D';
1337  tmp[1] = '/';
1338  tmp[2] = digit;
1339  tmp[3] = '\0';
1340  }
1341  transmit_notify_request(sub, tmp);
1343  } else {
1344  ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
1345  }
1346  ast_mutex_unlock(&sub->lock);
1347 
1348  return res;
1349 }
char digit
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define MGCP_DTMF_RFC2833
Definition: chan_mgcp.c:119
static int tmp()
Definition: bt_open.c:389
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:120
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define MGCP_DTMF_HYBRID
Definition: chan_mgcp.c:121
#define LOG_ERROR
Definition: logger.h:285
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
struct stasis_forward * sub
Definition: res_corosync.c:240
#define ast_mutex_unlock(a)
Definition: lock.h:188
int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit)
Stop sending a DTMF digit.
Definition: rtp_engine.c:2095

◆ mgcp_set_owner()

static void mgcp_set_owner ( struct mgcp_subchannel sub,
struct ast_channel chan 
)
static

Definition at line 1222 of file chan_mgcp.c.

References ast_channel_uniqueid(), ast_rtp_instance_set_channel_id(), mgcp_subchannel::owner, and mgcp_subchannel::rtp.

Referenced by mgcp_fixup(), mgcp_hangup(), mgcp_new(), and unalloc_sub().

1223 {
1224  sub->owner = chan;
1225  if (sub->rtp) {
1227  }
1228 }
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
Definition: rtp_engine.c:553
struct ast_channel * owner
Definition: chan_mgcp.c:306
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308

◆ mgcp_set_rtp_peer()

static int mgcp_set_rtp_peer ( struct ast_channel chan,
struct ast_rtp_instance rtp,
struct ast_rtp_instance vrtp,
struct ast_rtp_instance trtp,
const struct ast_format_cap cap,
int  nat_active 
)
static

Definition at line 4491 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_channel_tech_pvt(), sub, and transmit_modify_with_sdp().

4492 {
4493  /* XXX Is there such thing as video support with MGCP? XXX */
4494  struct mgcp_subchannel *sub;
4495  sub = ast_channel_tech_pvt(chan);
4496  if (sub && !sub->alreadygone) {
4497  transmit_modify_with_sdp(sub, rtp, cap);
4498  return 0;
4499  }
4500  return -1;
4501 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs)
Definition: chan_mgcp.c:2301
struct stasis_forward * sub
Definition: res_corosync.c:240

◆ mgcp_ss()

static void* mgcp_ss ( void *  data)
static

Definition at line 3000 of file chan_mgcp.c.

References ao2_cleanup, ast_canmatch_extension(), ast_channel_caller(), ast_channel_context(), ast_channel_dialed(), ast_channel_exten_set(), ast_channel_get_bridge_channel(), ast_channel_language(), ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_copy_string(), ast_db_put(), ast_debug, ast_exists_extension(), ast_get_chan_features_pickup_config(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log, ast_matchmore_extension(), AST_MAX_EXTENSION, ast_parking_blind_transfer_park(), ast_parking_is_exten_park(), ast_parking_provider_registered(), ast_pbx_run(), ast_pickup_call(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strdup, ast_strdupa, ast_strlen_zero, ast_verb, ast_waitfordigit(), mgcp_endpoint::call_forward, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::data, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, exten, firstdigittimeout, gendigittimeout, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::lastcallerid, len(), LOG_ERROR, LOG_WARNING, matchdigittimeout, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::ncs, mgcp_subchannel::next, NULL, ast_party_dialed::number, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_endpoint::parent, RAII_VAR, S_COR, start_rtp(), ast_party_dialed::str, sub, timeout, and transmit_notify_request().

Referenced by handle_hd_hf().

3001 {
3002  struct ast_channel *chan = data;
3003  struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
3004  struct mgcp_endpoint *p = sub->parent;
3005  /* char exten[AST_MAX_EXTENSION] = ""; */
3006  int len = 0;
3007  int timeout = firstdigittimeout;
3008  int res= 0;
3009  int getforward = 0;
3010  int loop_pause = 100;
3011  RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
3012  const char *pickupexten;
3013 
3014  len = strlen(p->dtmf_buf);
3015 
3016  ast_channel_lock(chan);
3017  pickup_cfg = ast_get_chan_features_pickup_config(chan);
3018  if (!pickup_cfg) {
3019  ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
3020  pickupexten = "";
3021  } else {
3022  pickupexten = ast_strdupa(pickup_cfg->pickupexten);
3023  }
3024  ast_channel_unlock(chan);
3025 
3026  while (len < AST_MAX_EXTENSION - 1) {
3027  ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name);
3028  res = 1; /* Assume that we will get a digit */
3029  while (strlen(p->dtmf_buf) == len) {
3030  ast_safe_sleep(chan, loop_pause);
3031  timeout -= loop_pause;
3032  if (timeout <= 0){
3033  res = 0;
3034  break;
3035  }
3036  res = 1;
3037  }
3038 
3039  timeout = 0;
3040  len = strlen(p->dtmf_buf);
3041 
3043  /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
3044  ast_indicate(chan, -1);
3045  } else {
3046  /* XXX Redundant? We should already be playing dialtone */
3047  /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
3048  transmit_notify_request(sub, "L/dl");
3049  }
3050  if (ast_exists_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1, p->cid_num)) {
3051  if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1, p->cid_num)) {
3052  if (getforward) {
3053  /* Record this as the forwarding extension */
3054  ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward));
3055  ast_verb(3, "Setting call forward to '%s' on channel %s\n",
3056  p->call_forward, ast_channel_name(chan));
3057  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3058  transmit_notify_request(sub, "L/sl");
3059  if (res)
3060  break;
3061  usleep(500000);
3062  /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
3063  ast_indicate(chan, -1);
3064  sleep(1);
3065  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3066  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
3067  transmit_notify_request(sub, "L/dl");
3068  len = 0;
3069  getforward = 0;
3070  } else {
3071  /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
3072  ast_indicate(chan, -1);
3073  ast_channel_lock(chan);
3074  ast_channel_exten_set(chan, p->dtmf_buf);
3076  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3077  ast_set_callerid(chan,
3078  p->hidecallerid ? "" : p->cid_num,
3079  p->hidecallerid ? "" : p->cid_name,
3080  ast_channel_caller(chan)->ani.number.valid ? NULL : p->cid_num);
3082  ast_channel_unlock(chan);
3083  if (p->dtmfmode & MGCP_DTMF_HYBRID) {
3084  p->dtmfmode |= MGCP_DTMF_INBAND;
3085  ast_indicate(chan, -1);
3086  }
3087  res = ast_pbx_run(chan);
3088  if (res) {
3089  ast_log(LOG_WARNING, "PBX exited non-zero\n");
3090  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
3091  /*transmit_notify_request(p, "nbz", 1);*/
3092  transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
3093  }
3094  return NULL;
3095  }
3096  } else {
3097  /* It's a match, but they just typed a digit, and there is an ambiguous match,
3098  so just set the timeout to matchdigittimeout and wait some more */
3099  timeout = matchdigittimeout;
3100  }
3101  } else if (res == 0) {
3102  ast_debug(1, "not enough digits (and no ambiguous match)...\n");
3103  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
3104  transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
3105  /*dahdi_wait_event(p->subs[index].zfd);*/
3106  ast_hangup(chan);
3107  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3108  return NULL;
3109  } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) {
3110  ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
3111  /* Disable call waiting if enabled */
3112  p->callwaiting = 0;
3113  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3114  transmit_notify_request(sub, "L/sl");
3115  len = 0;
3116  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3117  timeout = firstdigittimeout;
3118  } else if (!strcmp(p->dtmf_buf, pickupexten)) {
3119  /* Scan all channels and see if any there
3120  * ringing channqels with that have call groups
3121  * that equal this channels pickup group
3122  */
3123  if (ast_pickup_call(chan)) {
3124  ast_log(LOG_WARNING, "No call pickup possible...\n");
3125  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
3126  transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
3127  }
3128  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3129  ast_hangup(chan);
3130  return NULL;
3131  } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) {
3132  ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
3133  /* Disable Caller*ID if enabled */
3134  p->hidecallerid = 1;
3135  ast_set_callerid(chan, "", "", NULL);
3136  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3137  transmit_notify_request(sub, "L/sl");
3138  len = 0;
3139  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3140  timeout = firstdigittimeout;
3141  } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) {
3142  res = 0;
3143  if (!ast_strlen_zero(p->lastcallerid)) {
3144  res = ast_say_digit_str(chan, p->lastcallerid, "", ast_channel_language(chan));
3145  }
3146  if (!res)
3147  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3148  transmit_notify_request(sub, "L/sl");
3149  break;
3150  } else if (!strcmp(p->dtmf_buf, "*78")) {
3151  /* Do not disturb */
3152  ast_verb(3, "Enabled DND on channel %s\n", ast_channel_name(chan));
3153  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3154  transmit_notify_request(sub, "L/sl");
3155  p->dnd = 1;
3156  getforward = 0;
3157  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3158  len = 0;
3159  } else if (!strcmp(p->dtmf_buf, "*79")) {
3160  /* Do not disturb */
3161  ast_verb(3, "Disabled DND on channel %s\n", ast_channel_name(chan));
3162  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3163  transmit_notify_request(sub, "L/sl");
3164  p->dnd = 0;
3165  getforward = 0;
3166  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3167  len = 0;
3168  } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) {
3169  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3170  transmit_notify_request(sub, "L/sl");
3171  getforward = 1;
3172  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3173  len = 0;
3174  } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) {
3175  ast_verb(3, "Cancelling call forwarding on channel %s\n", ast_channel_name(chan));
3176  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3177  transmit_notify_request(sub, "L/sl");
3178  memset(p->call_forward, 0, sizeof(p->call_forward));
3179  getforward = 0;
3180  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3181  len = 0;
3183  sub->next->owner) {
3184  RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
3185  /* This is a three way call, the main call being a real channel,
3186  and we're parking the first call. */
3187  ast_channel_lock(chan);
3188  bridge_channel = ast_channel_get_bridge_channel(chan);
3189  ast_channel_unlock(chan);
3190  if (bridge_channel && !ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), p->dtmf_buf, NULL, NULL)) {
3191  ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
3192  }
3193  break;
3194  } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) {
3195  ast_verb(3, "Blacklisting number %s\n", p->lastcallerid);
3196  res = ast_db_put("blacklist", p->lastcallerid, "1");
3197  if (!res) {
3198  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3199  transmit_notify_request(sub, "L/sl");
3200  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3201  len = 0;
3202  }
3203  } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) {
3204  ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
3205  /* Enable Caller*ID if enabled */
3206  p->hidecallerid = 0;
3207  ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
3208  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3209  transmit_notify_request(sub, "L/sl");
3210  len = 0;
3211  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3212  timeout = firstdigittimeout;
3213  } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1,
3214  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
3215  && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
3216  ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf,
3217  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
3218  ast_channel_context(chan));
3219  break;
3220  }
3221  if (!timeout)
3222  timeout = gendigittimeout;
3223  if (len && !ast_ignore_pattern(ast_channel_context(chan), p->dtmf_buf))
3224  /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
3225  ast_indicate(chan, -1);
3226  }
3227 #if 0
3228  for (;;) {
3229  res = ast_waitfordigit(chan, to);
3230  if (!res) {
3231  ast_debug(1, "Timeout...\n");
3232  break;
3233  }
3234  if (res < 0) {
3235  ast_debug(1, "Got hangup...\n");
3236  ast_hangup(chan);
3237  break;
3238  }
3239  exten[pos++] = res;
3240  if (!ast_ignore_pattern(chan->context, exten))
3241  ast_indicate(chan, -1);
3242  if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
3243  if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
3244  to = 3000;
3245  else
3246  to = 8000;
3247  } else
3248  break;
3249  }
3250  if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
3251  ast_copy_string(chan->exten, exten, sizeof(chan->exten)1);
3252  if (!p->rtp) {
3253  start_rtp(p);
3254  }
3256  chan->rings = 1;
3257  if (ast_pbx_run(chan)) {
3258  ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
3259  } else {
3260  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3261  return NULL;
3262  }
3263  }
3264 #endif
3265  ast_hangup(chan);
3266  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3267  return NULL;
3268 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7434
static void start_rtp(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2967
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Definition: pbx.c:4199
#define ast_channel_lock(chan)
Definition: channel.h:2945
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
struct ast_party_dialed::@246 number
Dialed/Called number.
char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:340
static int firstdigittimeout
Definition: chan_mgcp.c:214
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:387
char lastcallerid[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:342
char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:341
int hascallwaiting
Definition: chan_mgcp.c:353
void * ast_channel_tech_pvt(const struct ast_channel *chan)
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4322
int hidecallerid
Definition: chan_mgcp.c:362
#define LOG_WARNING
Definition: logger.h:274
char dtmf_buf[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:343
static int timeout
Definition: cdr_mysql.c:86
int cancallforward
Definition: chan_mgcp.c:357
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:120
char call_forward[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:344
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
Definition: channel.c:8355
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6921
int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data)
Perform a blind transfer to a parking extension.
Definition: parking.c:143
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
const char * data
struct mgcp_subchannel * next
Definition: chan_mgcp.c:323
#define ast_verb(level,...)
Definition: logger.h:463
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4194
#define ast_strlen_zero(foo)
Definition: strings.h:52
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: chan_mgcp.c:334
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
struct ast_channel * owner
Definition: chan_mgcp.c:306
#define MGCP_DTMF_HYBRID
Definition: chan_mgcp.c:121
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char name[80]
Definition: chan_mgcp.c:401
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
static int gendigittimeout
Definition: chan_mgcp.c:217
#define LOG_ERROR
Definition: logger.h:285
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:200
int ast_parking_is_exten_park(const char *context, const char *exten)
Determine if the context/exten is a "parking" extension.
Definition: parking.c:179
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const ast_string_field name
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
int ast_parking_provider_registered(void)
Check whether a parking provider is registered.
Definition: parking.c:241
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel&#39;s bridge pointer.
Definition: channel.c:10783
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2499
Structure that contains information regarding a channel in a bridge.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4759
struct stasis_forward * sub
Definition: res_corosync.c:240
const char * ast_channel_language(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
static int matchdigittimeout
Definition: chan_mgcp.c:220
Configuration relating to call pickup.

◆ mgcp_write()

static int mgcp_write ( struct ast_channel ast,
struct ast_frame frame 
)
static

Definition at line 1240 of file chan_mgcp.c.

References ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_tech_pvt(), ast_channel_writeformat(), ast_debug, ast_format_cap_get_names(), ast_format_cap_iscompatible_format(), AST_FORMAT_CAP_NAMES_LEN, AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_write(), ast_str_alloca, ast_frame_subclass::format, ast_frame::frametype, mgcp_subchannel::gate, GATE_ALLOCATED, mgcp_subchannel::lock, LOG_WARNING, NULL, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, mgcp_endpoint::singlepath, cops_gate::state, sub, mgcp_endpoint::sub, ast_frame::subclass, and transmit_modify_with_sdp().

1241 {
1242  struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
1243  int res = 0;
1244 
1245  if (frame->frametype != AST_FRAME_VOICE) {
1246  if (frame->frametype == AST_FRAME_IMAGE)
1247  return 0;
1248  else {
1249  ast_log(LOG_WARNING, "Can't send %u type frames with MGCP write\n", frame->frametype);
1250  return 0;
1251  }
1252  } else {
1254  struct ast_str *cap_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1255 
1256  ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
1261  /* return -1; */
1262  }
1263  }
1264  if (sub) {
1265  ast_mutex_lock(&sub->lock);
1266  if (!sub->sdpsent && sub->gate) {
1267  if (sub->gate->state == GATE_ALLOCATED) {
1268  ast_debug(1, "GATE ALLOCATED, sending sdp\n");
1269  transmit_modify_with_sdp(sub, NULL, 0);
1270  }
1271  }
1272  if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
1273  if (sub->rtp) {
1274  res = ast_rtp_instance_write(sub->rtp, frame);
1275  }
1276  }
1277  ast_mutex_unlock(&sub->lock);
1278  }
1279  return res;
1280 }
struct cops_gate * gate
Definition: chan_mgcp.c:322
int state
Definition: pktccops.h:59
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define LOG_WARNING
Definition: logger.h:274
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:568
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_str_alloca(init_len)
Definition: strings.h:800
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if ast_format is within the capabilities of the ast_format_cap object.
Definition: format_cap.c:583
static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs)
Definition: chan_mgcp.c:2301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:736
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
struct stasis_forward * sub
Definition: res_corosync.c:240
enum ast_frame_type frametype
struct ast_format * format
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mgcpsock_read()

static int mgcpsock_read ( int *  id,
int  fd,
short  events,
void *  ignore 
)
static

Definition at line 3669 of file chan_mgcp.c.

References ast_debug, ast_free, ast_inet_ntoa(), ast_log, ast_mutex_lock, ast_mutex_unlock, AST_SCHED_DEL, ast_strlen_zero, mgcp_request::data, mgcp_request::endpoint, errno, find_and_retrans(), find_subchannel_and_lock(), handle_request(), handle_response(), mgcp_request::headers, mgcp_request::identifier, mgcp_request::len, len(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcpsock, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, NULL, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_subchannel::parent, mgcp_endpoint::parent, parse(), result, mgcp_gateway::retransid, mgcp_message::seqno, sub, mgcp_request::verb, and mgcp_request::version.

Referenced by do_monitor().

3670 {
3671  struct mgcp_request req;
3672  struct sockaddr_in sin;
3673  struct mgcp_subchannel *sub;
3674  int res;
3675  socklen_t len;
3676  int result;
3677  int ident;
3678  len = sizeof(sin);
3679  memset(&req, 0, sizeof(req));
3680  res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
3681  if (res < 0) {
3682  if (errno != ECONNREFUSED)
3683  ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
3684  return 1;
3685  }
3686  req.data[res] = '\0';
3687  req.len = res;
3688  ast_debug(1, "MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
3689  parse(&req);
3690  if (req.headers < 1) {
3691  /* Must have at least one header */
3692  return 1;
3693  }
3694  if (ast_strlen_zero(req.identifier)) {
3695  ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
3696  return 1;
3697  }
3698 
3699  if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) {
3700  if (result < 200) {
3701  ast_debug(1, "Ignoring provisional response on transaction %d\n", ident);
3702  return 1;
3703  }
3704  /* Try to find who this message is for, if it's important */
3705  sub = find_subchannel_and_lock(NULL, ident, &sin);
3706  if (sub) {
3707  struct mgcp_gateway *gw = sub->parent->parent;
3708  struct mgcp_message *cur, *prev;
3709 
3710  ast_mutex_unlock(&sub->lock);
3711  ast_mutex_lock(&gw->msgs_lock);
3712  for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
3713  if (cur->seqno == ident) {
3714  ast_debug(1, "Got response back on transaction %d\n", ident);
3715  if (prev)
3716  prev->next = cur->next;
3717  else
3718  gw->msgs = cur->next;
3719  break;
3720  }
3721  }
3722 
3723  /* stop retrans timer if the queue is empty */
3724  if (!gw->msgs) {
3726  }
3727 
3729  if (cur) {
3730  handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
3731  ast_free(cur);
3732  return 1;
3733  }
3734 
3735  ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
3736  gw->name, ident);
3737  }
3738  } else {
3739  if (ast_strlen_zero(req.endpoint) ||
3740  ast_strlen_zero(req.version) ||
3741  ast_strlen_zero(req.verb)) {
3742  ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
3743  return 1;
3744  }
3745  /* Process request, with iflock held */
3746  sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
3747  if (sub) {
3748  /* look first to find a matching response in the queue */
3749  if (!find_and_retrans(sub, &req))
3750  /* pass the request off to the currently mastering subchannel */
3751  handle_request(sub, &req, &sin);
3752  ast_mutex_unlock(&sub->lock);
3753  }
3754  }
3755  return 1;
3756 }
static int mgcpsock
Definition: chan_mgcp.c:432
static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp)
Definition: chan_mgcp.c:2797
struct mgcp_endpoint * owner_ep
Definition: chan_mgcp.c:271
#define LOG_WARNING
Definition: logger.h:274
Definition: sched.c:76
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
ast_mutex_t msgs_lock
Definition: chan_mgcp.c:418
#define ast_strlen_zero(foo)
Definition: strings.h:52
mgcp_message: MGCP message for queuing up
Definition: chan_mgcp.c:270
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
struct mgcp_message * msgs
Definition: chan_mgcp.c:417
char name[80]
Definition: chan_mgcp.c:401
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
#define LOG_NOTICE
Definition: logger.h:263
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
#define ast_free(a)
Definition: astmm.h:182
static struct mgcp_subchannel * find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
Definition: chan_mgcp.c:1777
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
Definition: chan_mgcp.c:3639
static PGresult * result
Definition: cel_pgsql.c:88
struct stasis_forward * sub
Definition: res_corosync.c:240
struct mgcp_message * next
Definition: chan_mgcp.c:277
static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
Definition: chan_mgcp.c:3402
unsigned int seqno
Definition: chan_mgcp.c:275
#define ast_mutex_unlock(a)
Definition: lock.h:188
struct mgcp_subchannel * owner_sub
Definition: chan_mgcp.c:272

◆ parse()

static void parse ( struct mgcp_request req)
static

Definition at line 1872 of file chan_mgcp.c.

References ast_debug, ast_log, ast_strlen_zero, c, mgcp_request::data, mgcp_request::endpoint, mgcp_request::header, mgcp_request::headers, mgcp_request::identifier, mgcp_request::line, mgcp_request::lines, LOG_WARNING, MGCP_MAX_HEADERS, MGCP_MAX_LINES, mgcp_request::verb, and mgcp_request::version.

Referenced by acf_jabberreceive_read(), acf_meetme_info(), acf_vm_info(), add_hintdevice(), agent_function_read(), agent_login_exec(), agent_request_exec(), aMYSQL_clear(), aMYSQL_connect(), aMYSQL_disconnect(), aMYSQL_fetch(), aMYSQL_nextresult(), aMYSQL_query(), aMYSQL_set(), app_exec(), applicationmap_handler(), aqm_exec(), ast_format_cap_update_by_allow_disallow(), AST_TEST_DEFINE(), attended_transfer_exec(), audiosocket_exec(), audiosocket_request(), blind_transfer_exec(), bridgewait_exec(), cb_events(), cdr_prop_write(), cdr_prop_write_callback(), cdr_read(), cdr_write(), cdr_write_callback(), celgenuserevent_exec(), channelvars_handler(), chanspy_exec(), conf_exec(), conf_run(), confbridge_exec(), config_function_read(), confkick_exec(), cut_internal(), destroy_all_channels(), detect_write(), dial_exec_full(), dictate_exec(), directory_exec(), dtmfstore_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enum_query_read(), enum_result_read(), eval_exten_read(), execif_exec(), expand_gosub_args(), extenspy_exec(), find_conf(), forkcdr_exec(), free_zone(), func_confbridge_helper(), func_confbridge_info(), get_comma(), get_in_brackets_const(), get_in_brackets_full(), gosub_exec(), goto_parser(), hook_on(), iconv_read(), isAnsweringMachine(), isexten_function_read(), jb_helper(), load_channelvars(), local_alloc(), log_exec(), post_process_documentation::main(), man_do_variable_value(), mbl_sendsms_exec(), mbl_status_exec(), mgcpsock_read(), misdn_check_l2l1(), misdn_facility_exec(), misdn_set_opt_exec(), mixmonitor_exec(), msg_send_exec(), multicast_rtp_request(), mwi_has_voicemail(), mwi_inboxcount(), originate_exec(), oss_call(), oss_request(), page_exec(), park_and_announce_app_exec(), park_app_parse_data(), parked_call_app_exec(), parse_cookies(), pbx_builtin_answer(), pbx_builtin_background(), pbx_builtin_saycharacters_case(), pbx_builtin_waitdigit(), pbx_builtin_waitexten(), pickup_exec(), pickupchan_exec(), pjsip_acf_channel_read(), play_moh_exec(), pqm_exec(), presence_read(), privacy_exec(), process_echocancel(), ql_exec(), queue_exec(), queue_function_queuegetchannel(), qupd_exec(), rcvfax_exec(), receivefax_exec(), record_exec(), reload(), reload_single_member(), retrydial_exec(), rqm_exec(), saycountedadj_exec(), saycountednoun_exec(), sayunixtime_exec(), scramble_write(), sendfax_exec(), sip_acf_channel_read(), sip_parse_nat_option(), sla_trunk_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), sms_exec(), sndfax_exec(), softhangup_exec(), speech_background(), srv_result_read(), start_moh_exec(), start_monitor_exec(), stir_shaken_read(), stop_mixmonitor_full(), stream_echo_exec(), talk_detect_fn_write(), tls_method_to_str(), transfer_exec(), unicast_rtp_request(), upqm_exec(), user_event_hook_cb(), userevent_exec(), verbose_exec(), vm_execmain(), vm_playmsgexec(), waitfor_exec(), and zapateller_exec().

1873 {
1874  /* Divide fields by NULL's */
1875  char *c;
1876  int f = 0;
1877  c = req->data;
1878 
1879  /* First header starts immediately */
1880  req->header[f] = c;
1881  for (; *c; c++) {
1882  if (*c == '\n') {
1883  /* We've got a new header */
1884  *c = 0;
1885  ast_debug(3, "Header: %s (%d)\n", req->header[f], (int) strlen(req->header[f]));
1886  if (ast_strlen_zero(req->header[f])) {
1887  /* Line by itself means we're now in content */
1888  c++;
1889  break;
1890  }
1891  if (f >= MGCP_MAX_HEADERS - 1) {
1892  ast_log(LOG_WARNING, "Too many MGCP headers...\n");
1893  } else {
1894  f++;
1895  }
1896  req->header[f] = c + 1;
1897  } else if (*c == '\r') {
1898  /* Ignore but eliminate \r's */
1899  *c = 0;
1900  }
1901  }
1902  /* Check for last header */
1903  if (!ast_strlen_zero(req->header[f])) {
1904  f++;
1905  }
1906  req->headers = f;
1907  /* Now we process any mime content */
1908  f = 0;
1909  req->line[f] = c;
1910  for (; *c; c++) {
1911  if (*c == '\n') {
1912  /* We've got a new line */
1913  *c = 0;
1914  ast_debug(3, "Line: %s (%d)\n", req->line[f], (int) strlen(req->line[f]));
1915  if (f >= MGCP_MAX_LINES - 1) {
1916  ast_log(LOG_WARNING, "Too many SDP lines...\n");
1917  } else {
1918  f++;
1919  }
1920  req->line[f] = c + 1;
1921  } else if (*c == '\r') {
1922  /* Ignore and eliminate \r's */
1923  *c = 0;
1924  }
1925  }
1926  /* Check for last line */
1927  if (!ast_strlen_zero(req->line[f])) {
1928  f++;
1929  }
1930  req->lines = f;
1931  /* Parse up the initial header */
1932  c = req->header[0];
1933  while (*c && *c < 33) c++;
1934  /* First the verb */
1935  req->verb = c;
1936  while (*c && (*c > 32)) c++;
1937  if (*c) {
1938  *c = '\0';
1939  c++;
1940  while (*c && (*c < 33)) c++;
1941  req->identifier = c;
1942  while (*c && (*c > 32)) c++;
1943  if (*c) {
1944  *c = '\0';
1945  c++;
1946  while (*c && (*c < 33)) c++;
1947  req->endpoint = c;
1948  while (*c && (*c > 32)) c++;
1949  if (*c) {
1950  *c = '\0';
1951  c++;
1952  while (*c && (*c < 33)) c++;
1953  req->version = c;
1954  while (*c && (*c > 32)) c++;
1955  while (*c && (*c < 33)) c++;
1956  while (*c && (*c > 32)) c++;
1957  *c = '\0';
1958  }
1959  }
1960  }
1961 
1962  ast_debug(1, "Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
1963  req->verb, req->identifier, req->endpoint, req->version);
1964  ast_debug(1, "%d headers, %d lines\n", req->headers, req->lines);
1965  if (*c) {
1966  ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
1967  }
1968 }
#define LOG_WARNING
Definition: logger.h:274
char * identifier
Definition: chan_mgcp.c:256
char * verb
Definition: chan_mgcp.c:255
static struct test_val c
char * endpoint
Definition: chan_mgcp.c:257
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define MGCP_MAX_LINES
Definition: chan_mgcp.c:251
#define MGCP_MAX_HEADERS
Definition: chan_mgcp.c:250
char * line[MGCP_MAX_LINES]
Definition: chan_mgcp.c:262
char * header[MGCP_MAX_HEADERS]
Definition: chan_mgcp.c:260
char data[MGCP_MAX_PACKET]
Definition: chan_mgcp.c:263
char * version
Definition: chan_mgcp.c:258

◆ process_sdp()

static int process_sdp ( struct mgcp_subchannel sub,
struct mgcp_request req 
)
static

Definition at line 1970 of file chan_mgcp.c.

References a, ao2_ref, ast_debug, ast_format_cap_alloc, ast_format_cap_count(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_compatible(), ast_format_cap_get_names(), AST_FORMAT_CAP_NAMES_LEN, ast_gethostbyname(), ast_inet_ntoa(), ast_log, ast_rtp_codecs_payload_formats(), ast_rtp_codecs_payloads_set_m_type(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_set_remote_address, ast_sockaddr_from_sin, ast_str_alloca, ast_strdupa, ast_strlen_zero, c, mgcp_endpoint::cap, codecs, get_sdp(), get_sdp_iterate(), host, hp, len(), LOG_WARNING, nonCodecCapability, mgcp_endpoint::nonCodecCapability, mgcp_subchannel::parent, mgcp_subchannel::rtp, and sdpLineNum_iterator_init().

Referenced by handle_response().

1971 {
1972  char *m;
1973  char *c;
1974  char *a;
1975  char host[258];
1976  int len = 0;
1977  int portno;
1978  struct ast_format_cap *peercap;
1979  int peerNonCodecCapability;
1980  struct sockaddr_in sin;
1981  struct ast_sockaddr sin_tmp;
1982  char *codecs;
1983  struct ast_hostent ahp; struct hostent *hp;
1984  int codec, codec_count=0;
1985  int iterator;
1986  struct mgcp_endpoint *p = sub->parent;
1987  struct ast_str *global_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1988  struct ast_str *peer_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1989  struct ast_str *pvt_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1990 
1991  /* Get codec and RTP info from SDP */
1992  m = get_sdp(req, "m");
1993  c = get_sdp(req, "c");
1994  if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
1995  ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
1996  return -1;
1997  }
1998  if (sscanf(c, "IN IP4 %256s", host) != 1) {
1999  ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
2000  return -1;
2001  }
2002  /* XXX This could block for a long time, and block the main thread! XXX */
2003  hp = ast_gethostbyname(host, &ahp);
2004  if (!hp) {
2005  ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
2006  return -1;
2007  }
2008  if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1 || !len) {
2009  ast_log(LOG_WARNING, "Malformed media stream descriptor: %s\n", m);
2010  return -1;
2011  }
2012  sin.sin_family = AF_INET;
2013  memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
2014  sin.sin_port = htons(portno);
2015  ast_sockaddr_from_sin(&sin_tmp, &sin);
2016  ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2017  ast_debug(3, "Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
2018  /* Scan through the RTP payload types specified in a "m=" line: */
2019  codecs = ast_strdupa(m + len);
2020  while (!ast_strlen_zero(codecs)) {
2021  if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
2022  if (codec_count) {
2023  break;
2024  }
2025  ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
2026  return -1;
2027  }
2029  codec_count++;
2030  codecs += len;
2031  }
2032 
2033  /* Next, scan through each "a=rtpmap:" line, noting each */
2034  /* specified RTP payload type (with corresponding MIME subtype): */
2035  sdpLineNum_iterator_init(&iterator);
2036  while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
2037  char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
2038  if (sscanf(a, "rtpmap: %30d %127[^/]/", &codec, mimeSubtype) != 2)
2039  continue;
2040  /* Note: should really look at the 'freq' and '#chans' params too */
2041  ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0);
2042  }
2043 
2044  /* Now gather all of the codecs that were asked for: */
2046  return -1;
2047  }
2048  ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), peercap, &peerNonCodecCapability);
2050  ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n",
2052  ast_format_cap_get_names(peercap, &peer_buf),
2053  ast_format_cap_get_names(p->cap, &pvt_buf));
2054  ao2_ref(peercap, -1);
2055 
2056  ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n",
2057  nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
2058  if (!ast_format_cap_count(p->cap)) {
2059  ast_log(LOG_WARNING, "No compatible codecs!\n");
2060  return -1;
2061  }
2062  return 0;
2063 }
void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
Retrieve all formats that were found.
Definition: rtp_engine.c:1580
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:727
#define LOG_WARNING
Definition: logger.h:274
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
static struct ast_format_cap * global_capability
Definition: chan_mgcp.c:235
static void sdpLineNum_iterator_init(int *iterator)
Definition: chan_mgcp.c:1619
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
static struct test_val c
#define ast_str_alloca(init_len)
Definition: strings.h:800
Socket address structure.
Definition: netsock2.h:97
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static char host[256]
Definition: muted.c:77
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:782
static struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int nonCodecCapability
Definition: chan_mgcp.c:375
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options)
Record tx payload type information that was seen in an a=rtpmap: SDP line.
Definition: rtp_engine.c:1428
static struct ast_hostent ahp
Definition: chan_skinny.c:1235
static int nonCodecCapability
Definition: chan_mgcp.c:236
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1080
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:736
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
Definition: main/utils.c:197
static char * get_sdp_iterate(int *iterator, struct mgcp_request *req, char *name)
Definition: chan_mgcp.c:1624
static char * get_sdp(struct mgcp_request *req, char *name)
Definition: chan_mgcp.c:1606
static struct hostent * hp
Definition: chan_skinny.c:1236
int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
Find the compatible formats between two capabilities structures.
Definition: format_cap.c:630
void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
Record tx payload type information that was seen in an m= SDP line.
Definition: rtp_engine.c:1301
static struct test_val a

◆ prune_gateways()

static void prune_gateways ( void  )
static

Definition at line 4608 of file chan_mgcp.c.

References ast_mutex_lock, ast_mutex_unlock, mgcp_endpoint::delme, mgcp_gateway::delme, destroy_endpoint(), destroy_gateway(), mgcp_gateway::endpoints, gatelock, gateways, mgcp_endpoint::next, mgcp_gateway::next, NULL, and mgcp_gateway::realtime.

Referenced by reload_config(), and unload_module().

4609 {
4610  struct mgcp_gateway *g, *z, *r;
4611  struct mgcp_endpoint *e, *p, *t;
4612 
4614 
4615  /* prune gateways */
4616  for (z = NULL, g = gateways; g;) {
4617  /* prune endpoints */
4618  for (p = NULL, e = g->endpoints; e; ) {
4619  if (!g->realtime && (e->delme || g->delme)) {
4620  t = e;
4621  e = e->next;
4622  if (!p)
4623  g->endpoints = e;
4624  else
4625  p->next = e;
4626  destroy_endpoint(t);
4627  } else {
4628  p = e;
4629  e = e->next;
4630  }
4631  }
4632 
4633  if (g->delme) {
4634  r = g;
4635  g = g->next;
4636  if (!z)
4637  gateways = g;
4638  else
4639  z->next = g;
4640 
4641  destroy_gateway(r);
4642  } else {
4643  z = g;
4644  g = g->next;
4645  }
4646  }
4647 
4649 }
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:430
static void destroy_gateway(struct mgcp_gateway *g)
Definition: chan_mgcp.c:4598
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
static void destroy_endpoint(struct mgcp_endpoint *e)
Definition: chan_mgcp.c:4539
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
static struct mgcp_gateway * gateways
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ reload()

static int reload ( void  )
static

Definition at line 4941 of file chan_mgcp.c.

References mgcp_reload(), and NULL.

Referenced by unload_module().

4942 {
4943  mgcp_reload(NULL, 0, NULL);
4944  return 0;
4945 }
static char * mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mgcp.c:4908
#define NULL
Definition: resample.c:96

◆ reload_config()

static int reload_config ( int  reload)
static

Definition at line 4683 of file chan_mgcp.c.

References __ourip, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_format_cap_update_by_allow_disallow(), ast_gethostbyname(), ast_inet_ntoa(), ast_io_remove(), ast_io_wait(), ast_jb_read_conf(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_sched_runq(), ast_set_qos(), ast_str2cos(), ast_str2tos(), ast_variable_browse(), ast_verb, bindaddr, build_gateway(), config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, dtmfmode, mgcp_gateway::endpoints, errno, firstdigittimeout, gatelock, gateways, gendigittimeout, global_jbconf, hp, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, matchdigittimeout, mgcpsock, mgcpsock_read_id, monitor_thread, ast_variable::name, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::needaudit, netlock, ast_variable::next, mgcp_endpoint::next, mgcp_gateway::next, NULL, ourhost, ourport, prune_gateways(), qos, transmit_audit_endpoint(), and ast_variable::value.

Referenced by do_monitor(), and load_module().

4684 {
4685  struct ast_config *cfg;
4686  struct ast_variable *v;
4687  struct mgcp_gateway *g;
4688  struct mgcp_endpoint *e;
4689  char *cat;
4690  struct ast_hostent ahp;
4691  struct hostent *hp;
4692  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
4693 
4694  if (gethostname(ourhost, sizeof(ourhost)-1)) {
4695  ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
4696  return 0;
4697  }
4698  cfg = ast_config_load(config, config_flags);
4699 
4700  /* We *must* have a config file otherwise stop immediately */
4701  if (!cfg) {
4702  ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
4703  return 0;
4704  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
4705  return 0;
4706  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
4707  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
4708  return 0;
4709  }
4710 
4711  memset(&bindaddr, 0, sizeof(bindaddr));
4712  dtmfmode = 0;
4713 
4714  /* Copy the default jb config over global_jbconf */
4715  memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
4716 
4717  for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
4718  /* handle jb conf */
4719  if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
4720  continue;
4721  }
4722 
4723  /* Create the interface list */
4724  if (!strcasecmp(v->name, "bindaddr")) {
4725  if (!(hp = ast_gethostbyname(v->value, &ahp))) {
4726  ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
4727  } else {
4728  memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
4729  }
4730  } else if (!strcasecmp(v->name, "allow")) {
4732  } else if (!strcasecmp(v->name, "disallow")) {
4734  } else if (!strcasecmp(v->name, "tos")) {
4735  if (ast_str2tos(v->value, &qos.tos)) {
4736  ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
4737  }
4738  } else if (!strcasecmp(v->name, "tos_audio")) {
4739  if (ast_str2tos(v->value, &qos.tos_audio))
4740  ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
4741  } else if (!strcasecmp(v->name, "cos")) {
4742  if (ast_str2cos(v->value, &qos.cos))
4743  ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
4744  } else if (!strcasecmp(v->name, "cos_audio")) {
4745  if (ast_str2cos(v->value, &qos.cos_audio))
4746  ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
4747  } else if (!strcasecmp(v->name, "port")) {
4748  if (sscanf(v->value, "%5d", &ourport) == 1) {
4749  bindaddr.sin_port = htons(ourport);
4750  } else {
4751  ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
4752  }
4753  } else if (!strcasecmp(v->name, "firstdigittimeout")) {
4754  firstdigittimeout = atoi(v->value);
4755  } else if (!strcasecmp(v->name, "gendigittimeout")) {
4756  gendigittimeout = atoi(v->value);
4757  } else if (!strcasecmp(v->name, "matchdigittimeout")) {
4758  matchdigittimeout = atoi(v->value);
4759  }
4760  }
4761 
4762  /* mark existing entries for deletion */
4764  for (g = gateways; g; g = g->next) {
4765  g->delme = 1;
4766  for (e = g->endpoints; e; e = e->next) {
4767  e->delme = 1;
4768  }
4769  }
4771 
4772  for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
4773  if (strcasecmp(cat, "general")) {
4775  if ((g = build_gateway(cat, ast_variable_browse(cfg, cat)))) {
4776  ast_verb(3, "Added gateway '%s'\n", g->name);
4777  g->next = gateways;
4778  gateways = g;
4779  }
4781 
4782  /* FS: process queue and IO */
4783  if (monitor_thread == pthread_self()) {
4784  if (sched) ast_sched_runq(sched);
4785  if (io) ast_io_wait(io, 10);
4786  }
4787  }
4788  }
4789 
4790  /* prune deleted entries etc. */
4791  prune_gateways();
4792 
4793  if (ntohl(bindaddr.sin_addr.s_addr)) {
4794  memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
4795  } else {
4796  hp = ast_gethostbyname(ourhost, &ahp);
4797  if (!hp) {
4798  ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
4799  ast_config_destroy(cfg);
4800  return 0;
4801  }
4802  memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
4803  }
4804  if (!ntohs(bindaddr.sin_port))
4805  bindaddr.sin_port = htons(DEFAULT_MGCP_CA_PORT);
4806  bindaddr.sin_family = AF_INET;
4808  if (mgcpsock > -1)
4809  close(mgcpsock);
4810 
4811  if (mgcpsock_read_id != NULL)
4814 
4815  mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
4816  if (mgcpsock < 0) {
4817  ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
4818  } else {
4819  if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
4820  ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
4821  ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
4822  strerror(errno));
4823  close(mgcpsock);
4824  mgcpsock = -1;
4825  } else {
4826  ast_verb(2, "MGCP Listening on %s:%d\n",
4827  ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
4828  ast_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP");
4829  }
4830  }
4832  ast_config_destroy(cfg);
4833 
4834  /* send audit only to the new endpoints */
4835  for (g = gateways; g; g = g->next) {
4836  for (e = g->endpoints; e && e->needaudit; e = e->next) {
4837  e->needaudit = 0;
4839  ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
4840  }
4841  }
4842 
4843  return 0;
4844 }
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:278
struct ast_variable * next
static int mgcpsock
Definition: chan_mgcp.c:432
static int dtmfmode
Definition: chan_mgcp.c:167
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:430
static int firstdigittimeout
Definition: chan_mgcp.c:214
static struct mgcp_gateway * build_gateway(char *cat, struct ast_variable *v)
build_gateway: parse mgcp.conf and create gateway/endpoint structures
Definition: chan_mgcp.c:4016
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
static int * mgcpsock_read_id
Definition: chan_mgcp.c:3758
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define LOG_WARNING
Definition: logger.h:274
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:545
static struct ast_format_cap * global_capability
Definition: chan_mgcp.c:235
#define CONFIG_STATUS_FILEINVALID
static const char config[]
Definition: chan_mgcp.c:117
Structure for variables, used for configurations and for channel variables.
static char ourhost[MAXHOSTNAMELEN]
Definition: chan_mgcp.c:238
Definition: sched.c:76
#define ast_mutex_lock(a)
Definition: lock.h:187
static struct @126 qos
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
Definition: acl.c:967
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
static int transmit_audit_endpoint(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:2676
int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing)
Parse an "allow" or "deny" list and modify a format capabilities structure accordingly.
Definition: format_cap.c:320
static void prune_gateways(void)
Definition: chan_mgcp.c:4608
#define DEFAULT_MGCP_CA_PORT
Definition: chan_mgcp.c:124
static ast_mutex_t netlock
Definition: chan_mgcp.c:224
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: chan_mgcp.c:334
#define ast_config_load(filename, flags)
Load a config file.
static struct sockaddr_in bindaddr
Definition: chan_mgcp.c:434
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static struct io_context * io
Definition: chan_mgcp.c:245
char name[80]
Definition: chan_mgcp.c:401
static int reload(void)
Definition: chan_mgcp.c:4941
#define CONFIG_STATUS_FILEUNCHANGED
static struct ast_hostent ahp
Definition: chan_skinny.c:1235
static int gendigittimeout
Definition: chan_mgcp.c:217
static pthread_t monitor_thread
Definition: chan_mgcp.c:231
#define LOG_ERROR
Definition: logger.h:285
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
Definition: netsock2.c:621
int errno
#define LOG_NOTICE
Definition: logger.h:263
static struct ast_jb_conf global_jbconf
Definition: chan_mgcp.c:114
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
int ast_str2cos(const char *value, unsigned int *cos)
Convert a string to the appropriate COS value.
Definition: acl.c:953
static struct mgcp_gateway * gateways
Structure used to handle boolean flags.
Definition: utils.h:199
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Definition: io.c:245
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
Definition: main/utils.c:197
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
static int matchdigittimeout
Definition: chan_mgcp.c:220
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
static struct in_addr __ourip
Definition: chan_mgcp.c:239
static struct ast_jb_conf default_jbconf
Definition: chan_mgcp.c:106
static struct hostent * hp
Definition: chan_skinny.c:1236
static int ourport
Definition: chan_mgcp.c:240
General jitterbuffer configuration.
Definition: abstract_jb.h:69
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ reqprep()

static int reqprep ( struct mgcp_request req,
struct mgcp_endpoint p,
char *  verb 
)
static

Definition at line 2159 of file chan_mgcp.c.

References ast_mutex_lock, ast_mutex_unlock, init_req(), oseq_global, and oseq_lock.

Referenced by transmit_audit_endpoint(), transmit_connect(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().

2160 {
2161  unsigned int oseq;
2162  memset(req, 0, sizeof(struct mgcp_request));
2164  oseq_global++;
2165  if (oseq_global > 999999999) {
2166  oseq_global = 1;
2167  }
2168  oseq = oseq_global;
2170  init_req(p, req, verb, oseq);
2171  return oseq;
2172 }
static unsigned int oseq_global
Definition: chan_mgcp.c:210
#define ast_mutex_lock(a)
Definition: lock.h:187
static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb, unsigned int oseq)
Definition: chan_mgcp.c:2128
static ast_mutex_t oseq_lock
Definition: chan_mgcp.c:211
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ resend_response()

static int resend_response ( struct mgcp_subchannel sub,
struct mgcp_response resp 
)
static

Definition at line 547 of file chan_mgcp.c.

References __mgcp_xmit(), mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), mgcp_response::buf, mgcp_response::len, mgcp_subchannel::parent, and mgcp_endpoint::parent.

Referenced by find_and_retrans().

548 {
549  struct mgcp_endpoint *p = sub->parent;
550  int res;
551  ast_debug(1, "Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
552  res = __mgcp_xmit(p->parent, resp->buf, resp->len);
553  if (res > 0)
554  res = 0;
555  return res;
556 }
static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
Definition: chan_mgcp.c:534
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
struct sockaddr_in addr
Definition: chan_mgcp.c:403
char buf[0]
Definition: chan_mgcp.c:288
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307

◆ respprep()

static int respprep ( struct mgcp_request resp,
struct mgcp_endpoint p,
char *  msg,
struct mgcp_request req,
char *  msgrest 
)
static

Definition at line 2152 of file chan_mgcp.c.

References init_resp().

Referenced by transmit_response().

2153 {
2154  memset(resp, 0, sizeof(*resp));
2155  init_resp(resp, msg, req, msgrest);
2156  return 0;
2157 }
static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
Definition: chan_mgcp.c:2110

◆ restart_monitor()

static int restart_monitor ( void  )
static

Definition at line 3936 of file chan_mgcp.c.

References ast_log, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, monitor_thread, monlock, and NULL.

Referenced by load_module(), mgcp_reload(), and mgcp_request().

3937 {
3938  /* If we're supposed to be stopped -- stay stopped */
3940  return 0;
3941  if (ast_mutex_lock(&monlock)) {
3942  ast_log(LOG_WARNING, "Unable to lock monitor\n");
3943  return -1;
3944  }
3945  if (monitor_thread == pthread_self()) {
3947  ast_log(LOG_WARNING, "Cannot kill myself\n");
3948  return -1;
3949  }
3951  /* Wake up the thread */
3952  pthread_kill(monitor_thread, SIGURG);
3953  } else {
3954  /* Start a new monitor */
3957  ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
3958  return -1;
3959  }
3960  }
3962  return 0;
3963 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
static void * do_monitor(void *data)
Definition: chan_mgcp.c:3818
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
#define ast_log
Definition: astobj2.c:42
#define AST_PTHREADT_NULL
Definition: lock.h:66
static pthread_t monitor_thread
Definition: chan_mgcp.c:231
static ast_mutex_t monlock
Definition: chan_mgcp.c:226
#define LOG_ERROR
Definition: logger.h:285
#define AST_PTHREADT_STOP
Definition: lock.h:67
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ retrans_pkt()

static int retrans_pkt ( const void *  data)
static

Definition at line 644 of file chan_mgcp.c.

References __mgcp_xmit(), ast_debug, ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, mgcp_message::buf, handle_response(), mgcp_message::len, LOG_WARNING, MAX_RETRANS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, NULL, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_message::retrans, mgcp_gateway::retransid, and mgcp_message::seqno.

Referenced by mgcp_postrequest().

645 {
646  struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
647  struct mgcp_message *cur, *exq = NULL, *w, *prev;
648  int res = 0;
649 
650  /* find out expired msgs */
652 
653  for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
654  if (cur->retrans < MAX_RETRANS) {
655  cur->retrans++;
656  ast_debug(1, "Retransmitting #%d transaction %u on [%s]\n",
657  cur->retrans, cur->seqno, gw->name);
658  __mgcp_xmit(gw, cur->buf, cur->len);
659  } else {
660  if (prev)
661  prev->next = cur->next;
662  else
663  gw->msgs = cur->next;
664 
665  ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
666  cur->seqno, gw->name);
667 
668  w = cur;
669 
670  if (exq) {
671  w->next = exq;
672  } else {
673  w->next = NULL;
674  }
675  exq = w;
676  }
677  }
678 
679  if (!gw->msgs) {
680  gw->retransid = -1;
681  res = 0;
682  } else {
683  res = 1;
684  }
686 
687  while (exq) {
688  cur = exq;
689  /* time-out transaction */
690  handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
691  exq = exq->next;
692  ast_free(cur);
693  }
694 
695  return res;
696 }
static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
Definition: chan_mgcp.c:534
static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp)
Definition: chan_mgcp.c:2797
struct mgcp_endpoint * owner_ep
Definition: chan_mgcp.c:271
#define LOG_WARNING
Definition: logger.h:274
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
ast_mutex_t msgs_lock
Definition: chan_mgcp.c:418
mgcp_message: MGCP message for queuing up
Definition: chan_mgcp.c:270
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
char buf[0]
Definition: chan_mgcp.c:278
struct mgcp_message * msgs
Definition: chan_mgcp.c:417
char name[80]
Definition: chan_mgcp.c:401
#define ast_free(a)
Definition: astmm.h:182
#define MAX_RETRANS
Definition: chan_mgcp.c:127
struct mgcp_message * next
Definition: chan_mgcp.c:277
unsigned int seqno
Definition: chan_mgcp.c:275
#define ast_mutex_unlock(a)
Definition: lock.h:188
struct mgcp_subchannel * owner_sub
Definition: chan_mgcp.c:272

◆ sdpLineNum_iterator_init()

static void sdpLineNum_iterator_init ( int *  iterator)
static

Definition at line 1619 of file chan_mgcp.c.

Referenced by process_sdp().

1620 {
1621  *iterator = 0;
1622 }

◆ send_request()

static int send_request ( struct mgcp_endpoint p,
struct mgcp_subchannel sub,
struct mgcp_request req,
unsigned int  seqno 
)
static

Definition at line 743 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_debug, ast_free, ast_inet_ntoa(), ast_log, ast_malloc, ast_mutex_lock, ast_mutex_unlock, mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_request::data, mgcp_request::len, LOG_WARNING, MGCP_CMD_CRCX, MGCP_CMD_DLCX, MGCP_CMD_MDCX, MGCP_CMD_RQNT, mgcp_postrequest(), mgcp_endpoint::ncs, mgcp_request::next, NULL, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::slowsequence.

Referenced by transmit_audit_endpoint(), transmit_connect(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().

745 {
746  int res = 0;
747  struct mgcp_request **queue, *q, *r, *t;
748  ast_mutex_t *l;
749 
750  ast_debug(1, "Slow sequence is %d\n", p->slowsequence);
751  if (p->slowsequence) {
752  queue = &p->cmd_queue;
753  l = &p->cmd_queue_lock;
754  ast_mutex_lock(l);
755  } else {
756  switch (req->cmd) {
757  case MGCP_CMD_DLCX:
758  queue = &sub->cx_queue;
759  l = &sub->cx_queue_lock;
760  ast_mutex_lock(l);
761  q = sub->cx_queue;
762  /* delete pending cx cmds */
763  /* buggy sb5120 */
764  if (!sub->parent->ncs) {
765  while (q) {
766  r = q->next;
767  ast_free(q);
768  q = r;
769  }
770  *queue = NULL;
771  }
772  break;
773 
774  case MGCP_CMD_CRCX:
775  case MGCP_CMD_MDCX:
776  queue = &sub->cx_queue;
777  l = &sub->cx_queue_lock;
778  ast_mutex_lock(l);
779  break;
780 
781  case MGCP_CMD_RQNT:
782  queue = &p->rqnt_queue;
783  l = &p->rqnt_queue_lock;
784  ast_mutex_lock(l);
785  break;
786 
787  default:
788  queue = &p->cmd_queue;
789  l = &p->cmd_queue_lock;
790  ast_mutex_lock(l);
791  break;
792  }
793  }
794 
795  if (!(r = ast_malloc(sizeof(*r)))) {
796  ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
797  ast_mutex_unlock(l);
798  return -1;
799  }
800  memcpy(r, req, sizeof(*r));
801 
802  if (!(*queue)) {
803  ast_debug(1, "Posting Request:\n%s to %s:%d\n", req->data,
804  ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
805 
806  res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
807  } else {
808  ast_debug(1, "Queueing Request:\n%s to %s:%d\n", req->data,
809  ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
810  }
811 
812  /* XXX find tail. We could also keep tail in the data struct for faster access */
813  for (t = *queue; t && t->next; t = t->next);
814 
815  r->next = NULL;
816  if (t)
817  t->next = r;
818  else
819  *queue = r;
820 
821  ast_mutex_unlock(l);
822 
823  return res;
824 }
struct mgcp_request * cx_queue
Definition: chan_mgcp.c:315
ast_mutex_t cmd_queue_lock
Definition: chan_mgcp.c:385
int slowsequence
Definition: chan_mgcp.c:369
#define LOG_WARNING
Definition: logger.h:274
struct mgcp_request * next
Definition: chan_mgcp.c:266
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct mgcp_request * rqnt_queue
Definition: chan_mgcp.c:382
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno)
Definition: chan_mgcp.c:699
ast_mutex_t cx_queue_lock
Definition: chan_mgcp.c:316
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
struct sockaddr_in addr
Definition: chan_mgcp.c:403
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
#define ast_free(a)
Definition: astmm.h:182
ast_mutex_t rqnt_queue_lock
Definition: chan_mgcp.c:383
struct mgcp_request * cmd_queue
Definition: chan_mgcp.c:384
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
char data[MGCP_MAX_PACKET]
Definition: chan_mgcp.c:263
Structure for mutex and tracking information.
Definition: lock.h:135
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ send_response()

static int send_response ( struct mgcp_subchannel sub,
struct mgcp_request req 
)
static

Definition at line 558 of file chan_mgcp.c.

References __mgcp_xmit(), mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), mgcp_request::data, mgcp_request::len, mgcp_subchannel::parent, and mgcp_endpoint::parent.

Referenced by transmit_response().

559 {
560  struct mgcp_endpoint *p = sub->parent;
561  int res;
562  ast_debug(1, "Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
563  res = __mgcp_xmit(p->parent, req->data, req->len);
564  if (res > 0)
565  res = 0;
566  return res;
567 }
static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
Definition: chan_mgcp.c:534
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
struct sockaddr_in addr
Definition: chan_mgcp.c:403
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
char data[MGCP_MAX_PACKET]
Definition: chan_mgcp.c:263

◆ start_rtp()

static void start_rtp ( struct mgcp_subchannel sub)
static

Definition at line 2967 of file chan_mgcp.c.

References ast_channel_set_fd(), ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_rtp_instance_destroy(), ast_rtp_instance_fd(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), AST_RTP_PROPERTY_NAT, ast_sockaddr_from_sin, bindaddr, mgcp_subchannel::callid, mgcp_subchannel::gate, mgcp_subchannel::lock, mgcp_alloc_pktcgate(), mgcp_queue_hangup(), mgcp_subchannel::nat, NULL, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_endpoint::pktcgatealloc, qos, mgcp_subchannel::rtp, transmit_connect(), transmit_connect_with_sdp(), and mgcp_subchannel::txident.

Referenced by handle_hd_hf(), handle_response(), mgcp_answer(), mgcp_call(), and mgcp_ss().

2968 {
2969  struct ast_sockaddr bindaddr_tmp;
2970 
2971  ast_mutex_lock(&sub->lock);
2972  /* check again to be on the safe side */
2973  if (sub->rtp) {
2975  sub->rtp = NULL;
2976  }
2977  /* Allocate the RTP now */
2978  ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
2979  sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
2980  if (sub->rtp && sub->owner)
2981  ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
2982  if (sub->rtp) {
2983  ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
2985  }
2986  /* Make a call*ID */
2987  snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", (unsigned long)ast_random(), sub->txident);
2988  /* Transmit the connection create */
2989  if(!sub->parent->pktcgatealloc) {
2991  } else {
2992  transmit_connect(sub);
2993  sub->gate = NULL;
2994  if(!mgcp_alloc_pktcgate(sub))
2995  mgcp_queue_hangup(sub);
2996  }
2997  ast_mutex_unlock(&sub->lock);
2998 }
struct cops_gate * gate
Definition: chan_mgcp.c:322
char callid[80]
Definition: chan_mgcp.c:313
static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
Definition: chan_mgcp.c:2363
int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
Set QoS parameters on an RTP session.
Definition: rtp_engine.c:2169
static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:621
Definition: sched.c:76
ast_mutex_t lock
Definition: chan_mgcp.c:304
#define ast_mutex_lock(a)
Definition: lock.h:187
static struct @126 qos
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:782
static struct sockaddr_in bindaddr
Definition: chan_mgcp.c:434
static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2448
static int transmit_connect(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2462
struct ast_channel * owner
Definition: chan_mgcp.c:306
long int ast_random(void)
Definition: main/utils.c:2064
int pktcgatealloc
Definition: chan_mgcp.c:366
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
Definition: rtp_engine.c:2192
char txident[80]
Definition: chan_mgcp.c:310
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:458
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2431
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:705
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct ast_sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:465
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ transmit_audit_endpoint()

static int transmit_audit_endpoint ( struct mgcp_endpoint p)
static

Definition at line 2676 of file chan_mgcp.c.

References add_header(), mgcp_request::cmd, MGCP_CMD_AUEP, NULL, reqprep(), send_request(), and mgcp_request::trid.

Referenced by find_realtime_gw(), handle_mgcp_audit_endpoint(), handle_request(), and reload_config().

2677 {
2678  struct mgcp_request resp;
2679  unsigned int oseq;
2680  oseq = reqprep(&resp, p, "AUEP");
2681  /* removed unknown param VS */
2682  /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
2683  add_header(&resp, "F", "A");
2684  /* fill in new fields */
2685  resp.cmd = MGCP_CMD_AUEP;
2686  resp.trid = oseq;
2687  return send_request(p, NULL, &resp, oseq);
2688 }
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2159
#define NULL
Definition: resample.c:96
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:743
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ transmit_connect()

static int transmit_connect ( struct mgcp_subchannel sub)
static

Definition at line 2462 of file chan_mgcp.c.

References add_header(), ao2_ref, ast_copy_string(), ast_debug, ast_format_cap_count(), ast_format_cap_get_format(), ast_rtp_lookup_mime_subtype2(), mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_CRCX, mgcp_cxmodes, mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::parent, mgcp_endpoint::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), tmp(), mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by start_rtp().

2463 {
2464  struct mgcp_request resp;
2465  int x;
2466  char local[256];
2467  char tmp[80];
2468  struct ast_format *tmpfmt;
2469  struct mgcp_endpoint *p = sub->parent;
2470  unsigned int oseq;
2471 
2472  ast_copy_string(local, "p:20, s:off, e:on", sizeof(local));
2473 
2474  for (x = 0; x < ast_format_cap_count(p->cap); x++) {
2475  tmpfmt = ast_format_cap_get_format(p->cap, x);
2476 
2477  snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, tmpfmt, 0, 0));
2478  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2479 
2480  ao2_ref(tmpfmt, -1);
2481  }
2482 
2483  ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
2484  p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2485  sub->sdpsent = 0;
2486  oseq = reqprep(&resp, p, "CRCX");
2487  add_header(&resp, "C", sub->callid);
2488  add_header(&resp, "L", local);
2489  add_header(&resp, "M", "inactive");
2490  /* X header should not be sent. kept for compatibility */
2491  add_header(&resp, "X", sub->txident);
2492  /*add_header(&resp, "S", "");*/
2493  /* fill in new fields */
2494  resp.cmd = MGCP_CMD_CRCX;
2495  resp.trid = oseq;
2496  return send_request(p, sub, &resp, oseq);
2497 }
static const char *const mgcp_cxmodes[]
Definition: chan_mgcp.c:139
char callid[80]
Definition: chan_mgcp.c:313
static int tmp()
Definition: bt_open.c:389
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2159
Definition of a media format.
Definition: format.c:43
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char name[80]
Definition: chan_mgcp.c:334
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const struct ast_format *format, int code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:1992
#define ao2_ref(o, delta)
Definition: astobj2.h:464
char name[80]
Definition: chan_mgcp.c:401
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
char txident[80]
Definition: chan_mgcp.c:310
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:743
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ transmit_connect_with_sdp()

static int transmit_connect_with_sdp ( struct mgcp_subchannel sub,
struct ast_rtp_instance rtp 
)
static

Definition at line 2363 of file chan_mgcp.c.

References add_header(), add_sdp(), ao2_ref, ast_copy_string(), ast_debug, ast_format_cap_count(), ast_format_cap_get_format(), ast_format_get_type(), AST_MEDIA_TYPE_AUDIO, ast_rtp_lookup_mime_subtype2(), mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxmode, format, mgcp_subchannel::gate, GATE_ALLOCATED, cops_gate::gateid, mgcp_subchannel::id, MGCP_CMD_CRCX, mgcp_cxmodes, mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::parent, mgcp_endpoint::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), cops_gate::state, tmp(), mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by start_rtp().

2364 {
2365  struct mgcp_request resp;
2366  char local[256];
2367  char tmp[80];
2368  int i;
2369  struct mgcp_endpoint *p = sub->parent;
2370  unsigned int oseq;
2371 
2372  ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
2373  p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2374 
2375  ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
2376 
2377  for (i = 0; i < ast_format_cap_count(p->cap); i++) {
2379 
2380  if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) {
2381  ao2_ref(format, -1);
2382  continue;
2383  }
2384 
2385  snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
2386  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2387 
2388  ao2_ref(format, -1);
2389  }
2390 
2391  if (sub->gate) {
2392  if(sub->gate->state == GATE_ALLOCATED) {
2393  snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
2394  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2395  }
2396  }
2397  sub->sdpsent = 1;
2398  oseq = reqprep(&resp, p, "CRCX");
2399  add_header(&resp, "C", sub->callid);
2400  add_header(&resp, "L", local);
2401  add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2402  /* X header should not be sent. kept for compatibility */
2403  add_header(&resp, "X", sub->txident);
2404  /*add_header(&resp, "S", "");*/
2405  add_sdp(&resp, sub, rtp);
2406  /* fill in new fields */
2407  resp.cmd = MGCP_CMD_CRCX;
2408  resp.trid = oseq;
2409  return send_request(p, sub, &resp, oseq);
2410 }
static const char *const mgcp_cxmodes[]
Definition: chan_mgcp.c:139
struct cops_gate * gate
Definition: chan_mgcp.c:322
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
char callid[80]
Definition: chan_mgcp.c:313
static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
Definition: chan_mgcp.c:2201
int state
Definition: pktccops.h:59
static int tmp()
Definition: bt_open.c:389
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2159
Definition of a media format.
Definition: format.c:43
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char name[80]
Definition: chan_mgcp.c:334
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const struct ast_format *format, int code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:1992
#define ao2_ref(o, delta)
Definition: astobj2.h:464
char name[80]
Definition: chan_mgcp.c:401
uint32_t gateid
Definition: pktccops.h:55
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
char txident[80]
Definition: chan_mgcp.c:310
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:743
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
static snd_pcm_format_t format
Definition: chan_alsa.c:102
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ transmit_connection_del()

static int transmit_connection_del ( struct mgcp_subchannel sub)
static

Definition at line 2690 of file chan_mgcp.c.

References add_header(), ast_debug, mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_DLCX, mgcp_cxmodes, mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::parent, mgcp_endpoint::parent, reqprep(), send_request(), mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by destroy_endpoint(), handle_request(), handle_response(), mgcp_hangup(), and unalloc_sub().

2691 {
2692  struct mgcp_endpoint *p = sub->parent;
2693  struct mgcp_request resp;
2694  unsigned int oseq;
2695 
2696  ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
2697  sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2698  oseq = reqprep(&resp, p, "DLCX");
2699  /* check if call id is avail */
2700  if (sub->callid[0])
2701  add_header(&resp, "C", sub->callid);
2702  /* X header should not be sent. kept for compatibility */
2703  add_header(&resp, "X", sub->txident);
2704  /* check if cxident is avail */
2705  if (sub->cxident[0])
2706  add_header(&resp, "I", sub->cxident);
2707  /* fill in new fields */
2708  resp.cmd = MGCP_CMD_DLCX;
2709  resp.trid = oseq;
2710  return send_request(p, sub, &resp, oseq);
2711 }
static const char *const mgcp_cxmodes[]
Definition: chan_mgcp.c:139
char callid[80]
Definition: chan_mgcp.c:313
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2159
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char name[80]
Definition: chan_mgcp.c:334
char name[80]
Definition: chan_mgcp.c:401
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
char cxident[80]
Definition: chan_mgcp.c:312
char txident[80]
Definition: chan_mgcp.c:310
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:743
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ transmit_connection_del_w_params()

static int transmit_connection_del_w_params ( struct mgcp_endpoint p,
char *  callid,
char *  cxident 
)
static

Definition at line 2713 of file chan_mgcp.c.

References add_header(), ast_debug, mgcp_request::cmd, MGCP_CMD_DLCX, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::parent, reqprep(), send_request(), mgcp_endpoint::sub, and mgcp_request::trid.

Referenced by handle_response().

2714 {
2715  struct mgcp_request resp;
2716  unsigned int oseq;
2717 
2718  ast_debug(3, "Delete connection %s %s@%s on callid: %s\n",
2719  cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
2720  oseq = reqprep(&resp, p, "DLCX");
2721  /* check if call id is avail */
2722  if (callid && *callid)
2723  add_header(&resp, "C", callid);
2724  /* check if cxident is avail */
2725  if (cxident && *cxident)
2726  add_header(&resp, "I", cxident);
2727  /* fill in new fields */
2728  resp.cmd = MGCP_CMD_DLCX;
2729  resp.trid = oseq;
2730  return send_request(p, p->sub, &resp, oseq);
2731 }
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2159
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char name[80]
Definition: chan_mgcp.c:334
char name[80]
Definition: chan_mgcp.c:401
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:743
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ transmit_modify_request()

static int transmit_modify_request ( struct mgcp_subchannel sub)
static

Definition at line 2572 of file chan_mgcp.c.

References add_header(), add_header_offhook(), add_sdp(), ao2_ref, ast_copy_string(), ast_debug, ast_format_cap_append, ast_format_cap_count(), ast_format_cap_get_format(), ast_format_cap_remove_by_type(), AST_MEDIA_TYPE_UNKNOWN, ast_rtp_lookup_mime_subtype2(), ast_strlen_zero, mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, format, mgcp_subchannel::gate, GATE_ALLOCATED, GATE_OPEN, cops_gate::gateid, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_MDCX, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::ncs, NULL, mgcp_subchannel::parent, mgcp_endpoint::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), cops_gate::state, tmp(), mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), mgcp_call(), mgcp_hangup(), and mgcp_indicate().

2573 {
2574  struct mgcp_request resp;
2575  struct mgcp_endpoint *p = sub->parent;
2576  int i;
2577  int fc = 1;
2578  char local[256];
2579  char tmp[80];
2580  unsigned int oseq;
2581 
2582  if (ast_strlen_zero(sub->cxident)) {
2583  /* We don't have a CXident yet, store the destination and
2584  wait a bit */
2585  return 0;
2586  }
2587  ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n",
2588  p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2589 
2590  ast_copy_string(local, "", sizeof(local));
2591  for (i = 0; i < ast_format_cap_count(p->cap); i++) {
2593 
2594  if (p->ncs && !fc) {
2596  ast_format_cap_append(p->cap, format, 0); /* sb5120e bug */
2597  ao2_ref(format, -1);
2598  break;
2599  } else {
2600  fc = 0;
2601  snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
2602  }
2603  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2604 
2605  ao2_ref(format, -1);
2606  }
2607 
2608  if (!sub->sdpsent) {
2609  if (sub->gate) {
2610  if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
2611  snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
2612  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2613  } else {
2614  /* we still don't have gateid wait */
2615  return 0;
2616  }
2617  }
2618  }
2619 
2620  oseq = reqprep(&resp, p, "MDCX");
2621  add_header(&resp, "C", sub->callid);
2622  if (!sub->sdpsent) {
2623  add_header(&resp, "L", local);
2624  }
2625  add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2626  /* X header should not be sent. kept for compatibility */
2627  add_header(&resp, "X", sub->txident);
2628  add_header(&resp, "I", sub->cxident);
2629  switch (sub->parent->hookstate) {
2630  case MGCP_ONHOOK:
2631  add_header(&resp, "R", "L/hd(N)");
2632  break;
2633  case MGCP_OFFHOOK:
2634  add_header_offhook(sub, &resp, "");
2635  break;
2636  }
2637  if (!sub->sdpsent) {
2638  add_sdp(&resp, sub, NULL);
2639  sub->sdpsent = 1;
2640  }
2641  /* fill in new fields */
2642  resp.cmd = MGCP_CMD_MDCX;
2643  resp.trid = oseq;
2644  return send_request(p, sub, &resp, oseq);
2645 }
static const char *const mgcp_cxmodes[]
Definition: chan_mgcp.c:139
struct cops_gate * gate
Definition: chan_mgcp.c:322
char callid[80]
Definition: chan_mgcp.c:313
static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
Definition: chan_mgcp.c:2201
int state
Definition: pktccops.h:59
static int tmp()
Definition: bt_open.c:389
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2159
Definition of a media format.
Definition: format.c:43
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char name[80]
Definition: chan_mgcp.c:334
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const struct ast_format *format, int code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:1992
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:327
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
char name[80]
Definition: chan_mgcp.c:401
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:525
uint32_t gateid
Definition: pktccops.h:55
static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone)
Definition: chan_mgcp.c:2648
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
char cxident[80]
Definition: chan_mgcp.c:312
char txident[80]
Definition: chan_mgcp.c:310
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:743
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
static snd_pcm_format_t format
Definition: chan_alsa.c:102
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ transmit_modify_with_sdp()

static int transmit_modify_with_sdp ( struct mgcp_subchannel sub,
struct ast_rtp_instance rtp,
const struct ast_format_cap codecs 
)
static

Definition at line 2301 of file chan_mgcp.c.

References add_header(), add_sdp(), ao2_ref, ast_copy_string(), ast_debug, ast_format_cap_count(), ast_format_cap_get_format(), ast_format_get_type(), AST_MEDIA_TYPE_AUDIO, ast_rtp_instance_get_remote_address, ast_rtp_lookup_mime_subtype2(), ast_sockaddr_to_sin, ast_strlen_zero, mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, format, mgcp_subchannel::gate, GATE_ALLOCATED, GATE_OPEN, cops_gate::gateid, MGCP_CMD_MDCX, mgcp_cxmodes, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), cops_gate::state, tmp(), mgcp_subchannel::tmpdest, mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by handle_response(), mgcp_pktcgate_open(), mgcp_set_rtp_peer(), and mgcp_write().

2302 {
2303  struct mgcp_request resp;
2304  char local[256];
2305  char tmp[80];
2306  struct mgcp_endpoint *p = sub->parent;
2307  int i;
2308  struct ast_sockaddr sub_tmpdest_tmp;
2309  unsigned int oseq;
2310 
2311  if (ast_strlen_zero(sub->cxident) && rtp) {
2312  /* We don't have a CXident yet, store the destination and
2313  wait a bit */
2314  ast_rtp_instance_get_remote_address(rtp, &sub_tmpdest_tmp);
2315  ast_sockaddr_to_sin(&sub_tmpdest_tmp, &sub->tmpdest);
2316  return 0;
2317  }
2318  ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
2319 
2320  for (i = 0; i < ast_format_cap_count(p->cap); i++) {
2322 
2323  if (ast_format_get_type(format) != AST_MEDIA_TYPE_AUDIO) {
2324  ao2_ref(format, -1);
2325  continue;
2326  }
2327 
2328  snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
2329  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2330 
2331  ao2_ref(format, -1);
2332  }
2333 
2334  if (sub->gate) {
2335  if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
2336  snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
2337  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2338  sub->sdpsent = 1;
2339  } else {
2340  /* oops wait */
2341  ast_debug(1, "Waiting for opened gate...\n");
2342  sub->sdpsent = 0;
2343  return 0;
2344  }
2345  }
2346 
2347 
2348  oseq = reqprep(&resp, p, "MDCX");
2349  add_header(&resp, "C", sub->callid);
2350  add_header(&resp, "L", local);
2351  add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2352  /* X header should not be sent. kept for compatibility */
2353  add_header(&resp, "X", sub->txident);
2354  add_header(&resp, "I", sub->cxident);
2355  /*add_header(&resp, "S", "");*/
2356  add_sdp(&resp, sub, rtp);
2357  /* fill in new fields */
2358  resp.cmd = MGCP_CMD_MDCX;
2359  resp.trid = oseq;
2360  return send_request(p, sub, &resp, oseq);
2361 }
static const char *const mgcp_cxmodes[]
Definition: chan_mgcp.c:139
struct cops_gate * gate
Definition: chan_mgcp.c:322
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
char callid[80]
Definition: chan_mgcp.c:313
static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
Definition: chan_mgcp.c:2201
int state
Definition: pktccops.h:59
static int tmp()
Definition: bt_open.c:389
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2159
Definition of a media format.
Definition: format.c:43
struct sockaddr_in tmpdest
Definition: chan_mgcp.c:309
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
Socket address structure.
Definition: netsock2.h:97
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_format_cap * cap
Definition: chan_mgcp.c:374
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const struct ast_format *format, int code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:1992
#define ao2_ref(o, delta)
Definition: astobj2.h:464
uint32_t gateid
Definition: pktccops.h:55
char cxident[80]
Definition: chan_mgcp.c:312
char txident[80]
Definition: chan_mgcp.c:310
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:743
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:769
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ transmit_notify_request()

static int transmit_notify_request ( struct mgcp_subchannel sub,
char *  tone 
)
static

Definition at line 2499 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_debug, ast_strlen_zero, mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_endpoint::name, mgcp_gateway::name, NULL, mgcp_subchannel::parent, mgcp_endpoint::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), and mgcp_request::trid.

Referenced by do_monitor(), handle_hd_hf(), handle_request(), handle_response(), mgcp_answer(), mgcp_hangup(), mgcp_indicate(), mgcp_request(), mgcp_senddigit_end(), and mgcp_ss().

2500 {
2501  struct mgcp_request resp;
2502  struct mgcp_endpoint *p = sub->parent;
2503  unsigned int oseq;
2504 
2505  ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2506  tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2507  ast_copy_string(p->curtone, tone, sizeof(p->curtone));
2508  oseq = reqprep(&resp, p, "RQNT");
2509  add_header(&resp, "X", p->rqnt_ident);
2510  switch (p->hookstate) {
2511  case MGCP_ONHOOK:
2512  add_header(&resp, "R", "L/hd(N)");
2513  break;
2514  case MGCP_OFFHOOK:
2515  add_header_offhook(sub, &resp, tone);
2516  break;
2517  }
2518  if (!ast_strlen_zero(tone)) {
2519  add_header(&resp, "S", tone);
2520  }
2521  /* fill in new fields */
2522  resp.cmd = MGCP_CMD_RQNT;
2523  resp.trid = oseq;
2524  return send_request(p, NULL, &resp, oseq);
2525 }
static const char *const mgcp_cxmodes[]
Definition: chan_mgcp.c:139
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2159
char curtone[80]
Definition: chan_mgcp.c:346
char rqnt_ident[80]
Definition: chan_mgcp.c:381
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char name[80]
Definition: chan_mgcp.c:334
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:327
char name[80]
Definition: chan_mgcp.c:401
static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone)
Definition: chan_mgcp.c:2648
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:743
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ transmit_notify_request_with_callerid()

static int transmit_notify_request_with_callerid ( struct mgcp_subchannel sub,
char *  tone,
char *  callernum,
char *  callername 
)
static

Definition at line 2527 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_debug, ast_localtime(), ast_strlen_zero, ast_tvnow(), mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::lastcallerid, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_endpoint::name, mgcp_gateway::name, NULL, mgcp_subchannel::parent, mgcp_endpoint::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and mgcp_request::trid.

Referenced by mgcp_call(), and mgcp_hangup().

2528 {
2529  struct mgcp_request resp;
2530  char tone2[256];
2531  char *l, *n;
2532  struct timeval t = ast_tvnow();
2533  struct ast_tm tm;
2534  struct mgcp_endpoint *p = sub->parent;
2535  unsigned int oseq;
2536 
2537  ast_localtime(&t, &tm, NULL);
2538  n = callername;
2539  l = callernum;
2540  if (!n)
2541  n = "";
2542  if (!l)
2543  l = "";
2544 
2545  /* Keep track of last callerid for blacklist and callreturn */
2546  ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
2547 
2548  snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
2549  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
2550  ast_copy_string(p->curtone, tone, sizeof(p->curtone));
2551  oseq = reqprep(&resp, p, "RQNT");
2552  add_header(&resp, "X", p->rqnt_ident);
2553  switch (p->hookstate) {
2554  case MGCP_ONHOOK:
2555  add_header(&resp, "R", "L/hd(N)");
2556  break;
2557  case MGCP_OFFHOOK:
2558  add_header_offhook(sub, &resp, tone);
2559  break;
2560  }
2561  if (!ast_strlen_zero(tone2)) {
2562  add_header(&resp, "S", tone2);
2563  }
2564  ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2565  tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2566  /* fill in new fields */
2567  resp.cmd = MGCP_CMD_RQNT;
2568  resp.trid = oseq;
2569  return send_request(p, NULL, &resp, oseq);
2570 }
static const char *const mgcp_cxmodes[]
Definition: chan_mgcp.c:139
char lastcallerid[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:342
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2159
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
char curtone[80]
Definition: chan_mgcp.c:346
char rqnt_ident[80]
Definition: chan_mgcp.c:381
#define MGCP_ONHOOK
Definition: chan_mgcp.c:326
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char name[80]
Definition: chan_mgcp.c:334
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:327
char name[80]
Definition: chan_mgcp.c:401
static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone)
Definition: chan_mgcp.c:2648
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:743
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2065

◆ transmit_response()

static int transmit_response ( struct mgcp_subchannel sub,
char *  msg,
struct mgcp_request req,
char *  msgrest 
)
static

Definition at line 2174 of file chan_mgcp.c.

References ast_calloc, mgcp_response::buf, mgcp_request::data, mgcp_request::identifier, mgcp_request::len, mgcp_response::len, mgcp_response::next, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_gateway::responses, respprep(), send_response(), mgcp_response::seqno, and mgcp_response::whensent.

Referenced by handle_request(), and handle_response().

2175 {
2176  struct mgcp_request resp;
2177  struct mgcp_endpoint *p = sub->parent;
2178  struct mgcp_response *mgr;
2179 
2180  if (!sub) {
2181  return -1;
2182  }
2183 
2184  respprep(&resp, p, msg, req, msgrest);
2185  if (!(mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1))) {
2186  return send_response(sub, &resp);
2187  }
2188  /* Store MGCP response in case we have to retransmit */
2189  sscanf(req->identifier, "%30d", &mgr->seqno);
2190  time(&mgr->whensent);
2191  mgr->len = resp.len;
2192  memcpy(mgr->buf, resp.data, resp.len);
2193  mgr->buf[resp.len] = '\0';
2194  mgr->next = p->parent->responses;
2195  p->parent->responses = mgr;
2196 
2197  return send_response(sub, &resp);
2198 }
char * identifier
Definition: chan_mgcp.c:256
static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
Definition: chan_mgcp.c:558
struct mgcp_response * responses
Definition: chan_mgcp.c:422
struct mgcp_response * next
Definition: chan_mgcp.c:287
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
char buf[0]
Definition: chan_mgcp.c:288
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
Definition: chan_mgcp.c:2152
time_t whensent
Definition: chan_mgcp.c:284

◆ unalloc_sub()

static int unalloc_sub ( struct mgcp_subchannel sub)
static

Definition at line 506 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_debug, ast_log, ast_rtp_instance_destroy(), ast_strlen_zero, mgcp_subchannel::callid, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, dump_cmd_queues(), mgcp_subchannel::id, LOG_WARNING, MGCP_CX_INACTIVE, mgcp_set_owner(), mgcp_endpoint::name, mgcp_gateway::name, NULL, mgcp_subchannel::outgoing, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, mgcp_subchannel::tmpdest, and transmit_connection_del().

Referenced by attempt_transfer().

507 {
508  struct mgcp_endpoint *p = sub->parent;
509  if (p->sub == sub) {
510  ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
511  return -1;
512  }
513  ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
514 
515  mgcp_set_owner(sub, NULL);
516  if (!ast_strlen_zero(sub->cxident)) {
518  }
519  sub->cxident[0] = '\0';
520  sub->callid[0] = '\0';
521  sub->cxmode = MGCP_CX_INACTIVE;
522  sub->outgoing = 0;
523  sub->alreadygone = 0;
524  memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
525  if (sub->rtp) {
527  sub->rtp = NULL;
528  }
529  dump_cmd_queues(NULL, sub);
530  return 0;
531 }
char callid[80]
Definition: chan_mgcp.c:313
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:335
static void mgcp_set_owner(struct mgcp_subchannel *sub, struct ast_channel *chan)
Definition: chan_mgcp.c:1222
#define LOG_WARNING
Definition: logger.h:274
struct sockaddr_in tmpdest
Definition: chan_mgcp.c:309
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
char name[80]
Definition: chan_mgcp.c:334
char name[80]
Definition: chan_mgcp.c:401
static int transmit_connection_del(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2690
struct mgcp_gateway * parent
Definition: chan_mgcp.c:396
char cxident[80]
Definition: chan_mgcp.c:312
static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
dump_cmd_queues: (SC:) cleanup pending commands
Definition: chan_mgcp.c:2734
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:458
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:308
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:307
#define MGCP_CX_INACTIVE
Definition: chan_mgcp.c:136

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 4947 of file chan_mgcp.c.

References ao2_ref, ast_channel_register(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DRIVER, AST_MODULE_INFO(), AST_MODULE_SUPPORT_EXTENDED, ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_glue_unregister(), ast_sched_context_destroy(), ASTERISK_GPL_KEY, ast_channel_tech::capabilities, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, gatelock, gateways, load_module(), LOG_WARNING, mgcp_reload(), mgcp_reload_lock, mgcp_reloading, mgcpsock, monitor_thread, monlock, mgcp_endpoint::next, mgcp_gateway::next, NULL, prune_gateways(), and reload().

4948 {
4949  struct mgcp_endpoint *e;
4950  struct mgcp_gateway *g;
4951 
4952  /* Check to see if we're reloading */
4954  ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n");
4955  return -1;
4956  } else {
4957  mgcp_reloading = 1;
4959  }
4960 
4961  /* First, take us out of the channel loop */
4963 
4964  /* Shut down the monitoring thread */
4965  if (!ast_mutex_lock(&monlock)) {
4967  pthread_cancel(monitor_thread);
4968  pthread_kill(monitor_thread, SIGURG);
4969  pthread_join(monitor_thread, NULL);
4970  }
4973  } else {
4974  ast_log(LOG_WARNING, "Unable to lock the monitor\n");
4975  /* We always want to leave this in a consistent state */
4977  mgcp_reloading = 0;
4978  mgcp_reload(NULL, 0, NULL);
4979  return -1;
4980  }
4981 
4982  if (!ast_mutex_lock(&gatelock)) {
4983  for (g = gateways; g; g = g->next) {
4984  g->delme = 1;
4985  for (e = g->endpoints; e; e = e->next) {
4986  e->delme = 1;
4987  }
4988  }
4989 
4990  prune_gateways();
4992  } else {
4993  ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
4994  /* We always want to leave this in a consistent state */
4996  /* Allow the monitor to restart */
4998  mgcp_reloading = 0;
4999  mgcp_reload(NULL, 0, NULL);
5000  return -1;
5001  }
5002 
5003  if (mgcpsock > -1) {
5004  close(mgcpsock);
5005  }
5007  ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
5009 
5014 
5015  return 0;
5016 }
static int mgcpsock
Definition: chan_mgcp.c:432
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:430
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static char * mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mgcp.c:4908
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
descriptor for a cli entry.
Definition: cli.h:171
#define LOG_WARNING
Definition: logger.h:274
static struct ast_format_cap * global_capability
Definition: chan_mgcp.c:235
Definition: sched.c:76
#define ast_mutex_lock(a)
Definition: lock.h:187
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
#define NULL
Definition: resample.c:96
static void prune_gateways(void)
Definition: chan_mgcp.c:4608
#define ast_log
Definition: astobj2.c:42
#define ast_mutex_trylock(a)
Definition: lock.h:189
#define AST_PTHREADT_NULL
Definition: lock.h:66
struct mgcp_gateway * next
Definition: chan_mgcp.c:423
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ast_channel_tech mgcp_tech
Definition: chan_mgcp.c:472
static pthread_t monitor_thread
Definition: chan_mgcp.c:231
static ast_mutex_t monlock
Definition: chan_mgcp.c:226
static int mgcp_reloading
Definition: chan_mgcp.c:427
struct ast_format_cap * capabilities
Definition: channel.h:633
static struct mgcp_gateway * gateways
static struct ast_cli_entry cli_mgcp[]
Definition: chan_mgcp.c:1149
static ast_mutex_t mgcp_reload_lock
Definition: chan_mgcp.c:426
static struct ast_rtp_glue mgcp_rtp_glue
Definition: chan_mgcp.c:4511
#define AST_PTHREADT_STOP
Definition: lock.h:67
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Definition: rtp_engine.c:408
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:408
struct mgcp_endpoint * next
Definition: chan_mgcp.c:395
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
#define ast_mutex_unlock(a)
Definition: lock.h:188

Variable Documentation

◆ __mod_info

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

Definition at line 5025 of file chan_mgcp.c.

◆ __ourip

struct in_addr __ourip
static

Definition at line 239 of file chan_mgcp.c.

Referenced by build_gateway(), find_subchannel_and_lock(), and reload_config().

◆ accountcode

char accountcode[AST_MAX_ACCOUNT_CODE] = ""
static

Definition at line 202 of file chan_mgcp.c.

Referenced by build_gateway().

◆ adsi

int adsi = 0
static

Definition at line 208 of file chan_mgcp.c.

Referenced by build_gateway().

◆ amaflags

int amaflags = 0
static

Definition at line 206 of file chan_mgcp.c.

Referenced by build_gateway().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 5025 of file chan_mgcp.c.

◆ bindaddr

struct sockaddr_in bindaddr
static

Definition at line 434 of file chan_mgcp.c.

Referenced by reload_config(), and start_rtp().

◆ callreturn

int callreturn = 0
static

Definition at line 187 of file chan_mgcp.c.

Referenced by build_gateway().

◆ callwaiting

int callwaiting = 0
static

Definition at line 185 of file chan_mgcp.c.

Referenced by build_gateway().

◆ cancallforward

int cancallforward = 0
static

Definition at line 196 of file chan_mgcp.c.

Referenced by build_gateway().

◆ cid_name

char cid_name[AST_MAX_EXTENSION] = ""
static

◆ cid_num

char cid_num[AST_MAX_EXTENSION] = ""
static

◆ cli_mgcp

struct ast_cli_entry cli_mgcp[]
static

Definition at line 1149 of file chan_mgcp.c.

◆ config

const char config[] = "mgcp.conf"
static

Definition at line 117 of file chan_mgcp.c.

Referenced by reload_config().

◆ context

char context[AST_MAX_EXTENSION] = "default"
static

Definition at line 159 of file chan_mgcp.c.

Referenced by build_gateway().

◆ cos

unsigned int cos

Definition at line 179 of file chan_mgcp.c.

◆ cos_audio

unsigned int cos_audio

Definition at line 180 of file chan_mgcp.c.

◆ cur_callergroup

ast_group_t cur_callergroup = 0
static

Definition at line 173 of file chan_mgcp.c.

Referenced by build_gateway().

◆ cur_pickupgroup

ast_group_t cur_pickupgroup = 0
static

Definition at line 174 of file chan_mgcp.c.

Referenced by build_gateway().

◆ default_jbconf

struct ast_jb_conf default_jbconf
static

Global jitterbuffer configuration - by default, jb is disabled

Note
Values shown here match the defaults shown in mgcp.conf.sample

Definition at line 106 of file chan_mgcp.c.

◆ directmedia

int directmedia = DIRECTMEDIA
static

Definition at line 200 of file chan_mgcp.c.

Referenced by build_gateway().

◆ dtmfmode

int dtmfmode = 0
static

Definition at line 167 of file chan_mgcp.c.

Referenced by build_gateway(), and reload_config().

◆ firstdigittimeout

int firstdigittimeout = 16000
static

Wait up to 16 seconds for first digit (FXO logic)

Definition at line 214 of file chan_mgcp.c.

Referenced by disa_exec(), mgcp_ss(), and reload_config().

◆ gatelock

ast_mutex_t gatelock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

◆ gateways

struct mgcp_gateway * gateways = NULL
static

◆ gendigittimeout

int gendigittimeout = 8000
static

How long to wait for following digits (FXO logic)

Definition at line 217 of file chan_mgcp.c.

Referenced by mgcp_ss(), and reload_config().

◆ global_capability

struct ast_format_cap* global_capability
static

Definition at line 235 of file chan_mgcp.c.

◆ global_jbconf

struct ast_jb_conf global_jbconf
static

Definition at line 114 of file chan_mgcp.c.

Referenced by mgcp_new(), and reload_config().

◆ hangupongateremove

int hangupongateremove = 0
static

Definition at line 171 of file chan_mgcp.c.

Referenced by build_gateway().

◆ immediate

int immediate = 0
static

Definition at line 183 of file chan_mgcp.c.

Referenced by build_gateway().

◆ io

struct io_context* io
static

Definition at line 245 of file chan_mgcp.c.

◆ language

char language[MAX_LANGUAGE] = ""
static

Definition at line 161 of file chan_mgcp.c.

Referenced by build_gateway().

◆ mailbox

char mailbox[AST_MAX_MAILBOX_UNIQUEID]
static

◆ matchdigittimeout

int matchdigittimeout = 3000
static

How long to wait for an extra digit, if there is an ambiguous match

Definition at line 220 of file chan_mgcp.c.

Referenced by mgcp_ss(), and reload_config().

◆ mgcp_cxmodes

const char* const mgcp_cxmodes[]
static

◆ mgcp_reload_lock

ast_mutex_t mgcp_reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 426 of file chan_mgcp.c.

Referenced by do_monitor(), mgcp_reload(), and unload_module().

◆ mgcp_reloading

int mgcp_reloading = 0
static

Definition at line 427 of file chan_mgcp.c.

Referenced by do_monitor(), mgcp_reload(), and unload_module().

◆ mgcp_rtp_glue

struct ast_rtp_glue mgcp_rtp_glue
static

Definition at line 4511 of file chan_mgcp.c.

◆ mgcp_tech

struct ast_channel_tech mgcp_tech
static

Definition at line 472 of file chan_mgcp.c.

◆ mgcpdebug

int mgcpdebug = 0
static

Definition at line 242 of file chan_mgcp.c.

Referenced by handle_mgcp_audit_endpoint(), and handle_mgcp_set_debug().

◆ mgcpsock

int mgcpsock = -1
static

Definition at line 432 of file chan_mgcp.c.

Referenced by __mgcp_xmit(), do_monitor(), mgcpsock_read(), reload_config(), and unload_module().

◆ mgcpsock_read_id

int* mgcpsock_read_id = NULL
static

Definition at line 3758 of file chan_mgcp.c.

Referenced by do_monitor(), and reload_config().

◆ monitor_thread

pthread_t monitor_thread = AST_PTHREADT_NULL
static

This is the thread for the monitor which checks for input on the channels which are not currently in use.

Definition at line 231 of file chan_mgcp.c.

Referenced by reload_config(), restart_monitor(), and unload_module().

◆ monlock

ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 226 of file chan_mgcp.c.

Referenced by do_monitor(), restart_monitor(), and unload_module().

◆ musicclass

char musicclass[MAX_MUSICCLASS] = ""
static

◆ nat

int nat = 0
static

◆ ncs

int ncs = 0
static

Definition at line 169 of file chan_mgcp.c.

Referenced by build_gateway().

◆ netlock

ast_mutex_t netlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.

Definition at line 224 of file chan_mgcp.c.

Referenced by do_monitor(), and reload_config().

◆ nonCodecCapability

int nonCodecCapability = AST_RTP_DTMF
static

Definition at line 236 of file chan_mgcp.c.

Referenced by process_sdp().

◆ oseq_global

unsigned int oseq_global = 0
static

Definition at line 210 of file chan_mgcp.c.

Referenced by reqprep().

◆ oseq_lock

ast_mutex_t oseq_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 211 of file chan_mgcp.c.

Referenced by reqprep().

◆ ourhost

char ourhost[MAXHOSTNAMELEN]
static

Definition at line 238 of file chan_mgcp.c.

Referenced by ast_find_ourip(), and reload_config().

◆ ourport

int ourport
static

Definition at line 240 of file chan_mgcp.c.

Referenced by initreqprep(), reload_config(), and transmit_notify_with_mwi().

◆ parkinglot

char parkinglot[AST_MAX_CONTEXT]
static

◆ pktcgatealloc

int pktcgatealloc = 0
static

Definition at line 170 of file chan_mgcp.c.

Referenced by build_gateway().

◆ qos

struct { ... } qos

Referenced by reload_config(), and start_rtp().

◆ sched

struct ast_sched_context* sched
static

Definition at line 244 of file chan_mgcp.c.

◆ singlepath

int singlepath = 0
static

Definition at line 198 of file chan_mgcp.c.

Referenced by build_gateway().

◆ slowsequence

int slowsequence = 0
static

Definition at line 189 of file chan_mgcp.c.

Referenced by build_gateway().

◆ tdesc

const char tdesc[] = "Media Gateway Control Protocol (MGCP)"
static

Definition at line 116 of file chan_mgcp.c.

◆ threewaycalling

int threewaycalling = 0
static

Definition at line 191 of file chan_mgcp.c.

Referenced by build_gateway().

◆ tos

unsigned int tos

Definition at line 177 of file chan_mgcp.c.

◆ tos_audio

unsigned int tos_audio

Definition at line 178 of file chan_mgcp.c.

◆ transfer

int transfer = 0
static

This is for flashhook transfers

Definition at line 194 of file chan_mgcp.c.

Referenced by ast_transfer_protocol(), build_gateway(), iax2_send(), jb_debug_output(), leave_voicemail(), and transfer_exec().