Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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_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 resolve_first_addr (const char *hostname, struct in_addr *sin_addr)
 Resolve the given hostname and save its IPv4 address. More...
 
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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_DEPRECATED, .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 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 99 of file chan_mgcp.c.

◆ DEFAULT_MGCP_CA_PORT

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 127 of file chan_mgcp.c.

◆ DEFAULT_MGCP_GW_PORT

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 126 of file chan_mgcp.c.

◆ DEFAULT_RETRANS

#define DEFAULT_RETRANS   1000

How frequently to retransmit

Definition at line 129 of file chan_mgcp.c.

◆ DIRECTMEDIA

#define DIRECTMEDIA   1

Definition at line 101 of file chan_mgcp.c.

◆ INADDR_NONE

#define INADDR_NONE   (in_addr_t)(-1)

Definition at line 104 of file chan_mgcp.c.

◆ MAX_EXPIRY

#define MAX_EXPIRY   3600

Definition at line 100 of file chan_mgcp.c.

◆ MAX_RETRANS

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 130 of file chan_mgcp.c.

◆ MAX_SUBS

#define MAX_SUBS   2

Definition at line 292 of file chan_mgcp.c.

◆ MGCP_CX_CONF

#define MGCP_CX_CONF   3

Definition at line 136 of file chan_mgcp.c.

◆ MGCP_CX_CONFERENCE

#define MGCP_CX_CONFERENCE   3

Definition at line 137 of file chan_mgcp.c.

◆ MGCP_CX_INACTIVE

#define MGCP_CX_INACTIVE   4

Definition at line 139 of file chan_mgcp.c.

◆ MGCP_CX_MUTE

#define MGCP_CX_MUTE   4

Definition at line 138 of file chan_mgcp.c.

◆ MGCP_CX_RECVONLY

#define MGCP_CX_RECVONLY   1

Definition at line 134 of file chan_mgcp.c.

◆ MGCP_CX_SENDONLY

#define MGCP_CX_SENDONLY   0

MGCP rtp stream modes {

Definition at line 133 of file chan_mgcp.c.

◆ MGCP_CX_SENDRECV

#define MGCP_CX_SENDRECV   2

Definition at line 135 of file chan_mgcp.c.

◆ MGCP_DTMF_HYBRID

#define MGCP_DTMF_HYBRID   (1 << 2)

Definition at line 124 of file chan_mgcp.c.

◆ MGCP_DTMF_INBAND

#define MGCP_DTMF_INBAND   (1 << 1)

Definition at line 123 of file chan_mgcp.c.

◆ MGCP_DTMF_RFC2833

#define MGCP_DTMF_RFC2833   (1 << 0)

Definition at line 122 of file chan_mgcp.c.

◆ MGCP_MAX_HEADERS

#define MGCP_MAX_HEADERS   64

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

Definition at line 251 of file chan_mgcp.c.

◆ MGCP_MAX_LINES

#define MGCP_MAX_LINES   64

Definition at line 252 of file chan_mgcp.c.

◆ MGCP_MAX_PACKET

#define MGCP_MAX_PACKET   1500

Also from RFC 2543, should sub headers tho

Definition at line 128 of file chan_mgcp.c.

◆ MGCP_OFFHOOK

#define MGCP_OFFHOOK   2

Definition at line 328 of file chan_mgcp.c.

◆ MGCP_ONHOOK

#define MGCP_ONHOOK   1

Definition at line 327 of file chan_mgcp.c.

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

◆ MGCPDUMPER

#define MGCPDUMPER

Definition at line 98 of file chan_mgcp.c.

◆ RESPONSE_TIMEOUT

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 282 of file chan_mgcp.c.

◆ SUB_ALT

#define SUB_ALT   1

Definition at line 295 of file chan_mgcp.c.

◆ SUB_REAL

#define SUB_REAL   0

Definition at line 294 of file chan_mgcp.c.

◆ TYPE_LINE

#define TYPE_LINE   2

Definition at line 331 of file chan_mgcp.c.

◆ TYPE_TRUNK

#define TYPE_TRUNK   1

Definition at line 330 of file chan_mgcp.c.

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

150  {
160 };
@ MGCP_CMD_NTFY
Definition: chan_mgcp.c:156
@ MGCP_CMD_EPCF
Definition: chan_mgcp.c:151
@ MGCP_CMD_AUEP
Definition: chan_mgcp.c:157
@ MGCP_CMD_DLCX
Definition: chan_mgcp.c:154
@ MGCP_CMD_CRCX
Definition: chan_mgcp.c:152
@ MGCP_CMD_RQNT
Definition: chan_mgcp.c:155
@ MGCP_CMD_RSIP
Definition: chan_mgcp.c:159
@ MGCP_CMD_AUCX
Definition: chan_mgcp.c:158
@ MGCP_CMD_MDCX
Definition: chan_mgcp.c:153

Function Documentation

◆ __get_header()

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

Definition at line 1607 of file chan_mgcp.c.

1608 {
1609  int x;
1610  int len = strlen(name);
1611  char *r;
1612  for (x = *start; x < req->headers; x++) {
1613  if (!strncasecmp(req->header[x], name, len) &&
1614  (req->header[x][len] == ':')) {
1615  r = req->header[x] + len + 1;
1616  while (*r && (*r < 33)) {
1617  r++;
1618  }
1619  *start = x + 1;
1620  return r;
1621  }
1622  }
1623  /* Don't return NULL, so get_header is always a valid pointer */
1624  return def;
1625 }
static const char name[]
Definition: format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * header[MGCP_MAX_HEADERS]
Definition: chan_mgcp.c:261

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

Referenced by get_header().

◆ __mgcp_xmit()

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

Definition at line 535 of file chan_mgcp.c.

536 {
537  int res;
538  if (gw->addr.sin_addr.s_addr)
539  res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
540  else
541  res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
542  if (res != len) {
543  ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
544  }
545  return res;
546 }
#define ast_log
Definition: astobj2.c:42
static int mgcpsock
Definition: chan_mgcp.c:433
#define LOG_WARNING
int errno
struct sockaddr_in defaddr
Definition: chan_mgcp.c:405
struct sockaddr_in addr
Definition: chan_mgcp.c:404

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

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

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 5009 of file chan_mgcp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 5009 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 4485 of file chan_mgcp.c.

4486 {
4487  struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
4488  int res = 0;
4489 
4490  /* Sanity check */
4491  if (!chan || ast_channel_tech(chan) != &mgcp_tech) {
4492  ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n");
4493  return -1;
4494  }
4495 
4496  if (!strcasecmp(args, "ncs")) {
4497  snprintf(buf, buflen, "%s", sub->parent->ncs ? "yes":"no");
4498  } else {
4499  res = -1;
4500  }
4501  return res;
4502 }
static struct ast_channel_tech mgcp_tech
Definition: chan_mgcp.c:473
void * ast_channel_tech_pvt(const struct ast_channel *chan)
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_ERROR
struct stasis_forward * sub
Definition: res_corosync.c:240
const char * args

References args, ast_channel_tech(), ast_channel_tech_pvt(), ast_log, buf, LOG_ERROR, mgcp_tech, and sub.

◆ add_header()

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

Definition at line 2031 of file chan_mgcp.c.

2032 {
2033  if (req->len >= sizeof(req->data) - 4) {
2034  ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
2035  return -1;
2036  }
2037  if (req->lines) {
2038  ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
2039  return -1;
2040  }
2041  req->header[req->headers] = req->data + req->len;
2042  snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
2043  req->len += strlen(req->header[req->headers]);
2044  if (req->headers < MGCP_MAX_HEADERS) {
2045  req->headers++;
2046  } else {
2047  ast_log(LOG_WARNING, "Out of header space\n");
2048  return -1;
2049  }
2050  return 0;
2051 }
#define var
Definition: ast_expr2f.c:614
#define MGCP_MAX_HEADERS
Definition: chan_mgcp.c:251
char data[MGCP_MAX_PACKET]
Definition: chan_mgcp.c:264
int value
Definition: syslog.c:37

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

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

◆ add_header_offhook()

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

Definition at line 2614 of file chan_mgcp.c.

2615 {
2616  struct mgcp_endpoint *p = sub->parent;
2617  char tone_indicate_end = 0;
2618 
2619  /* We also should check the tone to indicate, because it have no sense
2620  to request notify D/[0-9#*] (dtmf keys) if we are sending congestion
2621  tone for example G/cg */
2622  if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) {
2623  tone_indicate_end = 1;
2624  }
2625 
2626  if (p && p->sub && p->sub->owner &&
2629  add_header(resp, "R", "L/hu(N),L/hf(N)");
2630 
2631  } else if (!tone_indicate_end){
2632  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)"));
2633  } else {
2634  ast_debug(1, "We don't want more digits if we will end the call\n");
2635  add_header(resp, "R", "L/hu(N),L/hf(N)");
2636  }
2637 }
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2031
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:123
#define MGCP_DTMF_HYBRID
Definition: chan_mgcp.c:124
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RINGING
Definition: channelstate.h:41
#define ast_debug(level,...)
Log a DEBUG message.
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:336
struct ast_channel * owner
Definition: chan_mgcp.c:307

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

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

◆ add_line()

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

Definition at line 2053 of file chan_mgcp.c.

2054 {
2055  if (req->len >= sizeof(req->data) - 4) {
2056  ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
2057  return -1;
2058  }
2059  if (!req->lines) {
2060  /* Add extra empty return */
2061  ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
2062  req->len += strlen(req->data + req->len);
2063  }
2064  req->line[req->lines] = req->data + req->len;
2065  snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
2066  req->len += strlen(req->line[req->lines]);
2067  if (req->lines < MGCP_MAX_LINES) {
2068  req->lines++;
2069  } else {
2070  ast_log(LOG_WARNING, "Out of line space\n");
2071  return -1;
2072  }
2073  return 0;
2074 }
#define MGCP_MAX_LINES
Definition: chan_mgcp.c:252
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:406
char * line[MGCP_MAX_LINES]
Definition: chan_mgcp.c:263

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

◆ add_sdp()

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

Definition at line 2167 of file chan_mgcp.c.

2168 {
2169  int len;
2170  int codec;
2171  char costr[80];
2172  struct sockaddr_in sin;
2173  struct ast_sockaddr sin_tmp;
2174  char v[256];
2175  char s[256];
2176  char o[256];
2177  char c[256];
2178  char t[256];
2179  char m[256] = "";
2180  char a[1024] = "";
2181  int x;
2182  struct sockaddr_in dest = { 0, };
2183  struct ast_sockaddr dest_tmp;
2184  struct mgcp_endpoint *p = sub->parent;
2185  /* XXX We break with the "recommendation" and send our IP, in order that our
2186  peer doesn't have to ast_gethostbyname() us XXX */
2187  len = 0;
2188  if (!sub->rtp) {
2189  ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
2190  return -1;
2191  }
2192  ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp);
2193  ast_sockaddr_to_sin(&sin_tmp, &sin);
2194  if (rtp) {
2195  ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp);
2196  ast_sockaddr_to_sin(&dest_tmp, &dest);
2197  } else {
2198  if (sub->tmpdest.sin_addr.s_addr) {
2199  dest.sin_addr = sub->tmpdest.sin_addr;
2200  dest.sin_port = sub->tmpdest.sin_port;
2201  /* Reset temporary destination */
2202  memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
2203  } else {
2204  dest.sin_addr = p->parent->ourip;
2205  dest.sin_port = sin.sin_port;
2206  }
2207  }
2208  ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
2209  ast_copy_string(v, "v=0\r\n", sizeof(v));
2210  snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
2211  ast_copy_string(s, "s=session\r\n", sizeof(s));
2212  snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
2213  ast_copy_string(t, "t=0 0\r\n", sizeof(t));
2214  snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
2215 
2216  for (x = 0; x < ast_format_cap_count(p->cap); x++) {
2218 
2220  ao2_ref(format, -1);
2221  continue;
2222  }
2223 
2224  ast_debug(1, "Answering with capability %s\n", ast_format_get_name(format));
2226  if (codec > -1) {
2227  snprintf(costr, sizeof(costr), " %d", codec);
2228  strncat(m, costr, sizeof(m) - strlen(m) - 1);
2229  snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
2230  strncat(a, costr, sizeof(a) - strlen(a) - 1);
2231  }
2232 
2233  ao2_ref(format, -1);
2234  }
2235 
2236  for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
2237  if (p->nonCodecCapability & x) {
2238  ast_debug(1, "Answering with non-codec capability %d\n", (int) x);
2240  if (codec > -1) {
2241  snprintf(costr, sizeof(costr), " %d", codec);
2242  strncat(m, costr, sizeof(m) - strlen(m) - 1);
2243  snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, NULL, x, 0));
2244  strncat(a, costr, sizeof(a) - strlen(a) - 1);
2245  if (x == AST_RTP_DTMF) {
2246  /* Indicate we support DTMF... Not sure about 16,
2247  but MSN supports it so dang it, we will too... */
2248  snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
2249  strncat(a, costr, sizeof(a) - strlen(a) - 1);
2250  }
2251  }
2252  }
2253  }
2254  strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
2255  len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
2256  snprintf(costr, sizeof(costr), "%d", len);
2257  add_line(resp, v);
2258  add_line(resp, o);
2259  add_line(resp, s);
2260  add_line(resp, c);
2261  add_line(resp, t);
2262  add_line(resp, m);
2263  add_line(resp, a);
2264  return 0;
2265 }
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
static snd_pcm_format_t format
Definition: chan_alsa.c:106
static int add_line(struct mgcp_request *req, char *line)
Definition: chan_mgcp.c:2053
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
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_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
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_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:765
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:928
#define NULL
Definition: resample.c:96
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 AST_RTP_DTMF
Definition: rtp_engine.h:266
#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
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
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:1984
#define AST_RTP_MAX
Definition: rtp_engine.h:272
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:1865
Definition of a media format.
Definition: format.c:43
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47
Socket address structure.
Definition: netsock2.h:97
int nonCodecCapability
Definition: chan_mgcp.c:376
struct mgcp_gateway * parent
Definition: chan_mgcp.c:397
struct ast_format_cap * cap
Definition: chan_mgcp.c:375
struct in_addr ourip
Definition: chan_mgcp.c:406
static struct test_val a
static struct test_val 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, ast_format::codec, format, len(), LOG_WARNING, mgcp_endpoint::nonCodecCapability, NULL, mgcp_gateway::ourip, mgcp_endpoint::parent, and sub.

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

◆ add_var()

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

Definition at line 4617 of file chan_mgcp.c.

4618 {
4619  struct ast_variable *tmpvar = NULL;
4620  char *varname = ast_strdupa(buf), *varval = NULL;
4621 
4622  if ((varval = strchr(varname, '='))) {
4623  *varval++ = '\0';
4624  if ((tmpvar = ast_variable_new(varname, varval, ""))) {
4625  tmpvar->next = list;
4626  list = tmpvar;
4627  }
4628  }
4629  return list;
4630 }
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_variable_new(name, value, filename)
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next

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

Referenced by build_gateway().

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 5009 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 3247 of file chan_mgcp.c.

3248 {
3249  enum ast_transfer_result res;
3250 
3251  /* Ensure that the other channel goes off hold and that it is indicating properly */
3252  ast_queue_unhold(sub->next->owner);
3253  if (ast_channel_state(sub->owner) == AST_STATE_RINGING) {
3254  ast_queue_control(sub->next->owner, AST_CONTROL_RINGING);
3255  }
3256 
3257  ast_mutex_unlock(&p->sub->next->lock);
3258  ast_mutex_unlock(&p->sub->lock);
3259  res = ast_bridge_transfer_attended(sub->owner, sub->next->owner);
3260 
3261  /* Subs are only freed when the endpoint itself is destroyed, so they will continue to exist
3262  * after ast_bridge_transfer_attended returns making this safe without reference counting
3263  */
3264  ast_mutex_lock(&p->sub->lock);
3265  ast_mutex_lock(&p->sub->next->lock);
3266 
3267  if (res != AST_BRIDGE_TRANSFER_SUCCESS) {
3268  /* If transferring fails hang up the other channel if present and us */
3269  if (sub->next->owner) {
3271  mgcp_queue_hangup(sub->next);
3272  }
3273  sub->next->alreadygone = 1;
3274  return 0;
3275  }
3276 
3277  unalloc_sub(sub->next);
3278 
3279  /* If the active sub is NOT the one completing the transfer change it to be, and hang up the other sub */
3280  if (p->sub != sub) {
3281  p->sub = sub;
3282  return 1;
3283  }
3284 
3285  return 0;
3286 }
ast_transfer_result
Definition: bridge.h:1098
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1100
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4662
static int unalloc_sub(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:507
static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:622
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1225
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1210
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
@ AST_CONTROL_RINGING
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:187
struct mgcp_subchannel * next
Definition: chan_mgcp.c:324
ast_mutex_t lock
Definition: chan_mgcp.c:305

References 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_endpoint::sub, sub, and unalloc_sub().

Referenced by handle_request().

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

3983 {
3984  struct mgcp_gateway *gw;
3985  struct mgcp_endpoint *e;
3986  struct mgcp_subchannel *sub;
3987  struct ast_variable *chanvars = NULL;
3988 
3989  /*char txident[80];*/
3990  int i=0, y=0;
3991  int gw_reload = 0;
3992  int ep_reload = 0;
3994 
3995  /* locate existing gateway */
3996  for (gw = gateways; gw; gw = gw->next) {
3997  if (!strcasecmp(cat, gw->name)) {
3998  /* gateway already exists */
3999  gw->delme = 0;
4000  gw_reload = 1;
4001  break;
4002  }
4003  }
4004 
4005  if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) {
4006  return NULL;
4007  }
4008 
4009  if (!gw_reload) {
4010  gw->expire = -1;
4011  gw->realtime = 0;
4012  gw->retransid = -1;
4013  ast_mutex_init(&gw->msgs_lock);
4014  ast_copy_string(gw->name, cat, sizeof(gw->name));
4015  /* check if the name is numeric ip */
4016  if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
4017  gw->isnamedottedip = 1;
4018  }
4019  for (; v; v = v->next) {
4020  if (!strcasecmp(v->name, "host")) {
4021  if (!strcasecmp(v->value, "dynamic")) {
4022  /* They'll register with us */
4023  gw->dynamic = 1;
4024  memset(&gw->addr.sin_addr, 0, 4);
4025  if (gw->addr.sin_port) {
4026  /* If we've already got a port, make it the default rather than absolute */
4027  gw->defaddr.sin_port = gw->addr.sin_port;
4028  gw->addr.sin_port = 0;
4029  }
4030  } else {
4031  /* Non-dynamic. Make sure we become that way if we're not */
4032  AST_SCHED_DEL(sched, gw->expire);
4033  gw->dynamic = 0;
4034  {
4035  struct ast_sockaddr tmp;
4036 
4037  ast_sockaddr_from_sin(&tmp, &gw->addr);
4038  if (ast_get_ip(&tmp, v->value)) {
4039  if (!gw_reload) {
4041  ast_free(gw);
4042  }
4043  return NULL;
4044  }
4045  ast_sockaddr_to_sin(&tmp, &gw->addr);
4046  }
4047  }
4048  } else if (!strcasecmp(v->name, "defaultip")) {
4049  struct ast_sockaddr tmp;
4050 
4052  if (ast_get_ip(&tmp, v->value)) {
4053  if (!gw_reload) {
4055  ast_free(gw);
4056  }
4057  return NULL;
4058  }
4060  } else if (!strcasecmp(v->name, "permit") ||
4061  !strcasecmp(v->name, "deny")) {
4062  int acl_error = 0;
4063  gw->ha = ast_append_ha(v->name, v->value, gw->ha, &acl_error);
4064  if (acl_error) {
4065  ast_log(LOG_ERROR, "Invalid ACL '%s' specified for MGCP gateway '%s' on line %d. Not creating.\n",
4066  v->value, cat, v->lineno);
4067  if (!gw_reload) {
4069  ast_free(gw);
4070  } else {
4071  gw->delme = 1;
4072  }
4073  return NULL;
4074  }
4075  } else if (!strcasecmp(v->name, "port")) {
4076  gw->addr.sin_port = htons(atoi(v->value));
4077  } else if (!strcasecmp(v->name, "context")) {
4078  ast_copy_string(context, v->value, sizeof(context));
4079  } else if (!strcasecmp(v->name, "dtmfmode")) {
4080  if (!strcasecmp(v->value, "inband"))
4082  else if (!strcasecmp(v->value, "rfc2833"))
4084  else if (!strcasecmp(v->value, "hybrid"))
4086  else if (!strcasecmp(v->value, "none"))
4087  dtmfmode = 0;
4088  else
4089  ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
4090  } else if (!strcasecmp(v->name, "nat")) {
4091  nat = ast_true(v->value);
4092  } else if (!strcasecmp(v->name, "ncs")) {
4093  ncs = ast_true(v->value);
4094  } else if (!strcasecmp(v->name, "hangupongateremove")) {
4096  } else if (!strcasecmp(v->name, "pktcgatealloc")) {
4098  } else if (!strcasecmp(v->name, "callerid")) {
4099  if (!strcasecmp(v->value, "asreceived")) {
4100  cid_num[0] = '\0';
4101  cid_name[0] = '\0';
4102  } else {
4103  ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
4104  }
4105  } else if (!strcasecmp(v->name, "language")) {
4106  ast_copy_string(language, v->value, sizeof(language));
4107  } else if (!strcasecmp(v->name, "accountcode")) {
4109  } else if (!strcasecmp(v->name, "amaflags")) {
4111  if (y < 0) {
4112  ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
4113  } else {
4114  amaflags = y;
4115  }
4116  } else if (!strcasecmp(v->name, "setvar")) {
4117  chanvars = add_var(v->value, chanvars);
4118  } else if (!strcasecmp(v->name, "clearvars")) {
4119  if (chanvars) {
4120  ast_variables_destroy(chanvars);
4121  chanvars = NULL;
4122  }
4123  } else if (!strcasecmp(v->name, "musiconhold")) {
4125  } else if (!strcasecmp(v->name, "parkinglot")) {
4127  } else if (!strcasecmp(v->name, "callgroup")) {
4129  } else if (!strcasecmp(v->name, "pickupgroup")) {
4131  } else if (!strcasecmp(v->name, "immediate")) {
4132  immediate = ast_true(v->value);
4133  } else if (!strcasecmp(v->name, "cancallforward")) {
4135  } else if (!strcasecmp(v->name, "singlepath")) {
4136  singlepath = ast_true(v->value);
4137  } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
4138  directmedia = ast_true(v->value);
4139  } else if (!strcasecmp(v->name, "mailbox")) {
4140  ast_copy_string(mailbox, v->value, sizeof(mailbox));
4141  } else if (!strcasecmp(v->name, "hasvoicemail")) {
4142  if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
4143  /*
4144  * hasvoicemail is a users.conf legacy voicemail enable method.
4145  * hasvoicemail is only going to work for app_voicemail mailboxes.
4146  */
4147  if (strchr(gw->name, '@')) {
4148  ast_copy_string(mailbox, gw->name, sizeof(mailbox));
4149  } else {
4150  snprintf(mailbox, sizeof(mailbox), "%s@default", gw->name);
4151  }
4152  }
4153  } else if (!strcasecmp(v->name, "adsi")) {
4154  adsi = ast_true(v->value);
4155  } else if (!strcasecmp(v->name, "callreturn")) {
4156  callreturn = ast_true(v->value);
4157  } else if (!strcasecmp(v->name, "callwaiting")) {
4158  callwaiting = ast_true(v->value);
4159  } else if (!strcasecmp(v->name, "slowsequence")) {
4160  slowsequence = ast_true(v->value);
4161  } else if (!strcasecmp(v->name, "transfer")) {
4162  transfer = ast_true(v->value);
4163  } else if (!strcasecmp(v->name, "threewaycalling")) {
4165  } else if (!strcasecmp(v->name, "wcardep")) {
4166  /* locate existing endpoint */
4167  for (e = gw->endpoints; e; e = e->next) {
4168  if (!strcasecmp(v->value, e->name)) {
4169  /* endpoint already exists */
4170  e->delme = 0;
4171  ep_reload = 1;
4172  break;
4173  }
4174  }
4175 
4176  if (!e) {
4177  /* Allocate wildcard endpoint */
4178  e = ast_calloc(1, sizeof(*e));
4179  ep_reload = 0;
4180  }
4181 
4182  if (e) {
4183  if (!ep_reload) {
4184  memset(e, 0, sizeof(struct mgcp_endpoint));
4185  ast_mutex_init(&e->lock);
4189  ast_copy_string(e->name, v->value, sizeof(e->name));
4190  e->needaudit = 1;
4191  }
4192  ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
4193  /* XXX Should we really check for uniqueness?? XXX */
4195  ast_copy_string(e->context, context, sizeof(e->context));
4196  ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
4197  ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
4198  ast_copy_string(e->language, language, sizeof(e->language));
4200  ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
4202  if (!ast_strlen_zero(e->mailbox)) {
4203  /* This module does not handle MWI in an event-based manner. However, it
4204  * subscribes to MWI for each mailbox that is configured so that the core
4205  * knows that we care about it. Then, chan_mgcp will get the MWI from the
4206  * event cache instead of checking the mailbox directly. */
4208  }
4209  snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", (unsigned long)ast_random());
4210  e->msgstate = -1;
4211  e->amaflags = amaflags;
4213  e->parent = gw;
4214  e->ncs = ncs;
4215  e->dtmfmode = dtmfmode;
4216  if (!ep_reload && e->sub && e->sub->rtp) {
4217  e->dtmfmode |= MGCP_DTMF_INBAND;
4218  }
4219  e->adsi = adsi;
4220  e->type = TYPE_LINE;
4221  e->immediate = immediate;
4224  e->callreturn = callreturn;
4226  e->singlepath = singlepath;
4227  e->directmedia = directmedia;
4228  e->callwaiting = callwaiting;
4231  e->transfer = transfer;
4233  e->onhooktime = time(NULL);
4234  /* ASSUME we're onhook */
4235  e->hookstate = MGCP_ONHOOK;
4236  e->chanvars = copy_vars(chanvars);
4237  if (!ep_reload) {
4238  /*snprintf(txident, sizeof(txident), "%08lx", (unsigned long)ast_random());*/
4239  for (i = 0; i < MAX_SUBS; i++) {
4240  sub = ast_calloc(1, sizeof(*sub));
4241  if (sub) {
4242  ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
4243  ast_mutex_init(&sub->lock);
4244  ast_mutex_init(&sub->cx_queue_lock);
4245  sub->parent = e;
4246  sub->id = i;
4247  snprintf(sub->txident, sizeof(sub->txident), "%08lx", (unsigned long)ast_random());
4248  /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/
4249  sub->cxmode = MGCP_CX_INACTIVE;
4250  sub->nat = nat;
4251  sub->gate = NULL;
4252  sub->sdpsent = 0;
4253  sub->next = e->sub;
4254  e->sub = sub;
4255  } else {
4256  /* XXX Should find a way to clean up our memory */
4257  ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
4258  return NULL;
4259  }
4260  }
4261  /* Make out subs a circular linked list so we can always sping through the whole bunch */
4262  /* find the end of the list */
4263  for (sub = e->sub; sub && sub->next; sub = sub->next);
4264  /* set the last sub->next to the first sub */
4265  sub->next = e->sub;
4266 
4267  e->next = gw->endpoints;
4268  gw->endpoints = e;
4269  }
4270  }
4271  } else if (!strcasecmp(v->name, "trunk") ||
4272  !strcasecmp(v->name, "line")) {
4273 
4274  /* locate existing endpoint */
4275  for (e = gw->endpoints; e; e = e->next) {
4276  if (!strcasecmp(v->value, e->name)) {
4277  /* endpoint already exists */
4278  e->delme = 0;
4279  ep_reload = 1;
4280  break;
4281  }
4282  }
4283 
4284  if (!e) {
4285  e = ast_calloc(1, sizeof(*e));
4286  ep_reload = 0;
4287  }
4288 
4289  if (e) {
4290  if (!ep_reload) {
4291  ast_mutex_init(&e->lock);
4295  ast_copy_string(e->name, v->value, sizeof(e->name));
4296  e->needaudit = 1;
4297  }
4298  /* XXX Should we really check for uniqueness?? XXX */
4300  ast_copy_string(e->context, context, sizeof(e->context));
4301  ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
4302  ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
4303  ast_copy_string(e->language, language, sizeof(e->language));
4305  ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
4307  if (!ast_strlen_zero(mailbox)) {
4308  ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
4309  }
4310  if (!ep_reload) {
4311  /* XXX potential issue due to reload */
4312  e->msgstate = -1;
4313  e->parent = gw;
4314  }
4315  e->amaflags = amaflags;
4317  e->dtmfmode = dtmfmode;
4318  e->ncs = ncs;
4321  e->adsi = adsi;
4322  e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE;
4323  e->immediate = immediate;
4326  e->callreturn = callreturn;
4328  e->directmedia = directmedia;
4329  e->singlepath = singlepath;
4330  e->callwaiting = callwaiting;
4333  e->transfer = transfer;
4335 
4336  /* If we already have a valid chanvars, it's not a new endpoint (it's a reload),
4337  so first, free previous mem
4338  */
4339  if (e->chanvars) {
4341  e->chanvars = NULL;
4342  }
4343  e->chanvars = copy_vars(chanvars);
4344 
4345  if (!ep_reload) {
4346  e->onhooktime = time(NULL);
4347  /* ASSUME we're onhook */
4348  e->hookstate = MGCP_ONHOOK;
4349  snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", (unsigned long)ast_random());
4350  }
4351 
4352  for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
4353  if (!ep_reload) {
4354  sub = ast_calloc(1, sizeof(*sub));
4355  } else {
4356  if (!sub) {
4357  sub = e->sub;
4358  } else {
4359  sub = sub->next;
4360  }
4361  }
4362 
4363  if (sub) {
4364  if (!ep_reload) {
4365  ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
4366  ast_mutex_init(&sub->lock);
4367  ast_mutex_init(&sub->cx_queue_lock);
4368  ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
4369  sub->parent = e;
4370  sub->id = i;
4371  snprintf(sub->txident, sizeof(sub->txident), "%08lx", (unsigned long)ast_random());
4372  sub->cxmode = MGCP_CX_INACTIVE;
4373  sub->next = e->sub;
4374  e->sub = sub;
4375  }
4376  sub->nat = nat;
4377  } else {
4378  /* XXX Should find a way to clean up our memory */
4379  ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
4380  return NULL;
4381  }
4382  }
4383  if (!ep_reload) {
4384  /* Make out subs a circular linked list so we can always sping through the whole bunch */
4385  /* find the end of the list */
4386  for (sub = e->sub; sub && sub->next; sub = sub->next);
4387  /* set the last sub->next to the first sub */
4388  sub->next = e->sub;
4389 
4390  e->next = gw->endpoints;
4391  gw->endpoints = e;
4392  }
4393  }
4394  } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) {
4395  /* just eliminate realtime warnings */
4396  } else {
4397  ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
4398  }
4399  }
4400  if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
4401  ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
4402  if (!gw_reload) {
4404  ast_free(gw);
4405  }
4406 
4407  /* Return NULL */
4408  gw_reload = 1;
4409  } else {
4410  gw->defaddr.sin_family = AF_INET;
4411  gw->addr.sin_family = AF_INET;
4412  if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) {
4413  gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
4414  }
4415  if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) {
4416  gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
4417  }
4418  {
4419  struct ast_sockaddr tmp1, tmp2;
4420  struct sockaddr_in tmp3 = {0,};
4421 
4422  tmp3.sin_addr = gw->ourip;
4423  ast_sockaddr_from_sin(&tmp1, &gw->addr);
4424  ast_sockaddr_from_sin(&tmp2, &tmp3);
4425  if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) {
4426  memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
4427  } else {
4428  ast_sockaddr_to_sin(&tmp2, &tmp3);
4429  gw->ourip = tmp3.sin_addr;
4430  }
4431  }
4432  }
4433 
4434  if (chanvars) {
4435  ast_variables_destroy(chanvars);
4436  chanvars = NULL;
4437  }
4438  return (gw_reload ? NULL : gw);
4439 }
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
int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
Get the IP address given a hostname.
Definition: acl.c:1000
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 ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static int tmp()
Definition: bt_open.c:389
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1092
static int slowsequence
Definition: chan_mgcp.c:192
static int dtmfmode
Definition: chan_mgcp.c:170
static int ncs
Definition: chan_mgcp.c:172
static struct in_addr __ourip
Definition: chan_mgcp.c:242
static int threewaycalling
Definition: chan_mgcp.c:194
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:167
static ast_group_t cur_callergroup
Definition: chan_mgcp.c:176
static int singlepath
Definition: chan_mgcp.c:201
#define INADDR_NONE
Definition: chan_mgcp.c:104
static int pktcgatealloc
Definition: chan_mgcp.c:173
#define MAX_SUBS
Definition: chan_mgcp.c:292
static int callwaiting
Definition: chan_mgcp.c:188
static struct ast_variable * add_var(const char *buf, struct ast_variable *list)
Definition: chan_mgcp.c:4617
static char context[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:162
static int directmedia
Definition: chan_mgcp.c:203
#define TYPE_TRUNK
Definition: chan_mgcp.c:330
static int adsi
Definition: chan_mgcp.c:211
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:166
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:207
static struct ast_variable * copy_vars(struct ast_variable *src)
duplicate a list of channel variables,
Definition: chan_mgcp.c:4635
static struct mgcp_gateway * gateways
#define MGCP_CX_INACTIVE
Definition: chan_mgcp.c:139
static ast_group_t cur_pickupgroup
Definition: chan_mgcp.c:177
static int transfer
Definition: chan_mgcp.c:197
#define MGCP_SUBCHANNEL_MAGIC
Definition: chan_mgcp.c:303
#define MGCP_DTMF_RFC2833
Definition: chan_mgcp.c:122
#define DIRECTMEDIA
Definition: chan_mgcp.c:101
static char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:165
#define TYPE_LINE
Definition: chan_mgcp.c:331
static int amaflags
Definition: chan_mgcp.c:209
static int immediate
Definition: chan_mgcp.c:186
static int nat
Definition: chan_mgcp.c:171
static int hangupongateremove
Definition: chan_mgcp.c:174
#define MGCP_ONHOOK
Definition: chan_mgcp.c:327
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:168
static char language[MAX_LANGUAGE]
Definition: chan_mgcp.c:164
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_mgcp.c:205
static int callreturn
Definition: chan_mgcp.c:190
static int cancallforward
Definition: chan_mgcp.c:199
static struct ast_format_cap * global_capability
Definition: chan_mgcp.c:238
#define DEFAULT_MGCP_GW_PORT
Definition: chan_mgcp.c:126
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4395
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7701
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
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_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define ast_verb(level,...)
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_mutex_destroy(a)
Definition: lock.h:186
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:235
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:778
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
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
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: main/utils.c:2097
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
int slowsequence
Definition: chan_mgcp.c:370
struct ast_variable * chanvars
Definition: chan_mgcp.c:395
char rqnt_ident[80]
Definition: chan_mgcp.c:382
ast_mutex_t cmd_queue_lock
Definition: chan_mgcp.c:386
int threewaycalling
Definition: chan_mgcp.c:356
char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:341
struct ast_mwi_subscriber * mwi_event_sub
Definition: chan_mgcp.c:350
char name[80]
Definition: chan_mgcp.c:335
int pktcgatealloc
Definition: chan_mgcp.c:367
char context[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:339
ast_mutex_t rqnt_queue_lock
Definition: chan_mgcp.c:384
char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:349
struct mgcp_endpoint * next
Definition: chan_mgcp.c:396
ast_group_t pickupgroup
Definition: chan_mgcp.c:352
char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:346
int hascallwaiting
Definition: chan_mgcp.c:354
char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:348
int hangupongateremove
Definition: chan_mgcp.c:368
char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:342
ast_mutex_t lock
Definition: chan_mgcp.c:334
char language[MAX_LANGUAGE]
Definition: chan_mgcp.c:340
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_mgcp.c:337
int cancallforward
Definition: chan_mgcp.c:358
ast_group_t callgroup
Definition: chan_mgcp.c:351
struct mgcp_gateway * next
Definition: chan_mgcp.c:424
char name[80]
Definition: chan_mgcp.c:402
ast_mutex_t msgs_lock
Definition: chan_mgcp.c:419
struct ast_ha * ha
Definition: chan_mgcp.c:410
char wcardep[30]
Definition: chan_mgcp.c:417
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:409
int isnamedottedip
Definition: chan_mgcp.c:403
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:309
Definition: sched.c:76
long int ast_random(void)
Definition: main/utils.c:2210

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_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, gateways, global_capability, mgcp_gateway::ha, hangupongateremove, mgcp_endpoint::hangupongateremove, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, immediate, mgcp_endpoint::immediate, INADDR_NONE, mgcp_gateway::isnamedottedip, language, mgcp_endpoint::language, ast_variable::lineno, mgcp_endpoint::lock, LOG_ERROR, LOG_WARNING, mgcp_endpoint::mailbox, 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, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::name, nat, ncs, mgcp_endpoint::ncs, mgcp_endpoint::needaudit, mgcp_endpoint::next, mgcp_gateway::next, ast_variable::next, NULL, mgcp_endpoint::onhooktime, mgcp_gateway::ourip, 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, singlepath, mgcp_endpoint::singlepath, slowsequence, mgcp_endpoint::slowsequence, stasis_subscription_cb_noop(), mgcp_endpoint::sub, sub, threewaycalling, mgcp_endpoint::threewaycalling, tmp(), transfer, mgcp_endpoint::transfer, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, and mgcp_gateway::wcardep.

Referenced by find_realtime_gw(), and reload_config().

◆ control2str()

static char* control2str ( int  ind)
static

Definition at line 1378 of file chan_mgcp.c.

1378  {
1379  switch (ind) {
1380  case AST_CONTROL_HANGUP:
1381  return "Other end has hungup";
1382  case AST_CONTROL_RING:
1383  return "Local ring";
1384  case AST_CONTROL_RINGING:
1385  return "Remote end is ringing";
1386  case AST_CONTROL_ANSWER:
1387  return "Remote end has answered";
1388  case AST_CONTROL_BUSY:
1389  return "Remote end is busy";
1391  return "Make it go off hook";
1392  case AST_CONTROL_OFFHOOK:
1393  return "Line is off hook";
1395  return "Congestion (circuits busy)";
1396  case AST_CONTROL_FLASH:
1397  return "Flash hook";
1398  case AST_CONTROL_WINK:
1399  return "Wink";
1400  case AST_CONTROL_OPTION:
1401  return "Set a low-level option";
1402  case AST_CONTROL_RADIO_KEY:
1403  return "Key Radio";
1405  return "Un-Key Radio";
1406  }
1407  return "UNKNOWN";
1408 }
@ AST_CONTROL_RING
@ AST_CONTROL_WINK
@ AST_CONTROL_OFFHOOK
@ AST_CONTROL_RADIO_UNKEY
@ AST_CONTROL_BUSY
@ AST_CONTROL_TAKEOFFHOOK
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_HANGUP
@ AST_CONTROL_RADIO_KEY
@ AST_CONTROL_OPTION
@ AST_CONTROL_FLASH

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

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

4636 {
4637  struct ast_variable *res = NULL, *tmp, *v = NULL;
4638 
4639  for (v = src ; v ; v = v->next) {
4640  if ((tmp = ast_variable_new(v->name, v->value, v->file))) {
4641  tmp->next = res;
4642  res = tmp;
4643  }
4644  }
4645  return res;
4646 }

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

Referenced by build_gateway().

◆ destroy_endpoint()

static void destroy_endpoint ( struct mgcp_endpoint e)
static

Definition at line 4505 of file chan_mgcp.c.

4506 {
4507  struct mgcp_subchannel *sub = e->sub->next, *s;
4508  int i;
4509 
4510  for (i = 0; i < MAX_SUBS; i++) {
4511  ast_mutex_lock(&sub->lock);
4512  if (!ast_strlen_zero(sub->cxident)) {
4514  }
4515  if (sub->rtp) {
4517  sub->rtp = NULL;
4518  }
4519  memset(sub->magic, 0, sizeof(sub->magic));
4522  if(sub->gate) {
4523  sub->gate->tech_pvt = NULL;
4524  sub->gate->got_dq_gi = NULL;
4525  sub->gate->gate_remove = NULL;
4526  sub->gate->gate_open = NULL;
4527  }
4528  ast_mutex_unlock(&sub->lock);
4529  sub = sub->next;
4530  }
4531 
4532  if (e->dsp) {
4533  ast_dsp_free(e->dsp);
4534  }
4535 
4536  dump_queue(e->parent, e);
4537  dump_cmd_queues(e, NULL);
4538 
4539  sub = e->sub;
4540  for (i = 0; (i < MAX_SUBS) && sub; i++) {
4541  s = sub;
4542  sub = sub->next;
4543  ast_mutex_destroy(&s->lock);
4544  ast_mutex_destroy(&s->cx_queue_lock);
4545  ast_free(s);
4546  }
4547 
4548  if (e->mwi_event_sub) {
4550  }
4551 
4552  if (e->chanvars) {
4554  e->chanvars = NULL;
4555  }
4556 
4557  ast_mutex_destroy(&e->lock);
4560  ao2_ref(e->cap, -1);
4561  ast_free(e);
4562 }
static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
Definition: chan_mgcp.c:571
static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
dump_cmd_queues: (SC:) cleanup pending commands
Definition: chan_mgcp.c:2700
static int transmit_connection_del(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2656
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1773
void * ast_mwi_unsubscribe(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic and MWI.
Definition: mwi.c:254
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:458
struct ast_dsp * dsp
Definition: chan_mgcp.c:389

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_endpoint::dsp, dump_cmd_queues(), dump_queue(), mgcp_endpoint::lock, MAX_SUBS, mgcp_queue_hangup(), mgcp_endpoint::mwi_event_sub, mgcp_subchannel::next, NULL, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue_lock, mgcp_endpoint::sub, sub, and transmit_connection_del().

Referenced by prune_gateways().

◆ destroy_gateway()

static void destroy_gateway ( struct mgcp_gateway g)
static

Definition at line 4564 of file chan_mgcp.c.

4565 {
4566  if (g->ha)
4567  ast_free_ha(g->ha);
4568 
4569  dump_queue(g, NULL);
4570 
4571  ast_free(g);
4572 }
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222

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

Referenced by prune_gateways().

◆ do_monitor()

static void* do_monitor ( void *  data)
static

Definition at line 3784 of file chan_mgcp.c.

3785 {
3786  int res;
3787  int reloading;
3788  struct mgcp_gateway *g, *gprev;
3789  /*struct mgcp_gateway *g;*/
3790  /*struct mgcp_endpoint *e;*/
3791  /*time_t thispass = 0, lastpass = 0;*/
3792  time_t lastrun = 0;
3793 
3794  /* Add an I/O event to our UDP socket */
3795  if (mgcpsock > -1) {
3797  }
3798  /* This thread monitors all the frame relay interfaces which are not yet in use
3799  (and thus do not have a separate thread) indefinitely */
3800  /* From here on out, we die whenever asked */
3801  for (;;) {
3802  /* Check for a reload request */
3804  reloading = mgcp_reloading;
3805  mgcp_reloading = 0;
3807  if (reloading) {
3808  ast_verb(1, "Reloading MGCP\n");
3809  reload_config(1);
3810  /* Add an I/O event to our UDP socket */
3811  if (mgcpsock > -1 && !mgcpsock_read_id) {
3813  }
3814  }
3815 
3816  /* Check for interfaces needing to be killed */
3817  /* Don't let anybody kill us right away. Nobody should lock the interface list
3818  and wait for the monitor list, but the other way around is okay. */
3820  /* Lock the network interface */
3822 
3823 #if 0
3824  /* XXX THIS IS COMPLETELY HOSED */
3825  /* The gateway goes into a state of panic */
3826  /* If the vmwi indicator is sent while it is reseting interfaces */
3827  lastpass = thispass;
3828  thispass = time(NULL);
3829  g = gateways;
3830  while(g) {
3831  if (thispass != lastpass) {
3832  e = g->endpoints;
3833  while(e) {
3834  if (e->type == TYPE_LINE) {
3835  res = has_voicemail(e);
3836  if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
3837  if (res) {
3838  transmit_notify_request(e, "L/vmwi(+)");
3839  } else {
3840  transmit_notify_request(e, "L/vmwi(-)");
3841  }
3842  e->msgstate = res;
3843  e->onhooktime = thispass;
3844  }
3845  }
3846  e = e->next;
3847  }
3848  }
3849  g = g->next;
3850  }
3851 #endif
3852  /* pruning unused realtime gateways, running in every 60 seconds*/
3853  if(time(NULL) > (lastrun + 60)) {
3855  g = gateways;
3856  gprev = NULL;
3857  while(g) {
3858  if(g->realtime) {
3860  if(gprev) {
3861  gprev->next = g->next;
3862  } else {
3863  gateways = g->next;
3864  }
3867  ast_free(g);
3868  } else {
3870  gprev = g;
3871  }
3872  } else {
3873  gprev = g;
3874  }
3875  g = g->next;
3876  }
3878  lastrun = time(NULL);
3879  }
3880  /* Okay, now that we know what to do, release the network lock */
3882  /* And from now on, we're okay to be killed, so release the monitor lock as well */
3884  pthread_testcancel();
3885  /* Wait for sched or io */
3886  res = ast_sched_wait(sched);
3887  /* copied from chan_sip.c */
3888  if ((res < 0) || (res > 1000)) {
3889  res = 1000;
3890  }
3891  res = ast_io_wait(io, res);
3893  if (res >= 0) {
3895  }
3897  }
3898  /* Never reached */
3899  return NULL;
3900 }
static int reload_config(int reload)
Definition: chan_mgcp.c:4673
static int mgcp_reloading
Definition: chan_mgcp.c:428
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2465
static int mgcpsock_read(int *id, int fd, short events, void *ignore)
Definition: chan_mgcp.c:3635
static int mgcp_prune_realtime_gateway(struct mgcp_gateway *g)
Definition: chan_mgcp.c:3726
static int * mgcpsock_read_id
Definition: chan_mgcp.c:3724
static ast_mutex_t mgcp_reload_lock
Definition: chan_mgcp.c:427
static ast_mutex_t monlock
Definition: chan_mgcp.c:229
static struct io_context * io
Definition: chan_mgcp.c:246
static int has_voicemail(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:491
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:431
static ast_mutex_t netlock
Definition: chan_mgcp.c:227
#define AST_IO_IN
Definition: io.h:34
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:278
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
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:786
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:433

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

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

2701 {
2702  struct mgcp_request *t, *q;
2703 
2704  if (p) {
2706  for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
2707  p->rqnt_queue = NULL;
2709 
2711  for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
2712  p->cmd_queue = NULL;
2714 
2716  for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
2717  p->sub->cx_queue = NULL;
2719 
2721  for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
2722  p->sub->next->cx_queue = NULL;
2724  } else if (sub) {
2725  ast_mutex_lock(&sub->cx_queue_lock);
2726  for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
2727  sub->cx_queue = NULL;
2728  ast_mutex_unlock(&sub->cx_queue_lock);
2729  }
2730 }
struct mgcp_request * cmd_queue
Definition: chan_mgcp.c:385
struct mgcp_request * rqnt_queue
Definition: chan_mgcp.c:383
struct mgcp_request * next
Definition: chan_mgcp.c:267
struct mgcp_request * cx_queue
Definition: chan_mgcp.c:316
ast_mutex_t cx_queue_lock
Definition: chan_mgcp.c:317

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, mgcp_endpoint::sub, and sub.

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

◆ dump_queue()

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

Definition at line 571 of file chan_mgcp.c.

572 {
573  struct mgcp_message *cur, *q = NULL, *w, *prev;
574 
576  for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
577  if (!p || cur->owner_ep == p) {
578  if (prev) {
579  prev->next = cur->next;
580  } else {
581  gw->msgs = cur->next;
582  }
583 
584  ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
585  gw->name, cur->seqno);
586 
587  w = cur;
588  if (q) {
589  w->next = q;
590  } else {
591  w->next = NULL;
592  }
593  q = w;
594  }
595  }
597 
598  while (q) {
599  cur = q;
600  q = q->next;
601  ast_free(cur);
602  }
603 }
#define LOG_NOTICE
struct mgcp_message * msgs
Definition: chan_mgcp.c:418
mgcp_message: MGCP message for queuing up
Definition: chan_mgcp.c:271
struct mgcp_message * next
Definition: chan_mgcp.c:278
struct mgcp_endpoint * owner_ep
Definition: chan_mgcp.c:272
unsigned int seqno
Definition: chan_mgcp.c:276

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

◆ find_and_retrans()

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

Definition at line 3605 of file chan_mgcp.c.

3606 {
3607  int seqno=0;
3608  time_t now;
3609  struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL;
3610  time(&now);
3611  if (sscanf(req->identifier, "%30d", &seqno) != 1) {
3612  seqno = 0;
3613  }
3614  for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) {
3615  if (now - cur->whensent > RESPONSE_TIMEOUT) {
3616  /* Delete this entry */
3617  if (prev)
3618  prev->next = next;
3619  else
3620  sub->parent->parent->responses = next;
3621  ast_free(cur);
3622  } else {
3623  if (seqno == cur->seqno)
3624  answer = cur;
3625  prev = cur;
3626  }
3627  }
3628  if (answer) {
3630  return 1;
3631  }
3632  return 0;
3633 }
static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
Definition: chan_mgcp.c:548
#define RESPONSE_TIMEOUT
Definition: chan_mgcp.c:282
static int answer(void *data)
Definition: chan_pjsip.c:675
char * identifier
Definition: chan_mgcp.c:257
struct mgcp_response * next
Definition: chan_mgcp.c:288

References answer(), ast_free, mgcp_request::identifier, mgcp_response::next, NULL, resend_response(), RESPONSE_TIMEOUT, mgcp_response::seqno, and sub.

Referenced by mgcpsock_read().

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

2736 {
2737  struct mgcp_request *prev, *req;
2738 
2739  ast_mutex_lock(l);
2740  for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
2741  if (req->trid == ident) {
2742  /* remove from queue */
2743  if (!prev)
2744  *queue = req->next;
2745  else
2746  prev->next = req->next;
2747 
2748  /* send next pending command */
2749  if (*queue) {
2750  ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
2751  ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
2752 
2753  mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
2754  }
2755  break;
2756  }
2757  }
2758  ast_mutex_unlock(l);
2759  return req;
2760 }
static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno)
Definition: chan_mgcp.c:700

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

Referenced by handle_response().

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

1659 {
1660  struct mgcp_gateway *g = NULL;
1661  struct ast_variable *mgcpgwconfig = NULL;
1662  struct ast_variable *gwv, *epname = NULL;
1663  struct mgcp_endpoint *e;
1664  char lines[256];
1665  int i, j;
1666 
1667  ast_debug(1, "*** find Realtime MGCPGW\n");
1668 
1669  if (!(i = ast_check_realtime("mgcpgw")) || !(j = ast_check_realtime("mgcpep"))) {
1670  return NULL;
1671  }
1672 
1673  if (ast_strlen_zero(at)) {
1674  ast_debug(1, "null gw name\n");
1675  return NULL;
1676  }
1677 
1678  if (!(mgcpgwconfig = ast_load_realtime("mgcpgw", "name", at, NULL))) {
1679  return NULL;
1680  }
1681 
1682  /*!
1683  * \note This is a fairly odd way of instantiating lines. Instead of each
1684  * line created by virtue of being in the database (and loaded via
1685  * ast_load_realtime_multientry), this code forces a specific order with a
1686  * "lines" entry in the "mgcpgw" record. This has benefits, because as with
1687  * chan_dahdi, values are inherited across definitions. The downside is
1688  * that it's not as clear what the values will be simply by looking at a
1689  * single row in the database, and it's probable that the sanest configuration
1690  * should have the first column in the "mgcpep" table be "clearvars", with a
1691  * static value of "all", if any variables are set at all. It may be worth
1692  * making this assumption explicit in the code in the future, and then just
1693  * using ast_load_realtime_multientry for the "mgcpep" records.
1694  */
1695  lines[0] = '\0';
1696  for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
1697  if (!strcasecmp(gwv->name, "lines")) {
1698  ast_copy_string(lines, gwv->value, sizeof(lines));
1699  break;
1700  }
1701  }
1702  /* Position gwv at the end of the list */
1703  for (gwv = gwv && gwv->next ? gwv : mgcpgwconfig; gwv->next; gwv = gwv->next);
1704 
1705  if (!ast_strlen_zero(lines)) {
1707  AST_APP_ARG(line)[100];
1708  );
1710  for (i = 0; i < args.argc; i++) {
1711  gwv->next = ast_load_realtime("mgcpep", "name", at, "line", args.line[i], NULL);
1712 
1713  /* Remove "line" AND position gwv at the end of the list. */
1714  for (epname = NULL; gwv->next; gwv = gwv->next) {
1715  if (!strcasecmp(gwv->next->name, "line")) {
1716  /* Remove it from the list */
1717  epname = gwv->next;
1718  gwv->next = gwv->next->next;
1719  }
1720  }
1721  /* Since "line" instantiates the configuration, we have to move it to the end. */
1722  if (epname) {
1723  gwv->next = epname;
1724  epname->next = NULL;
1725  gwv = gwv->next;
1726  }
1727  }
1728  }
1729  for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
1730  ast_debug(1, "MGCP Realtime var: %s => %s\n", gwv->name, gwv->value);
1731  }
1732 
1733  if (mgcpgwconfig) {
1734  g = build_gateway(at, mgcpgwconfig);
1735  ast_variables_destroy(mgcpgwconfig);
1736  }
1737  if (g) {
1738  g->next = gateways;
1739  g->realtime = 1;
1740  gateways = g;
1741  for (e = g->endpoints; e; e = e->next) {
1743  e->needaudit = 0;
1744  }
1745  }
1746  return g;
1747 }
static int transmit_audit_endpoint(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:2642
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:3982
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3405
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3429

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, mgcp_endpoint::next, mgcp_gateway::next, ast_variable::next, NULL, mgcp_gateway::realtime, transmit_audit_endpoint(), and ast_variable::value.

Referenced by find_subchannel_and_lock().

◆ find_subchannel_and_lock()

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

Definition at line 1749 of file chan_mgcp.c.

1750 {
1751  struct mgcp_endpoint *p = NULL;
1752  struct mgcp_subchannel *sub = NULL;
1753  struct mgcp_gateway *g;
1754  char tmp[256] = "";
1755  char *at = NULL, *c;
1756  int found = 0;
1757  if (name) {
1758  ast_copy_string(tmp, name, sizeof(tmp));
1759  at = strchr(tmp, '@');
1760  if (!at) {
1761  ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
1762  return NULL;
1763  }
1764  *at++ = '\0';
1765  }
1767  if (at && (at[0] == '[')) {
1768  at++;
1769  c = strrchr(at, ']');
1770  if (c) {
1771  *c = '\0';
1772  }
1773  }
1774  for (g = gateways ? gateways : find_realtime_gw(name, at, sin); g; g = g->next ? g->next : find_realtime_gw(name, at, sin)) {
1775  if ((!name || !strcasecmp(g->name, at)) &&
1776  (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
1777  /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */
1778  if (sin && g->dynamic && name) {
1779  if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1780  (g->addr.sin_port != sin->sin_port)) {
1781  memcpy(&g->addr, sin, sizeof(g->addr));
1782  {
1783  struct ast_sockaddr tmp1, tmp2;
1784  struct sockaddr_in tmp3 = {0,};
1785 
1786  tmp3.sin_addr = g->ourip;
1787  ast_sockaddr_from_sin(&tmp1, &g->addr);
1788  ast_sockaddr_from_sin(&tmp2, &tmp3);
1789  if (ast_ouraddrfor(&tmp1, &tmp2)) {
1790  memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
1791  }
1792  ast_sockaddr_to_sin(&tmp2, &tmp3);
1793  g->ourip = tmp3.sin_addr;
1794  }
1795  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));
1796  }
1797  /* not dynamic, check if the name matches */
1798  } else if (name) {
1799  if (strcasecmp(g->name, at)) {
1800  continue;
1801  }
1802  /* not dynamic, no name, check if the addr matches */
1803  } else if (!name && sin) {
1804  if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1805  (g->addr.sin_port != sin->sin_port)) {
1806  continue;
1807  }
1808  } else {
1809  continue;
1810  }
1811  for (p = g->endpoints; p; p = p->next) {
1812  ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name);
1813  if (msgid) {
1814  sub = p->sub;
1815  found = 1;
1816  break;
1817  } else if (name && !strcasecmp(p->name, tmp)) {
1818  ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
1819  p->name, g->name, p->sub->id);
1820  sub = p->sub;
1821  found = 1;
1822  break;
1823  }
1824  }
1825  if (sub && found) {
1826  ast_mutex_lock(&sub->lock);
1827  break;
1828  }
1829  }
1830  }
1832  if (!sub) {
1833  if (name) {
1834  if (g) {
1835  ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
1836  } else {
1837  ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
1838  }
1839  }
1840  }
1841  return sub;
1842 }
static struct mgcp_gateway * find_realtime_gw(char *name, char *at, struct sockaddr_in *sin)
Definition: chan_mgcp.c:1658

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, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, name, mgcp_endpoint::next, mgcp_gateway::next, NULL, mgcp_gateway::ourip, mgcp_endpoint::sub, sub, and tmp().

Referenced by mgcp_request(), and mgcpsock_read().

◆ get_csv()

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

get_csv: (SC:) get comma separated value

Definition at line 1634 of file chan_mgcp.c.

1635 {
1636  char *s;
1637 
1638  *next = NULL, *len = 0;
1639  if (!c) return NULL;
1640 
1641  while (*c && (*c < 33 || *c == ',')) {
1642  c++;
1643  }
1644 
1645  s = c;
1646  while (*c && (*c >= 33 && *c != ',')) {
1647  c++, (*len)++;
1648  }
1649  *next = c;
1650 
1651  if (*len == 0) {
1652  s = NULL, *next = NULL;
1653  }
1654 
1655  return s;
1656 }

References c, len(), and NULL.

Referenced by handle_response().

◆ get_header()

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

Definition at line 1627 of file chan_mgcp.c.

1628 {
1629  int start = 0;
1630  return __get_header(req, name, &start, "");
1631 }
static char * __get_header(struct mgcp_request *req, char *name, int *start, char *def)
Definition: chan_mgcp.c:1607

References __get_header(), and name.

Referenced by handle_request(), and handle_response().

◆ get_sdp()

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

Definition at line 1578 of file chan_mgcp.c.

1579 {
1580  int x;
1581  int len = strlen(name);
1582  char *r;
1583 
1584  for (x = 0; x < req->lines; x++) {
1585  r = get_sdp_by_line(req->line[x], name, len);
1586  if (r[0] != '\0') return r;
1587  }
1588  return "";
1589 }
static char * get_sdp_by_line(char *line, char *name, int nameLen)
Definition: chan_mgcp.c:1568

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

Referenced by process_sdp().

◆ get_sdp_by_line()

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

Definition at line 1568 of file chan_mgcp.c.

1569 {
1570  if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
1571  char *r = line + nameLen + 1;
1572  while (*r && (*r < 33)) ++r;
1573  return r;
1574  }
1575  return "";
1576 }

References name.

Referenced by get_sdp(), and get_sdp_iterate().

◆ get_sdp_iterate()

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

Definition at line 1596 of file chan_mgcp.c.

1597 {
1598  int len = strlen(name);
1599  char *r;
1600  while (*iterator < req->lines) {
1601  r = get_sdp_by_line(req->line[(*iterator)++], name, len);
1602  if (r[0] != '\0') return r;
1603  }
1604  return "";
1605 }

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

Referenced by process_sdp().

◆ handle_hd_hf()

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

Definition at line 3288 of file chan_mgcp.c.

3289 {
3290  struct mgcp_endpoint *p = sub->parent;
3291  struct ast_channel *c;
3292  pthread_t t;
3293 
3294  /* Off hook / answer */
3295  if (sub->outgoing) {
3296  /* Answered */
3297  if (sub->owner) {
3298  ast_queue_unhold(sub->owner);
3299  sub->cxmode = MGCP_CX_SENDRECV;
3300  if (!sub->rtp) {
3301  start_rtp(sub);
3302  } else {
3304  }
3305  /*transmit_notify_request(sub, "aw");*/
3308  }
3309  } else {
3310  /* Start switch */
3311  /*sub->cxmode = MGCP_CX_SENDRECV;*/
3312  if (!sub->owner) {
3313  if (!sub->rtp) {
3314  start_rtp(sub);
3315  } else {
3317  }
3318  if (p->immediate) {
3319  /* The channel is immediately up. Start right away */
3320 #ifdef DLINK_BUGGY_FIRMWARE
3322 #else
3323  transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt");
3324 #endif
3326  if (!c) {
3327  ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
3328  transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
3329  ast_hangup(c);
3330  }
3331  } else {
3332  if (has_voicemail(p)) {
3333  transmit_notify_request(sub, "L/sl");
3334  } else {
3335  transmit_notify_request(sub, "L/dl");
3336  }
3338  if (c) {
3340  ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
3341  ast_hangup(c);
3342  }
3343  } else {
3344  ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
3345  }
3346  }
3347  } else {
3348  if (p->hookstate == MGCP_OFFHOOK) {
3349  ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
3350  } else {
3351  ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
3352  ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
3353  }
3354  ast_queue_unhold(sub->owner);
3355  sub->cxmode = MGCP_CX_SENDRECV;
3356  if (!sub->rtp) {
3357  start_rtp(sub);
3358  } else {
3360  }
3361  /*transmit_notify_request(sub, "aw");*/
3363  /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
3364  }
3365  }
3366 }
static int transmit_modify_request(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2538
static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
Definition: chan_mgcp.c:639
static void * mgcp_ss(void *data)
Definition: chan_mgcp.c:2966
static void start_rtp(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2933
#define MGCP_CX_SENDRECV
Definition: chan_mgcp.c:135
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:1466
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:328
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2542
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_DOWN
Definition: channelstate.h:36
Main Channel structure associated with a channel.
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:583

References AST_CONTROL_ANSWER, ast_hangup(), ast_log, ast_pthread_create_detached, ast_queue_unhold(), AST_STATE_DOWN, AST_STATE_RING, c, 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_endpoint::parent, start_rtp(), sub, transmit_modify_request(), and transmit_notify_request().

Referenced by handle_request().

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

1062 {
1063  struct mgcp_gateway *mg;
1064  struct mgcp_endpoint *me;
1065  int found = 0;
1066  char *ename,*gname, *c;
1067 
1068  switch (cmd) {
1069  case CLI_INIT:
1070  e->command = "mgcp audit endpoint";
1071  e->usage =
1072  "Usage: mgcp audit endpoint <endpointid>\n"
1073  " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
1074  " Debug logging (core set debug on) MUST be on to see the results of this command.\n";
1075  return NULL;
1076  case CLI_GENERATE:
1077  return NULL;
1078  }
1079 
1080  if (!DEBUG_ATLEAST(1)) {
1081  return CLI_SHOWUSAGE;
1082  }
1083  if (a->argc != 4)
1084  return CLI_SHOWUSAGE;
1085  /* split the name into parts by null */
1086  ename = ast_strdupa(a->argv[3]);
1087  for (gname = ename; *gname; gname++) {
1088  if (*gname == '@') {
1089  *gname = 0;
1090  gname++;
1091  break;
1092  }
1093  }
1094  if (gname[0] == '[') {
1095  gname++;
1096  }
1097  if ((c = strrchr(gname, ']'))) {
1098  *c = '\0';
1099  }
1101  for (mg = gateways; mg; mg = mg->next) {
1102  if (!strcasecmp(mg->name, gname)) {
1103  for (me = mg->endpoints; me; me = me->next) {
1104  if (!strcasecmp(me->name, ename)) {
1105  found = 1;
1107  break;
1108  }
1109  }
1110  if (found) {
1111  break;
1112  }
1113  }
1114  }
1115  if (!found) {
1116  ast_cli(a->fd, " << Could not find endpoint >> ");
1117  }
1119  return CLI_SUCCESS;
1120 }
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define DEBUG_ATLEAST(level)
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177

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

1020 {
1021  struct mgcp_gateway *mg;
1022  struct mgcp_endpoint *me;
1023  int hasendpoints = 0;
1024  struct ast_variable * v = NULL;
1025 
1026  switch (cmd) {
1027  case CLI_INIT:
1028  e->command = "mgcp show endpoints";
1029  e->usage =
1030  "Usage: mgcp show endpoints\n"
1031  " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
1032  return NULL;
1033  case CLI_GENERATE:
1034  return NULL;
1035  }
1036 
1037  if (a->argc != 3) {
1038  return CLI_SHOWUSAGE;
1039  }
1041  for (mg = gateways; mg; mg = mg->next) {
1042  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");
1043  for (me = mg->endpoints; me; me = me->next) {
1044  ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
1045  if (me->chanvars) {
1046  ast_cli(a->fd, " Variables:\n");
1047  for (v = me->chanvars ; v ; v = v->next) {
1048  ast_cli(a->fd, " %s = '%s'\n", v->name, v->value);
1049  }
1050  }
1051  hasendpoints = 1;
1052  }
1053  if (!hasendpoints) {
1054  ast_cli(a->fd, " << No Endpoints Defined >> ");
1055  }
1056  }
1058  return CLI_SUCCESS;
1059 }

References a, mgcp_gateway::addr, 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, gatelock, gateways, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::name, mgcp_endpoint::next, mgcp_gateway::next, ast_variable::next, NULL, mgcp_subchannel::owner, mgcp_gateway::realtime, mgcp_endpoint::sub, ast_cli_entry::usage, and ast_variable::value.

◆ handle_request()

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

Definition at line 3368 of file chan_mgcp.c.

3369 {
3370  char *ev, *s;
3371  struct ast_frame f = { 0, };
3372  struct mgcp_endpoint *p = sub->parent;
3373  struct mgcp_gateway *g = NULL;
3374  int res;
3375 
3376  ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
3377  /* Clear out potential response */
3378  if (!strcasecmp(req->verb, "RSIP")) {
3379  /* Test if this RSIP request is just a keepalive */
3380  if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
3381  ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name);
3382  transmit_response(sub, "200", req, "OK");
3383  } else {
3384  dump_queue(p->parent, p);
3385  dump_cmd_queues(p, NULL);
3386 
3387  if ((strcmp(p->name, p->parent->wcardep) != 0)) {
3388  ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name);
3389  }
3390  /* For RSIP on wildcard we reset all endpoints */
3391  if (!strcmp(p->name, p->parent->wcardep)) {
3392  /* Reset all endpoints */
3393  struct mgcp_endpoint *tmp_ep;
3394 
3395  g = p->parent;
3396  for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) {
3397  /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/
3398  if (strcmp(tmp_ep->name, g->wcardep) != 0) {
3399  struct mgcp_subchannel *tmp_sub, *first_sub;
3400  ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
3401 
3402  first_sub = tmp_ep->sub;
3403  tmp_sub = tmp_ep->sub;
3404  while (tmp_sub) {
3405  mgcp_queue_hangup(tmp_sub);
3406  tmp_sub = tmp_sub->next;
3407  if (tmp_sub == first_sub)
3408  break;
3409  }
3410  }
3411  }
3412  } else if (sub->owner) {
3414  }
3415  transmit_response(sub, "200", req, "OK");
3416  /* We don't send NTFY or AUEP to wildcard ep */
3417  if (strcmp(p->name, p->parent->wcardep) != 0) {
3419  /* Audit endpoint.
3420  Idea is to prevent lost lines due to race conditions
3421  */
3423  }
3424  }
3425  } else if (!strcasecmp(req->verb, "NTFY")) {
3426  /* Acknowledge and be sure we keep looking for the same things */
3427  transmit_response(sub, "200", req, "OK");
3428  /* Notified of an event */
3429  ev = get_header(req, "O");
3430  s = strchr(ev, '/');
3431  if (s) ev = s + 1;
3432  ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
3433  /* Keep looking for events unless this was a hangup */
3434  if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
3436  }
3437  if (!strcasecmp(ev, "hd")) {
3438  p->hookstate = MGCP_OFFHOOK;
3439  sub->cxmode = MGCP_CX_SENDRECV;
3440 
3441  if (p) {
3442  /* When the endpoint have a Off hook transition we always
3443  starts without any previous dtmfs */
3444  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3445  }
3446 
3447  handle_hd_hf(sub, ev);
3448  } else if (!strcasecmp(ev, "hf")) {
3449  /* We can assume we are offhook if we received a hookflash */
3450  /* First let's just do call wait and ignore threeway */
3451  /* We're currently in charge */
3452  if (p->hookstate != MGCP_OFFHOOK) {
3453  /* Cisco c7940 sends hf even if the phone is onhook */
3454  /* Thanks to point on IRC for pointing this out */
3455  return -1;
3456  }
3457  /* do not let * conference two down channels */
3458  if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_DOWN && !sub->next->owner)
3459  return -1;
3460 
3461  if (p->callwaiting || p->transfer || p->threewaycalling) {
3462  ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
3463  p->sub = p->sub->next;
3464 
3465  /* transfer control to our next subchannel */
3466  if (!sub->next->owner) {
3467  /* plave the first call on hold and start up a new call */
3468  sub->cxmode = MGCP_CX_MUTE;
3469  ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3471  if (sub->owner) {
3472  ast_queue_hold(sub->owner, NULL);
3473  }
3474  sub->next->cxmode = MGCP_CX_RECVONLY;
3475  handle_hd_hf(sub->next, ev);
3476  } else if (sub->owner && sub->next->owner) {
3477  /* We've got two active calls lets decide whether or not to conference or just flip flop */
3478  if ((!sub->outgoing) && (!sub->next->outgoing)) {
3479  /* We made both calls lets conference */
3480  ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n",
3481  sub->id, sub->next->id, p->name, p->parent->name);
3482  sub->cxmode = MGCP_CX_CONF;
3483  sub->next->cxmode = MGCP_CX_CONF;
3484  ast_queue_unhold(sub->next->owner);
3487  } else {
3488  /* Let's flipflop between calls */
3489  /* XXX Need to check for state up ??? */
3490  /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
3491  ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
3492  sub->id, sub->next->id, p->name, p->parent->name);
3493  sub->cxmode = MGCP_CX_MUTE;
3494  ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3496 
3497  ast_queue_hold(sub->owner, NULL);
3498  ast_queue_hold(sub->next->owner, NULL);
3499 
3500  handle_hd_hf(sub->next, ev);
3501  }
3502  } else {
3503  /* We've most likely lost one of our calls find an active call and bring it up */
3504  if (sub->owner) {
3505  p->sub = sub;
3506  } else if (sub->next->owner) {
3507  p->sub = sub->next;
3508  } else {
3509  /* We seem to have lost both our calls */
3510  /* XXX - What do we do now? */
3511  return -1;
3512  }
3513  ast_queue_unhold(p->sub->owner);
3514  p->sub->cxmode = MGCP_CX_SENDRECV;
3516  }
3517  } else {
3518  ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
3519  p->name, p->parent->name);
3520  }
3521  } else if (!strcasecmp(ev, "hu")) {
3522  p->hookstate = MGCP_ONHOOK;
3523  sub->cxmode = MGCP_CX_RECVONLY;
3524  ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
3525  /* Do we need to send MDCX before a DLCX ?
3526  if (sub->rtp) {
3527  transmit_modify_request(sub);
3528  }
3529  */
3530  if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
3531  /* We're allowed to transfer, we have two active calls and */
3532  /* we made at least one of the calls. Let's try and transfer */
3533  ast_mutex_lock(&p->sub->next->lock);
3534  res = attempt_transfer(p, sub);
3535  if (res) {
3536  ast_log(LOG_WARNING, "Transfer attempt failed\n");
3537  ast_mutex_unlock(&p->sub->next->lock);
3538  return -1;
3539  }
3540  ast_mutex_unlock(&p->sub->next->lock);
3541  } else {
3542  /* Hangup the current call */
3543  /* If there is another active call, mgcp_hangup will ring the phone with the other call */
3544  if (sub->owner) {
3545  sub->alreadygone = 1;
3547  } else {
3548  ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
3549  p->name, p->parent->name, sub->id);
3550  /* Instruct the other side to remove the connection since it apparently *
3551  * still thinks the channel is active. *
3552  * For Cisco IAD2421 /BAK/ */
3554  }
3555  }
3556  if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
3557  p->hidecallerid = 0;
3558  if (p->hascallwaiting && !p->callwaiting) {
3559  ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
3560  p->callwaiting = -1;
3561  }
3562  if (has_voicemail(p)) {
3563  ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
3564  transmit_notify_request(sub, "L/vmwi(+)");
3565  } else {
3566  ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
3567  transmit_notify_request(sub, "L/vmwi(-)");
3568  }
3569  }
3570  } else if ((strlen(ev) == 1) &&
3571  (((ev[0] >= '0') && (ev[0] <= '9')) ||
3572  ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
3573  (ev[0] == '*') || (ev[0] == '#'))) {
3574  if (sub && sub->owner && (ast_channel_state(sub->owner) >= AST_STATE_UP)) {
3576  f.subclass.integer = ev[0];
3577  f.src = "mgcp";
3578  /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
3579  mgcp_queue_frame(sub, &f);
3580  ast_mutex_lock(&sub->next->lock);
3581  if (sub->next->owner)
3582  mgcp_queue_frame(sub->next, &f);
3583  ast_mutex_unlock(&sub->next->lock);
3584  if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) {
3585  memset(p->curtone, 0, sizeof(p->curtone));
3586  }
3587  } else {
3588  p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
3589  p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
3590  }
3591  } else if (!strcasecmp(ev, "T")) {
3592  /* Digit timeout -- unimportant */
3593  } else if (!strcasecmp(ev, "ping")) {
3594  /* ping -- unimportant */
3595  } else {
3596  ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
3597  }
3598  } else {
3599  ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
3600  transmit_response(sub, "510", req, "Unknown verb");
3601  }
3602  return 0;
3603 }
static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
Definition: chan_mgcp.c:3288
#define MGCP_CX_MUTE
Definition: chan_mgcp.c:138
#define MGCP_CX_CONF
Definition: chan_mgcp.c:136
static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
Definition: chan_mgcp.c:605
static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
Definition: chan_mgcp.c:2140
#define MGCP_CX_RECVONLY
Definition: chan_mgcp.c:134
static int attempt_transfer(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
Complete an attended transfer.
Definition: chan_mgcp.c:3247
static char * get_header(struct mgcp_request *req, char *name)
Definition: chan_mgcp.c:1627
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1185
@ AST_STATE_UP
Definition: channelstate.h:42
#define AST_FRAME_DTMF
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
const char * src
int hidecallerid
Definition: chan_mgcp.c:363
char dtmf_buf[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:344
char curtone[80]
Definition: chan_mgcp.c:347
char * verb
Definition: chan_mgcp.c:256

References 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::owner, mgcp_endpoint::parent, ast_frame::src, mgcp_endpoint::sub, 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().

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

2765 {
2766  char *c;
2767  struct mgcp_request *req;
2768  struct mgcp_gateway *gw = p->parent;
2769 
2770  if (result < 200) {
2771  /* provisional response */
2772  return;
2773  }
2774 
2775  if (p->slowsequence)
2776  req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2777  else if (sub)
2778  req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
2779  else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
2780  req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2781 
2782  if (!req) {
2783  ast_verb(3, "No command found on [%s] for transaction %u. Ignoring...\n",
2784  gw->name, ident);
2785  return;
2786  }
2787 
2788  if (p && (result >= 400) && (result <= 599)) {
2789  switch (result) {
2790  case 401:
2791  p->hookstate = MGCP_OFFHOOK;
2792  break;
2793  case 402:
2794  p->hookstate = MGCP_ONHOOK;
2795  break;
2796  case 406:
2797  ast_log(LOG_NOTICE, "Transaction %u timed out\n", ident);
2798  break;
2799  case 407:
2800  ast_log(LOG_NOTICE, "Transaction %u aborted\n", ident);
2801  break;
2802  }
2803  if (sub) {
2804  if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) {
2805  ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result);
2807  }
2808  if (sub->owner) {
2809  ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2810  result, p->name, p->parent->name, sub ? sub->id:-1);
2812  }
2813  } else {
2814  if (p->sub->next->owner) {
2815  ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2816  result, p->name, p->parent->name, sub ? sub->id:-1);
2817  mgcp_queue_hangup(p->sub);
2818  }
2819 
2820  if (p->sub->owner) {
2821  ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2822  result, p->name, p->parent->name, sub ? sub->id:-1);
2823  mgcp_queue_hangup(p->sub);
2824  }
2825 
2826  dump_cmd_queues(p, NULL);
2827  }
2828  }
2829 
2830  if (resp) {
2831  /* responseAck: */
2832  if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) {
2833  if (sub) {
2834  transmit_response(sub, "000", resp, "OK");
2835  if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_RINGING) {
2837  }
2838  }
2839  }
2840  if (req->cmd == MGCP_CMD_CRCX) {
2841  if ((c = get_header(resp, "I"))) {
2842  if (!ast_strlen_zero(c) && sub) {
2843  /* if we are hanging up do not process this conn. */
2844  if (sub->owner) {
2845  if (!ast_strlen_zero(sub->cxident)) {
2846  if (strcasecmp(c, sub->cxident)) {
2847  ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
2848  }
2849  }
2850  ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
2851  if (sub->tmpdest.sin_addr.s_addr) {
2853  }
2854  } else {
2855  /* XXX delete this one
2856  callid and conn id may already be lost.
2857  so the following del conn may have a side effect of
2858  cleaning up the next subchannel */
2860  }
2861  }
2862  }
2863  }
2864 
2865  if (req->cmd == MGCP_CMD_AUEP) {
2866  /* check stale connection ids */
2867  if ((c = get_header(resp, "I"))) {
2868  char *v, *n;
2869  int len;
2870  while ((v = get_csv(c, &len, &n))) {
2871  if (len) {
2872  if (strncasecmp(v, p->sub->cxident, len) &&
2873  strncasecmp(v, p->sub->next->cxident, len)) {
2874  /* connection id not found. delete it */
2875  char cxident[80] = "";
2876 
2877  if (len > (sizeof(cxident) - 1))
2878  len = sizeof(cxident) - 1;
2879  ast_copy_string(cxident, v, len);
2880  ast_verb(3, "Non existing connection id %s on %s@%s \n",
2881  cxident, p->name, gw->name);
2883  }
2884  }
2885  c = n;
2886  }
2887  }
2888 
2889  /* Try to determine the hookstate returned from an audit endpoint command */
2890  if ((c = get_header(resp, "ES"))) {
2891  if (!ast_strlen_zero(c)) {
2892  if (strstr(c, "hu")) {
2893  if (p->hookstate != MGCP_ONHOOK) {
2894  /* XXX cleanup if we think we are offhook XXX */
2895  if ((p->sub->owner || p->sub->next->owner ) &&
2896  p->hookstate == MGCP_OFFHOOK)
2898  p->hookstate = MGCP_ONHOOK;
2899 
2900  /* update the requested events according to the new hookstate */
2901  transmit_notify_request(p->sub, "");
2902 
2903  ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
2904  }
2905  } else if (strstr(c, "hd")) {
2906  if (p->hookstate != MGCP_OFFHOOK) {
2907  p->hookstate = MGCP_OFFHOOK;
2908 
2909  /* update the requested events according to the new hookstate */
2910  transmit_notify_request(p->sub, "");
2911 
2912  ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
2913  }
2914  }
2915  }
2916  }
2917  }
2918 
2919  if (resp && resp->lines) {
2920  /* do not process sdp if we are hanging up. this may be a late response */
2921  if (sub && sub->owner) {
2922  if (!sub->rtp)
2923  start_rtp(sub);
2924  if (sub->rtp)
2925  process_sdp(sub, resp);
2926  }
2927  }
2928  }
2929 
2930  ast_free(req);
2931 }
static PGresult * result
Definition: cel_pgsql.c:84
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:2267
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:2734
static char * get_csv(char *c, int *len, char **next)
get_csv: (SC:) get comma separated value
Definition: chan_mgcp.c:1634
static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
Definition: chan_mgcp.c:2679
static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
Definition: chan_mgcp.c:1942
char cxident[80]
Definition: chan_mgcp.c:313

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::cxident, dump_cmd_queues(), find_command(), get_csv(), get_header(), mgcp_endpoint::hookstate, 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(), result, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_endpoint::slowsequence, start_rtp(), mgcp_endpoint::sub, sub, 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().

◆ has_voicemail()

static int has_voicemail ( struct mgcp_endpoint p)
static

Definition at line 491 of file chan_mgcp.c.

492 {
493  int new_msgs;
494  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
495 
497  if (msg) {
498  struct ast_mwi_state *mwi_state = stasis_message_data(msg);
499  new_msgs = mwi_state->new_msgs;
500  } else {
502  }
503 
504  return new_msgs;
505 }
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
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"....
Definition: main/app.c:652
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
Definition: mwi.c:94
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
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
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
The structure that contains MWI state.
Definition: mwi.h:455
int new_msgs
Definition: mwi.h:459
#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:936

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

◆ init_req()

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

Definition at line 2094 of file chan_mgcp.c.

2095 {
2096  /* Initialize a response */
2097  if (req->headers || req->len) {
2098  ast_log(LOG_WARNING, "Request already initialized?!?\n");
2099  return -1;
2100  }
2101  req->header[req->headers] = req->data + req->len;
2102  /* check if we need brackets around the gw name */
2103  if (p->parent->isnamedottedip) {
2104  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" : "");
2105  } else {
2106 + 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" : "");
2107  }
2108  req->len += strlen(req->header[req->headers]);
2109  if (req->headers < MGCP_MAX_HEADERS) {
2110  req->headers++;
2111  } else {
2112  ast_log(LOG_WARNING, "Out of header space\n");
2113  }
2114  return 0;
2115 }

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

◆ init_resp()

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

Definition at line 2076 of file chan_mgcp.c.

2077 {
2078  /* Initialize a response */
2079  if (req->headers || req->len) {
2080  ast_log(LOG_WARNING, "Request already initialized?!?\n");
2081  return -1;
2082  }
2083  req->header[req->headers] = req->data + req->len;
2084  snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
2085  req->len += strlen(req->header[req->headers]);
2086  if (req->headers < MGCP_MAX_HEADERS) {
2087  req->headers++;
2088  } else {
2089  ast_log(LOG_WARNING, "Out of header space\n");
2090  }
2091  return 0;
2092 }

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

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

4841 {
4843  return AST_MODULE_LOAD_DECLINE;
4844  }
4847  return AST_MODULE_LOAD_DECLINE;
4848  }
4852  if (!(sched = ast_sched_context_create())) {
4853  ast_log(LOG_WARNING, "Unable to create schedule context\n");
4856  return AST_MODULE_LOAD_DECLINE;
4857  }
4858 
4859  if (!(io = io_context_create())) {
4860  ast_log(LOG_WARNING, "Unable to create I/O context\n");
4864  return AST_MODULE_LOAD_DECLINE;
4865  }
4866 
4867  if (reload_config(0)) {
4870  return AST_MODULE_LOAD_DECLINE;
4871  }
4872 
4873  /* Make sure we can register our mgcp channel type */
4875  ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
4880  return AST_MODULE_LOAD_DECLINE;
4881  }
4882 
4884  ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
4885 
4886  /* And start the monitor for the first time */
4887  restart_monitor();
4888 
4889  return AST_MODULE_LOAD_SUCCESS;
4890 }
static struct ast_cli_entry cli_mgcp[]
Definition: chan_mgcp.c:1122
static int restart_monitor(void)
Definition: chan_mgcp.c:3902
static struct ast_rtp_glue mgcp_rtp_glue
Definition: chan_mgcp.c:4477
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_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
void io_context_destroy(struct io_context *ioc)
Destroys a context.
Definition: io.c:107
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
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_rtp_glue_register(glue)
Definition: rtp_engine.h:847
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
struct ast_format_cap * capabilities
Definition: channel.h:632
descriptor for a cli entry.
Definition: cli.h:171

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, cli_mgcp, global_capability, io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, mgcp_rtp_glue, mgcp_tech, reload_config(), and restart_monitor().

◆ mgcp_alloc_pktcgate()

static int mgcp_alloc_pktcgate ( struct mgcp_subchannel sub)
static

Definition at line 2414 of file chan_mgcp.c.

2415 {
2416  struct mgcp_endpoint *p = sub->parent;
2417  sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr),
2418  8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove);
2419 
2420  if (!sub->gate) {
2421  return 0;
2422  }
2423  sub->gate->tech_pvt = sub;
2424  sub->gate->gate_open = &mgcp_pktcgate_open;
2425  return 1;
2426 }
static int mgcp_pktcgate_remove(struct cops_gate *gate)
Definition: chan_mgcp.c:2378
static int mgcp_pktcgate_open(struct cops_gate *gate)
Definition: chan_mgcp.c:2401
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:469
@ GATE_SET
Definition: pktccops.h:36

References mgcp_gateway::addr, ast_pktccops_gate_alloc(), GATE_SET, mgcp_pktcgate_open(), mgcp_pktcgate_remove(), NULL, mgcp_endpoint::parent, and sub.

Referenced by start_rtp().

◆ mgcp_answer()

static int mgcp_answer ( struct ast_channel ast)
static

Definition at line 1128 of file chan_mgcp.c.

1129 {
1130  int res = 0;
1131  struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
1132  struct mgcp_endpoint *p = sub->parent;
1133 
1134  ast_mutex_lock(&sub->lock);
1135  sub->cxmode = MGCP_CX_SENDRECV;
1136  if (!sub->rtp) {
1137  start_rtp(sub);
1138  } else {
1140  }
1141  ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n",
1142  ast_channel_name(ast), p->name, p->parent->name, sub->id);
1143  if (ast_channel_state(ast) != AST_STATE_UP) {
1144  ast_setstate(ast, AST_STATE_UP);
1145  ast_debug(1, "mgcp_answer(%s)\n", ast_channel_name(ast));
1148  }
1149  ast_mutex_unlock(&sub->lock);
1150  return res;
1151 }
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:7469

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

◆ mgcp_call()

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

Definition at line 827 of file chan_mgcp.c.

828 {
829  int res;
830  struct mgcp_endpoint *p;
831  struct mgcp_subchannel *sub;
832  char tone[50] = "";
833  const char *distinctive_ring = pbx_builtin_getvar_helper(ast, "ALERT_INFO");
834 
835  ast_debug(3, "MGCP mgcp_call(%s)\n", ast_channel_name(ast));
836  sub = ast_channel_tech_pvt(ast);
837  p = sub->parent;
838 
839  ast_mutex_lock(&sub->lock);
840  switch (p->hookstate) {
841  case MGCP_OFFHOOK:
842  if (!ast_strlen_zero(distinctive_ring)) {
843  snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
844  ast_debug(3, "MGCP distinctive callwait %s\n", tone);
845  } else {
846  ast_copy_string(tone, (p->ncs ? "L/wt1" : "L/wt"), sizeof(tone));
847  ast_debug(3, "MGCP normal callwait %s\n", tone);
848  }
849  break;
850  case MGCP_ONHOOK:
851  default:
852  if (!ast_strlen_zero(distinctive_ring)) {
853  snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
854  ast_debug(3, "MGCP distinctive ring %s\n", tone);
855  } else {
856  ast_copy_string(tone, "L/rg", sizeof(tone));
857  ast_debug(3, "MGCP default ring\n");
858  }
859  break;
860  }
861 
863  ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
864  ast_mutex_unlock(&sub->lock);
865  return -1;
866  }
867 
868  res = 0;
869  sub->outgoing = 1;
870  sub->cxmode = MGCP_CX_RECVONLY;
872  if (p->type == TYPE_LINE) {
873  if (!sub->rtp) {
874  start_rtp(sub);
875  } else {
877  }
878 
879  if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
880  /* try to prevent a callwait from disturbing the other connection */
881  sub->next->cxmode = MGCP_CX_RECVONLY;
883  }
884 
886  S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, ""),
887  S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, ""));
889 
890  if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
891  /* Put the connection back in sendrecv */
892  sub->next->cxmode = MGCP_CX_SENDRECV;
894  }
895  } else {
896  ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
897  res = -1;
898  }
899  ast_mutex_unlock(&sub->lock);
900  return res;
901 }
static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
Definition: chan_mgcp.c:2493
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
@ AST_STATE_RESERVED
Definition: channelstate.h:37
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 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:87
Number structure.
Definition: app_followme.c:154

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_endpoint::hookstate, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, name, mgcp_endpoint::ncs, pbx_builtin_getvar_helper(), S_COR, start_rtp(), sub, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, and TYPE_LINE.

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

1333 {
1334  struct mgcp_gateway *g;
1335  struct mgcp_endpoint *e = NULL;
1336  char *tmp, *endpt, *gw;
1337  int ret = AST_DEVICE_INVALID;
1338 
1339  endpt = ast_strdupa(data);
1340  if ((tmp = strchr(endpt, '@'))) {
1341  *tmp++ = '\0';
1342  gw = tmp;
1343  } else
1344  goto error;
1345 
1347  for (g = gateways; g; g = g->next) {
1348  if (strcasecmp(g->name, gw) == 0) {
1349  e = g->endpoints;
1350  break;
1351  }
1352  }
1353 
1354  if (!e)
1355  goto error;
1356 
1357  for (; e; e = e->next) {
1358  if (strcasecmp(e->name, endpt) == 0) {
1359  break;
1360  }
1361  }
1362 
1363  if (!e)
1364  goto error;
1365 
1366  /*
1367  * As long as the gateway/endpoint is valid, we'll
1368  * assume that the device is available and its state
1369  * can be tracked.
1370  */
1371  ret = AST_DEVICE_UNKNOWN;
1372 
1373 error:
1375  return ret;
1376 }
@ AST_DEVICE_UNKNOWN
Definition: devicestate.h:53
@ AST_DEVICE_INVALID
Definition: devicestate.h:57
int error(const char *format,...)
Definition: utils/frame.c:999

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

◆ mgcp_fixup()

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

Definition at line 1254 of file chan_mgcp.c.

1255 {
1256  struct mgcp_subchannel *sub = ast_channel_tech_pvt(newchan);
1257 
1258  ast_mutex_lock(&sub->lock);
1259  ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", ast_channel_name(oldchan), ast_channel_name(newchan));
1260  if (sub->owner != oldchan) {
1261  ast_mutex_unlock(&sub->lock);
1262  ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
1263  return -1;
1264  }
1265  mgcp_set_owner(sub, newchan);
1266  ast_mutex_unlock(&sub->lock);
1267  return 0;
1268 }
static void mgcp_set_owner(struct mgcp_subchannel *sub, struct ast_channel *chan)
Definition: chan_mgcp.c:1194

References ast_channel_name(), ast_channel_tech_pvt(), ast_log, ast_mutex_lock, ast_mutex_unlock, LOG_NOTICE, LOG_WARNING, mgcp_set_owner(), and sub.

◆ mgcp_get_codec()

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

Definition at line 4469 of file chan_mgcp.c.

4470 {
4471  struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
4472  struct mgcp_endpoint *p = sub->parent;
4473 
4475 }

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

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

4442 {
4443  struct mgcp_subchannel *sub = NULL;
4444 
4445  if (!(sub = ast_channel_tech_pvt(chan)) || !(sub->rtp))
4447 
4448  ao2_ref(sub->rtp, +1);
4449  *instance = sub->rtp;
4450 
4451  if (sub->parent->directmedia)
4453  else
4455 }
@ AST_RTP_GLUE_RESULT_LOCAL
Definition: rtp_engine.h:164
@ AST_RTP_GLUE_RESULT_REMOTE
Definition: rtp_engine.h:162
@ AST_RTP_GLUE_RESULT_FORBID
Definition: rtp_engine.h:160

◆ mgcp_hangup()

static int mgcp_hangup ( struct ast_channel ast)
static

Definition at line 903 of file chan_mgcp.c.

904 {
906  struct mgcp_endpoint *p = sub->parent;
907 
908  ast_debug(1, "mgcp_hangup(%s)\n", ast_channel_name(ast));
909  if (!ast_channel_tech_pvt(ast)) {
910  ast_debug(1, "Asked to hangup channel not connected\n");
911  return 0;
912  }
913  if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
914  ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n");
915  return 0;
916  }
917  ast_mutex_lock(&sub->lock);
918  ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast_channel_name(ast), p->name, p->parent->name);
919 
920  if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
921  /* check whether other channel is active. */
922  if (!sub->next->owner) {
923  if (p->dtmfmode & MGCP_DTMF_HYBRID) {
924  p->dtmfmode &= ~MGCP_DTMF_INBAND;
925  }
926  ast_debug(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
927  ast_dsp_free(p->dsp);
928  p->dsp = NULL;
929  }
930  }
931 
933 
934  /* for deleting gate */
935  if (p->pktcgatealloc && sub->gate) {
936  sub->gate->gate_open = NULL;
937  sub->gate->gate_remove = NULL;
938  sub->gate->got_dq_gi = NULL;
939  sub->gate->tech_pvt = NULL;
940  if (sub->gate->state == GATE_ALLOC_PROGRESS || sub->gate->state == GATE_ALLOCATED) {
941  ast_pktccops_gate_alloc(GATE_DEL, sub->gate, 0, 0, 0, 0, 0, 0, NULL, NULL);
942  } else {
943  sub->gate->deltimer = time(NULL) + 5;
944  }
945  sub->gate = NULL;
946  }
947 
948  if (!ast_strlen_zero(sub->cxident)) {
950  }
951  sub->cxident[0] = '\0';
952  if ((sub == p->sub) && sub->next->owner) {
953  RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(sub->next->owner), ast_channel_cleanup);
954 
955  if (p->hookstate == MGCP_OFFHOOK) {
956  if (sub->next->owner && bridged) {
957  /* ncs fix! */
958  transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"),
959  S_COR(ast_channel_caller(bridged)->id.number.valid, ast_channel_caller(bridged)->id.number.str, ""),
960  S_COR(ast_channel_caller(bridged)->id.name.valid, ast_channel_caller(bridged)->id.name.str, ""));
961  }
962  } else {
963  /* set our other connection as the primary and swith over to it */
964  p->sub = sub->next;
967  if (sub->next->owner && bridged) {
969  S_COR(ast_channel_caller(bridged)->id.number.valid, ast_channel_caller(bridged)->id.number.str, ""),
970  S_COR(ast_channel_caller(bridged)->id.name.valid, ast_channel_caller(bridged)->id.name.str, ""));
971  }
972  }
973 
974  } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
975  transmit_notify_request(sub, p->ncs ? "" : "L/v");
976  } else if (p->hookstate == MGCP_OFFHOOK) {
977  transmit_notify_request(sub, "L/ro");
978  } else {
980  }
981 
983  sub->alreadygone = 0;
984  sub->outgoing = 0;
985  sub->cxmode = MGCP_CX_INACTIVE;
986  sub->callid[0] = '\0';
987  if (p) {
988  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
989  }
990  /* Reset temporary destination */
991  memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
992  if (sub->rtp) {
994  sub->rtp = NULL;
995  }
996 
998 
999  if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
1000  p->hidecallerid = 0;
1001  if (p->hascallwaiting && !p->callwaiting) {
1002  ast_verb(3, "Enabling call waiting on %s\n", ast_channel_name(ast));
1003  p->callwaiting = -1;
1004  }
1005  if (has_voicemail(p)) {
1006  ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
1007  ast_channel_name(ast), p->name, p->parent->name);
1008  transmit_notify_request(sub, "L/vmwi(+)");
1009  } else {
1010  ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
1011  ast_channel_name(ast), p->name, p->parent->name);
1012  transmit_notify_request(sub, "L/vmwi(-)");
1013  }
1014  }
1015  ast_mutex_unlock(&sub->lock);
1016  return 0;
1017 }
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10750
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
@ GATE_ALLOCATED
Definition: pktccops.h:45
@ GATE_ALLOC_PROGRESS
Definition: pktccops.h:44
@ GATE_DEL
Definition: pktccops.h:39
struct ast_module * self
Definition: module.h:342

References 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_endpoint::callwaiting, mgcp_subchannel::cxmode, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, GATE_ALLOC_PROGRESS, GATE_ALLOCATED, GATE_DEL, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, MGCP_CX_INACTIVE, MGCP_CX_RECVONLY, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_set_owner(), MGCP_SUBCHANNEL_MAGIC, mgcp_endpoint::name, mgcp_gateway::name, name, mgcp_endpoint::ncs, mgcp_subchannel::next, NULL, mgcp_endpoint::parent, mgcp_endpoint::pktcgatealloc, RAII_VAR, S_COR, ast_module_info::self, mgcp_endpoint::sub, sub, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

◆ mgcp_indicate()

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

Definition at line 1410 of file chan_mgcp.c.

1411 {
1412  struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
1413  int res = 0;
1414 
1415  ast_debug(3, "MGCP asked to indicate %d '%s' condition on channel %s\n",
1416  ind, control2str(ind), ast_channel_name(ast));
1417  ast_mutex_lock(&sub->lock);
1418  switch(ind) {
1419  case AST_CONTROL_RINGING:
1420 #ifdef DLINK_BUGGY_FIRMWARE
1422 #else
1423  if (!sub->sdpsent) { /* will hide the inband progress!!! */
1424  transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt");
1425  }
1426 #endif
1427  break;
1428  case AST_CONTROL_BUSY:
1429  transmit_notify_request(sub, "L/bz");
1430  break;
1432  /* We do not currently support resetting of the Interdigit Timer, so treat
1433  * Incomplete control frames as a congestion response
1434  */
1436  transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg");
1437  break;
1438  case AST_CONTROL_HOLD:
1439  ast_moh_start(ast, data, NULL);
1440  break;
1441  case AST_CONTROL_UNHOLD:
1442  ast_moh_stop(ast);
1443  break;
1444  case AST_CONTROL_SRCUPDATE:
1446  break;
1447  case AST_CONTROL_SRCCHANGE:
1449  break;
1450  case AST_CONTROL_PROGRESS:
1453  case -1:
1455  break;
1456  default:
1457  ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
1458  /* fallthrough */
1460  res = -1;
1461  }
1462  ast_mutex_unlock(&sub->lock);
1463  return res;
1464 }
static char * control2str(int ind)
Definition: chan_mgcp.c:1378
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_HOLD
@ AST_CONTROL_SRCCHANGE
@ AST_CONTROL_INCOMPLETE
@ AST_CONTROL_PVT_CAUSE_CODE
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:7849
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7859
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:2152
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:2143

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(), LOG_WARNING, NULL, sub, transmit_modify_request(), and transmit_notify_request().

◆ mgcp_new()

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