Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
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"

Go to the source code of this file.

Data Structures

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

Macros

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

Enumerations

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

Functions

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

Variables

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

Detailed Description

Implementation of Media Gateway Control Protocol.

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

Definition in file chan_mgcp.c.

Macro Definition Documentation

◆ DEFAULT_EXPIRY

#define DEFAULT_EXPIRY   120

Definition at line 96 of file chan_mgcp.c.

◆ DEFAULT_MGCP_CA_PORT

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 124 of file chan_mgcp.c.

Referenced by reload_config().

◆ DEFAULT_MGCP_GW_PORT

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 123 of file chan_mgcp.c.

Referenced by build_gateway().

◆ DEFAULT_RETRANS

#define DEFAULT_RETRANS   1000

How frequently to retransmit

Definition at line 126 of file chan_mgcp.c.

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

◆ DIRECTMEDIA

#define DIRECTMEDIA   1

Definition at line 98 of file chan_mgcp.c.

Referenced by build_gateway().

◆ INADDR_NONE

#define INADDR_NONE   (in_addr_t)(-1)

Definition at line 101 of file chan_mgcp.c.

Referenced by build_gateway().

◆ MAX_EXPIRY

#define MAX_EXPIRY   3600

Definition at line 97 of file chan_mgcp.c.

◆ MAX_RETRANS

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 127 of file chan_mgcp.c.

Referenced by retrans_pkt().

◆ MAX_SUBS

#define MAX_SUBS   2

Definition at line 291 of file chan_mgcp.c.

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

◆ MGCP_CX_CONF

#define MGCP_CX_CONF   3

Definition at line 133 of file chan_mgcp.c.

Referenced by handle_request().

◆ MGCP_CX_CONFERENCE

#define MGCP_CX_CONFERENCE   3

Definition at line 134 of file chan_mgcp.c.

◆ MGCP_CX_INACTIVE

#define MGCP_CX_INACTIVE   4

Definition at line 136 of file chan_mgcp.c.

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

◆ MGCP_CX_MUTE

#define MGCP_CX_MUTE   4

Definition at line 135 of file chan_mgcp.c.

Referenced by handle_request().

◆ MGCP_CX_RECVONLY

#define MGCP_CX_RECVONLY   1

Definition at line 131 of file chan_mgcp.c.

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

◆ MGCP_CX_SENDONLY

#define MGCP_CX_SENDONLY   0

MGCP rtp stream modes {

Definition at line 130 of file chan_mgcp.c.

◆ MGCP_CX_SENDRECV

#define MGCP_CX_SENDRECV   2

Definition at line 132 of file chan_mgcp.c.

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

◆ MGCP_DTMF_HYBRID

#define MGCP_DTMF_HYBRID   (1 << 2)

◆ MGCP_DTMF_INBAND

#define MGCP_DTMF_INBAND   (1 << 1)

◆ MGCP_DTMF_RFC2833

#define MGCP_DTMF_RFC2833   (1 << 0)

◆ MGCP_MAX_HEADERS

#define MGCP_MAX_HEADERS   64

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

Definition at line 250 of file chan_mgcp.c.

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

◆ MGCP_MAX_LINES

#define MGCP_MAX_LINES   64

Definition at line 251 of file chan_mgcp.c.

Referenced by add_line(), and parse().

◆ MGCP_MAX_PACKET

#define MGCP_MAX_PACKET   1500

Also from RFC 2543, should sub headers tho

Definition at line 125 of file chan_mgcp.c.

◆ MGCP_OFFHOOK

#define MGCP_OFFHOOK   2

◆ MGCP_ONHOOK

#define MGCP_ONHOOK   1

◆ MGCP_SUBCHANNEL_MAGIC

#define MGCP_SUBCHANNEL_MAGIC   "!978!"

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

Definition at line 302 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_hangup().

◆ MGCPDUMPER

#define MGCPDUMPER

Definition at line 95 of file chan_mgcp.c.

◆ RESPONSE_TIMEOUT

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 281 of file chan_mgcp.c.

Referenced by find_and_retrans().

◆ SUB_ALT

#define SUB_ALT   1

Definition at line 294 of file chan_mgcp.c.

◆ SUB_REAL

#define SUB_REAL   0

Definition at line 293 of file chan_mgcp.c.

◆ TYPE_LINE

#define TYPE_LINE   2

Definition at line 330 of file chan_mgcp.c.

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

◆ TYPE_TRUNK

#define TYPE_TRUNK   1

Definition at line 329 of file chan_mgcp.c.

Referenced by build_gateway().

Enumeration Type Documentation

◆ anonymous enum

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

Definition at line 147 of file chan_mgcp.c.

Function Documentation

◆ __get_header()

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

Definition at line 1635 of file chan_mgcp.c.

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

Referenced by get_header().

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

◆ __mgcp_xmit()

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

Definition at line 534 of file chan_mgcp.c.

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

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

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

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 5025 of file chan_mgcp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 5025 of file chan_mgcp.c.

◆ acf_channel_read()

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

Definition at line 4519 of file chan_mgcp.c.

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

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

◆ add_header()

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

Definition at line 2065 of file chan_mgcp.c.

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

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

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

◆ add_header_offhook()

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

Definition at line 2648 of file chan_mgcp.c.

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

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

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

◆ add_line()

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

Definition at line 2087 of file chan_mgcp.c.

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

Referenced by add_sdp().

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

◆ add_sdp()

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

Definition at line 2201 of file chan_mgcp.c.

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

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

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

◆ add_var()

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

Definition at line 4651 of file chan_mgcp.c.

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

Referenced by build_gateway().

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

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 5025 of file chan_mgcp.c.

◆ attempt_transfer()

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

Complete an attended transfer.

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

Definition at line 3281 of file chan_mgcp.c.

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

Referenced by handle_request().

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

◆ build_gateway()

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

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

Definition at line 4016 of file chan_mgcp.c.

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

Referenced by find_realtime_gw(), and reload_config().

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

◆ control2str()

static char* control2str ( int  ind)
static

Definition at line 1406 of file chan_mgcp.c.

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

Referenced by mgcp_indicate().

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

◆ copy_vars()

static struct ast_variable * copy_vars ( struct ast_variable src)
static

duplicate a list of channel variables,

Returns
the copy.

Definition at line 4669 of file chan_mgcp.c.

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

Referenced by build_gateway().

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

◆ destroy_endpoint()

static void destroy_endpoint ( struct mgcp_endpoint e)
static

Definition at line 4539 of file chan_mgcp.c.

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

Referenced by prune_gateways().

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

◆ destroy_gateway()

static void destroy_gateway ( struct mgcp_gateway g)
static

Definition at line 4598 of file chan_mgcp.c.

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

Referenced by prune_gateways().

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

◆ do_monitor()

static void* do_monitor ( void *  data)
static

Definition at line 3818 of file chan_mgcp.c.

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

Referenced by restart_monitor().

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

◆ dump_cmd_queues()

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

dump_cmd_queues: (SC:) cleanup pending commands

Definition at line 2734 of file chan_mgcp.c.

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

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

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

◆ dump_queue()

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

Definition at line 570 of file chan_mgcp.c.

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

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

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

◆ find_and_retrans()

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

Definition at line 3639 of file chan_mgcp.c.

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

Referenced by mgcpsock_read().

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

◆ find_command()

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

find_command: (SC:) remove command transaction from queue

Definition at line 2768 of file chan_mgcp.c.

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

Referenced by handle_response().

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

◆ find_realtime_gw()

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

Definition at line 1686 of file chan_mgcp.c.

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

Referenced by find_subchannel_and_lock().

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

◆ find_subchannel_and_lock()

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

Definition at line 1777 of file chan_mgcp.c.

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

Referenced by mgcp_request(), and mgcpsock_read().

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

◆ get_csv()

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

get_csv: (SC:) get comma separated value

Definition at line 1662 of file chan_mgcp.c.

References c, and NULL.

Referenced by handle_response().

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

◆ get_header()

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

Definition at line 1655 of file chan_mgcp.c.

References __get_header().

Referenced by handle_request(), and handle_response().

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

◆ get_sdp()

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

Definition at line 1606 of file chan_mgcp.c.

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

Referenced by process_sdp().

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

◆ get_sdp_by_line()

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

Definition at line 1596 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

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

◆ get_sdp_iterate()

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

Definition at line 1624 of file chan_mgcp.c.

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

Referenced by process_sdp().

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

◆ handle_hd_hf()

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

Definition at line 3322 of file chan_mgcp.c.

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

Referenced by handle_request().

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

◆ handle_mgcp_audit_endpoint()

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

Definition at line 1060 of file chan_mgcp.c.

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

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

◆ handle_mgcp_set_debug()

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

Definition at line 1121 of file chan_mgcp.c.

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

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

◆ handle_mgcp_show_endpoints()

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

Definition at line 1018 of file chan_mgcp.c.

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

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

◆ handle_request()

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

Definition at line 3402 of file chan_mgcp.c.

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

Referenced by mgcpsock_read().

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

◆ handle_response()

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

Definition at line 2797 of file chan_mgcp.c.

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

Referenced by mgcpsock_read(), and retrans_pkt().

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

◆ has_voicemail()

static int has_voicemail ( struct mgcp_endpoint p)
static

Definition at line 490 of file chan_mgcp.c.

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

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

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

◆ init_req()

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

Definition at line 2128 of file chan_mgcp.c.

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

Referenced by reqprep().

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

◆ init_resp()

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

Definition at line 2110 of file chan_mgcp.c.

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

Referenced by respprep().

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

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 4856 of file chan_mgcp.c.

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

Referenced by unload_module().

4857 {
4859  return AST_MODULE_LOAD_DECLINE;
4860  }
4863  return AST_MODULE_LOAD_DECLINE;
4864  }
4868  if (!(sched = ast_sched_context_create())) {
4869  ast_log(LOG_WARNING, "Unable to create schedule context\n");
4872  return AST_MODULE_LOAD_DECLINE;
4873  }
4874 
4875  if (!(io = io_context_create())) {
4876  ast_log(LOG_WARNING, "Unable to create I/O context\n");
4880  return AST_MODULE_LOAD_DECLINE;
4881  }
4882 
4883  if (reload_config(0)) {
4886  return AST_MODULE_LOAD_DECLINE;
4887  }
4888 
4889  /* Make sure we can register our mgcp channel type */
4891  ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
4896  return AST_MODULE_LOAD_DECLINE;
4897  }