Wed Jan 8 2020 09:49:44

Asterisk developer's documentation


chan_mgcp.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Implementation of Media Gateway Control Protocol
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \par See also
26  * \arg \ref Config_mgcp
27  * \arg \ref res_pktccops
28  *
29  * \ingroup channel_drivers
30  */
31 
32 /*** MODULEINFO
33  <use>res_pktccops</use>
34  <support_level>extended</support_level>
35  ***/
36 
37 #include "asterisk.h"
38 
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
40 
41 #include <sys/socket.h>
42 #include <sys/ioctl.h>
43 #include <net/if.h>
44 #include <fcntl.h>
45 #include <netdb.h>
46 #include <sys/signal.h>
47 #include <signal.h>
48 #include <netinet/in.h>
49 #include <netinet/in_systm.h>
50 #include <netinet/ip.h>
51 #include <arpa/inet.h>
52 #include <ctype.h>
53 
54 #include "asterisk/lock.h"
55 #include "asterisk/channel.h"
56 #include "asterisk/config.h"
57 #include "asterisk/module.h"
58 #include "asterisk/pbx.h"
59 #include "asterisk/sched.h"
60 #include "asterisk/io.h"
61 #include "asterisk/rtp_engine.h"
62 #include "asterisk/acl.h"
63 #include "asterisk/callerid.h"
64 #include "asterisk/cli.h"
65 #include "asterisk/say.h"
66 #include "asterisk/cdr.h"
67 #include "asterisk/astdb.h"
68 #include "asterisk/features.h"
69 #include "asterisk/app.h"
70 #include "asterisk/musiconhold.h"
71 #include "asterisk/utils.h"
72 #include "asterisk/netsock.h"
73 #include "asterisk/causes.h"
74 #include "asterisk/dsp.h"
75 #include "asterisk/devicestate.h"
76 #include "asterisk/stringfields.h"
77 #include "asterisk/abstract_jb.h"
78 #include "asterisk/event.h"
79 #include "asterisk/chanvars.h"
80 #include "asterisk/pktccops.h"
81 
82 /*
83  * Define to work around buggy dlink MGCP phone firmware which
84  * appears not to know that "rt" is part of the "G" package.
85  */
86 /* #define DLINK_BUGGY_FIRMWARE */
87 
88 #define MGCPDUMPER
89 #define DEFAULT_EXPIRY 120
90 #define MAX_EXPIRY 3600
91 #define DIRECTMEDIA 1
92 
93 #ifndef INADDR_NONE
94 #define INADDR_NONE (in_addr_t)(-1)
95 #endif
96 
97 /*! Global jitterbuffer configuration - by default, jb is disabled
98  * \note Values shown here match the defaults shown in mgcp.conf.sample */
99 static struct ast_jb_conf default_jbconf =
100 {
101  .flags = 0,
102  .max_size = 200,
103  .resync_threshold = 1000,
104  .impl = "fixed",
105  .target_extra = 40,
106 };
108 
109 static const char tdesc[] = "Media Gateway Control Protocol (MGCP)";
110 static const char config[] = "mgcp.conf";
111 
112 #define MGCP_DTMF_RFC2833 (1 << 0)
113 #define MGCP_DTMF_INBAND (1 << 1)
114 #define MGCP_DTMF_HYBRID (1 << 2)
115 
116 #define DEFAULT_MGCP_GW_PORT 2427 /*!< From RFC 2705 */
117 #define DEFAULT_MGCP_CA_PORT 2727 /*!< From RFC 2705 */
118 #define MGCP_MAX_PACKET 1500 /*!< Also from RFC 2543, should sub headers tho */
119 #define DEFAULT_RETRANS 1000 /*!< How frequently to retransmit */
120 #define MAX_RETRANS 5 /*!< Try only 5 times for retransmissions */
121 
122 /*! MGCP rtp stream modes { */
123 #define MGCP_CX_SENDONLY 0
124 #define MGCP_CX_RECVONLY 1
125 #define MGCP_CX_SENDRECV 2
126 #define MGCP_CX_CONF 3
127 #define MGCP_CX_CONFERENCE 3
128 #define MGCP_CX_MUTE 4
129 #define MGCP_CX_INACTIVE 4
130 /*! } */
131 
132 static const char * const mgcp_cxmodes[] = {
133  "sendonly",
134  "recvonly",
135  "sendrecv",
136  "confrnce",
137  "inactive"
138 };
139 
140 enum {
150 };
151 
152 static char context[AST_MAX_EXTENSION] = "default";
153 
154 static char language[MAX_LANGUAGE] = "";
155 static char musicclass[MAX_MUSICCLASS] = "";
157 static char cid_num[AST_MAX_EXTENSION] = "";
158 static char cid_name[AST_MAX_EXTENSION] = "";
159 
160 static int dtmfmode = 0;
161 static int nat = 0;
162 static int ncs = 0;
163 static int pktcgatealloc = 0;
164 static int hangupongateremove = 0;
165 
168 
169 static struct {
170  unsigned int tos;
171  unsigned int tos_audio;
172  unsigned int cos;
173  unsigned int cos_audio;
174 } qos = { 0, 0, 0, 0 };
175 
176 static int immediate = 0;
177 
178 static int callwaiting = 0;
179 
180 static int callreturn = 0;
181 
182 static int slowsequence = 0;
183 
184 static int threewaycalling = 0;
185 
186 /*! This is for flashhook transfers */
187 static int transfer = 0;
188 
189 static int cancallforward = 0;
190 
191 static int singlepath = 0;
192 
194 
196 
198 
199 static int amaflags = 0;
200 
201 static int adsi = 0;
202 
203 static unsigned int oseq_global = 0;
205 
206 /*! Wait up to 16 seconds for first digit (FXO logic) */
207 static int firstdigittimeout = 16000;
208 
209 /*! How long to wait for following digits (FXO logic) */
210 static int gendigittimeout = 8000;
211 
212 /*! How long to wait for an extra digit, if there is an ambiguous match */
213 static int matchdigittimeout = 3000;
214 
215 /*! Protect the monitoring thread, so only one process can kill or start it, and not
216  when it's doing something critical. */
218 
220 
221 /*! This is the thread for the monitor which checks for input on the channels
222  * which are not currently in use.
223  */
225 
226 static int restart_monitor(void);
227 
230 
231 static char ourhost[MAXHOSTNAMELEN];
232 static struct in_addr __ourip;
233 static int ourport;
234 
235 static int mgcpdebug = 0;
236 
237 static struct sched_context *sched;
238 static struct io_context *io;
239 /*! The private structures of the mgcp channels are linked for
240  * selecting outgoing channels
241  */
242 
243 #define MGCP_MAX_HEADERS 64
244 #define MGCP_MAX_LINES 64
245 
246 struct mgcp_request {
247  int len;
248  char *verb;
249  char *identifier;
250  char *endpoint;
251  char *version;
252  int headers; /*!< MGCP Headers */
254  int lines; /*!< SDP Content */
257  int cmd; /*!< int version of verb = command */
258  unsigned int trid; /*!< int version of identifier = transaction id */
259  struct mgcp_request *next; /*!< next in the queue */
260 };
261 
262 /*! \brief mgcp_message: MGCP message for queuing up */
263 struct mgcp_message {
266  int retrans;
267  unsigned long expire;
268  unsigned int seqno;
269  int len;
271  char buf[0];
272 };
273 
274 #define RESPONSE_TIMEOUT 30 /*!< in seconds */
275 
277  time_t whensent;
278  int len;
279  int seqno;
281  char buf[0];
282 };
283 
284 #define MAX_SUBS 2
285 
286 #define SUB_REAL 0
287 #define SUB_ALT 1
288 
290  /*! subchannel magic string.
291  Needed to prove that any subchannel pointer passed by asterisk
292  really points to a valid subchannel memory area.
293  Ugly.. But serves the purpose for the time being.
294  */
295 #define MGCP_SUBCHANNEL_MAGIC "!978!"
296  char magic[6];
298  int id;
302  struct sockaddr_in tmpdest;
303  char txident[80]; /*! \todo FIXME txident is replaced by rqnt_ident in endpoint.
304  This should be obsoleted */
305  char cxident[80];
306  char callid[80];
307  int cxmode;
308  struct mgcp_request *cx_queue; /*!< pending CX commands */
309  ast_mutex_t cx_queue_lock; /*!< CX queue lock */
310  int nat;
311  int iseq; /*!< Not used? RTP? */
312  int outgoing;
314  int sdpsent;
315  struct cops_gate *gate;
316  struct mgcp_subchannel *next; /*!< for out circular linked list */
317 };
318 
319 #define MGCP_ONHOOK 1
320 #define MGCP_OFFHOOK 2
321 
322 #define TYPE_TRUNK 1
323 #define TYPE_LINE 2
324 
327  char name[80];
328  struct mgcp_subchannel *sub; /*!< Pointer to our current connection, channel and stuff */
329  char accountcode[AST_MAX_ACCOUNT_CODE];
330  char exten[AST_MAX_EXTENSION]; /*!< Extention where to start */
331  char context[AST_MAX_EXTENSION];
332  char language[MAX_LANGUAGE];
333  char cid_num[AST_MAX_EXTENSION]; /*!< Caller*ID number */
334  char cid_name[AST_MAX_EXTENSION]; /*!< Caller*ID name */
335  char lastcallerid[AST_MAX_EXTENSION]; /*!< Last Caller*ID */
336  char dtmf_buf[AST_MAX_EXTENSION]; /*!< place to collect digits be */
337  char call_forward[AST_MAX_EXTENSION]; /*!< Last Caller*ID */
338  char musicclass[MAX_MUSICCLASS];
339  char curtone[80]; /*!< Current tone */
340  char mailbox[AST_MAX_EXTENSION];
341  char parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */
347  int transfer;
353  int dnd; /* How does this affect callwait? Do we just deny a mgcp_request if we're dnd? */
356  int dtmfmode;
357  int amaflags;
358  int ncs;
361  int type;
362  int slowsequence; /*!< MS: Sequence the endpoint as a whole */
363  int group;
364  int iseq; /*!< Not used? */
365  int lastout; /*!< tracking this on the subchannels. Is it needed here? */
366  int needdestroy; /*!< Not used? */
370  int msgstate; /*!< voicemail message state */
373  int adsi;
374  char rqnt_ident[80]; /*!< request identifier */
375  struct mgcp_request *rqnt_queue; /*!< pending RQNT commands */
377  struct mgcp_request *cmd_queue; /*!< pending commands other than RQNT */
379  int delme; /*!< needed for reload */
380  int needaudit; /*!< needed for reload */
381  struct ast_dsp *dsp; /*!< XXX Should there be a dsp/subchannel? XXX */
382  /* owner is tracked on the subchannels, and the *sub indicates whos in charge */
383  /* struct ast_channel *owner; */
384  /* struct ast_rtp *rtp; */
385  /* struct sockaddr_in tmpdest; */
386  /* message go the the endpoint and not the channel so they stay here */
387  struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
390 };
391 
392 static struct mgcp_gateway {
393  /* A gateway containing one or more endpoints */
394  char name[80];
395  int isnamedottedip; /*!< is the name FQDN or dotted ip */
396  struct sockaddr_in addr;
397  struct sockaddr_in defaddr;
398  struct in_addr ourip;
399  int dynamic;
400  int expire; /*!< XXX Should we ever expire dynamic registrations? XXX */
402  struct ast_ha *ha;
403 /* obsolete
404  time_t lastouttime;
405  int lastout;
406  int messagepending;
407 */
408 /* Wildcard endpoint name */
409  char wcardep[30];
410  struct mgcp_message *msgs; /*!< gw msg queue */
411  ast_mutex_t msgs_lock; /*!< queue lock */
412  int retransid; /*!< retrans timer id */
413  int delme; /*!< needed for reload */
414  int realtime;
417 } *gateways = NULL;
418 
420 static int mgcp_reloading = 0;
421 
422 /*! \brief gatelock: mutex for gateway/endpoint lists */
424 
425 static int mgcpsock = -1;
426 
427 static struct sockaddr_in bindaddr;
428 
429 static struct ast_frame *mgcp_read(struct ast_channel *ast);
430 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
431 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
432 static int transmit_modify_request(struct mgcp_subchannel *sub);
433 static int transmit_connect(struct mgcp_subchannel *sub);
434 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
435 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, format_t codecs);
436 static int transmit_connection_del(struct mgcp_subchannel *sub);
437 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
438 static void start_rtp(struct mgcp_subchannel *sub);
439 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
440  int result, unsigned int ident, struct mgcp_request *resp);
441 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
442 static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
443 static int reload_config(int reload);
444 
445 static struct ast_channel *mgcp_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
446 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout);
447 static int mgcp_hangup(struct ast_channel *ast);
448 static int mgcp_answer(struct ast_channel *ast);
449 static struct ast_frame *mgcp_read(struct ast_channel *ast);
450 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame);
451 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
452 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
453 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
454 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
455 static int mgcp_devicestate(void *data);
456 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone);
457 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp);
458 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v);
459 static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub);
460 static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen);
461 static struct ast_variable *add_var(const char *buf, struct ast_variable *list);
462 static struct ast_variable *copy_vars(struct ast_variable *src);
463 
464 static const struct ast_channel_tech mgcp_tech = {
465  .type = "MGCP",
466  .description = tdesc,
467  .capabilities = AST_FORMAT_ULAW | AST_FORMAT_ALAW,
469  .requester = mgcp_request,
470  .devicestate = mgcp_devicestate,
471  .call = mgcp_call,
472  .hangup = mgcp_hangup,
473  .answer = mgcp_answer,
474  .read = mgcp_read,
475  .write = mgcp_write,
476  .indicate = mgcp_indicate,
477  .fixup = mgcp_fixup,
478  .send_digit_begin = mgcp_senddigit_begin,
479  .send_digit_end = mgcp_senddigit_end,
480  .bridge = ast_rtp_instance_bridge,
481  .func_channel_read = acf_channel_read,
482 };
483 
484 static void mwi_event_cb(const struct ast_event *event, void *userdata)
485 {
486  /* This module does not handle MWI in an event-based manner. However, it
487  * subscribes to MWI for each mailbox that is configured so that the core
488  * knows that we care about it. Then, chan_mgcp will get the MWI from the
489  * event cache instead of checking the mailbox directly. */
490 }
491 
492 static int has_voicemail(struct mgcp_endpoint *p)
493 {
494  int new_msgs;
495  struct ast_event *event;
496  char *mbox, *cntx;
497 
498  cntx = mbox = ast_strdupa(p->mailbox);
499  strsep(&cntx, "@");
500  if (ast_strlen_zero(cntx))
501  cntx = "default";
502 
507 
508  if (event) {
509  new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
510  ast_event_destroy(event);
511  } else
512  new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
513 
514  return new_msgs;
515 }
516 
517 static int unalloc_sub(struct mgcp_subchannel *sub)
518 {
519  struct mgcp_endpoint *p = sub->parent;
520  if (p->sub == sub) {
521  ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
522  return -1;
523  }
524  ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
525 
526  sub->owner = NULL;
527  if (!ast_strlen_zero(sub->cxident)) {
529  }
530  sub->cxident[0] = '\0';
531  sub->callid[0] = '\0';
532  sub->cxmode = MGCP_CX_INACTIVE;
533  sub->outgoing = 0;
534  sub->alreadygone = 0;
535  memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
536  if (sub->rtp) {
538  sub->rtp = NULL;
539  }
540  dump_cmd_queues(NULL, sub);
541  return 0;
542 }
543 
544 /* modified for new transport mechanism */
545 static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
546 {
547  int res;
548  if (gw->addr.sin_addr.s_addr)
549  res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
550  else
551  res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
552  if (res != len) {
553  ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
554  }
555  return res;
556 }
557 
558 static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
559 {
560  struct mgcp_endpoint *p = sub->parent;
561  int res;
562  ast_debug(1, "Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
563  res = __mgcp_xmit(p->parent, resp->buf, resp->len);
564  if (res > 0)
565  res = 0;
566  return res;
567 }
568 
569 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
570 {
571  struct mgcp_endpoint *p = sub->parent;
572  int res;
573  ast_debug(1, "Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
574  res = __mgcp_xmit(p->parent, req->data, req->len);
575  if (res > 0)
576  res = 0;
577  return res;
578 }
579 
580 /* modified for new transport framework */
581 static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
582 {
583  struct mgcp_message *cur, *q = NULL, *w, *prev;
584 
586  for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
587  if (!p || cur->owner_ep == p) {
588  if (prev) {
589  prev->next = cur->next;
590  } else {
591  gw->msgs = cur->next;
592  }
593 
594  ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
595  gw->name, cur->seqno);
596 
597  w = cur;
598  if (q) {
599  w->next = q;
600  } else {
601  w->next = NULL;
602  }
603  q = w;
604  }
605  }
607 
608  while (q) {
609  cur = q;
610  q = q->next;
611  ast_free(cur);
612  }
613 }
614 
615 static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
616 {
617  for (;;) {
618  if (sub->owner) {
619  if (!ast_channel_trylock(sub->owner)) {
620  ast_queue_frame(sub->owner, f);
622  break;
623  } else {
624  DEADLOCK_AVOIDANCE(&sub->lock);
625  }
626  } else {
627  break;
628  }
629  }
630 }
631 
632 static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
633 {
634  for (;;) {
635  if (sub->owner) {
636  if (!ast_channel_trylock(sub->owner)) {
637  ast_queue_hangup(sub->owner);
639  break;
640  } else {
641  DEADLOCK_AVOIDANCE(&sub->lock);
642  }
643  } else {
644  break;
645  }
646  }
647 }
648 
649 static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
650 {
651  struct ast_frame f = { AST_FRAME_CONTROL, { control } };
652  return mgcp_queue_frame(sub, &f);
653 }
654 
655 static int retrans_pkt(const void *data)
656 {
657  struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
658  struct mgcp_message *cur, *exq = NULL, *w, *prev;
659  int res = 0;
660 
661  /* find out expired msgs */
663 
664  for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
665  if (cur->retrans < MAX_RETRANS) {
666  cur->retrans++;
667  ast_debug(1, "Retransmitting #%d transaction %u on [%s]\n",
668  cur->retrans, cur->seqno, gw->name);
669  __mgcp_xmit(gw, cur->buf, cur->len);
670  } else {
671  if (prev)
672  prev->next = cur->next;
673  else
674  gw->msgs = cur->next;
675 
676  ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
677  cur->seqno, gw->name);
678 
679  w = cur;
680 
681  if (exq) {
682  w->next = exq;
683  } else {
684  w->next = NULL;
685  }
686  exq = w;
687  }
688  }
689 
690  if (!gw->msgs) {
691  gw->retransid = -1;
692  res = 0;
693  } else {
694  res = 1;
695  }
697 
698  while (exq) {
699  cur = exq;
700  /* time-out transaction */
701  handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
702  exq = exq->next;
703  ast_free(cur);
704  }
705 
706  return res;
707 }
708 
709 /* modified for the new transaction mechanism */
710 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
711  char *data, int len, unsigned int seqno)
712 {
713  struct mgcp_message *msg;
714  struct mgcp_message *cur;
715  struct mgcp_gateway *gw;
716  struct timeval now;
717 
718  if (!(msg = ast_malloc(sizeof(*msg) + len))) {
719  return -1;
720  }
721  if (!(gw = ((p && p->parent) ? p->parent : NULL))) {
722  ast_free(msg);
723  return -1;
724  }
725 
726  msg->owner_sub = sub;
727  msg->owner_ep = p;
728  msg->seqno = seqno;
729  msg->next = NULL;
730  msg->len = len;
731  msg->retrans = 0;
732  memcpy(msg->buf, data, msg->len);
733 
735  for (cur = gw->msgs; cur && cur->next; cur = cur->next);
736  if (cur) {
737  cur->next = msg;
738  } else {
739  gw->msgs = msg;
740  }
741 
742  now = ast_tvnow();
743  msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS;
744 
745  if (gw->retransid == -1)
746  gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
748  __mgcp_xmit(gw, msg->buf, msg->len);
749  /* XXX Should schedule retransmission XXX */
750  return 0;
751 }
752 
753 /* modified for new transport */
754 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
755  struct mgcp_request *req, unsigned int seqno)
756 {
757  int res = 0;
758  struct mgcp_request **queue, *q, *r, *t;
759  ast_mutex_t *l;
760 
761  ast_debug(1, "Slow sequence is %d\n", p->slowsequence);
762  if (p->slowsequence) {
763  queue = &p->cmd_queue;
764  l = &p->cmd_queue_lock;
765  ast_mutex_lock(l);
766  } else {
767  switch (req->cmd) {
768  case MGCP_CMD_DLCX:
769  queue = &sub->cx_queue;
770  l = &sub->cx_queue_lock;
771  ast_mutex_lock(l);
772  q = sub->cx_queue;
773  /* delete pending cx cmds */
774  /* buggy sb5120 */
775  if (!sub->parent->ncs) {
776  while (q) {
777  r = q->next;
778  ast_free(q);
779  q = r;
780  }
781  *queue = NULL;
782  }
783  break;
784 
785  case MGCP_CMD_CRCX:
786  case MGCP_CMD_MDCX:
787  queue = &sub->cx_queue;
788  l = &sub->cx_queue_lock;
789  ast_mutex_lock(l);
790  break;
791 
792  case MGCP_CMD_RQNT:
793  queue = &p->rqnt_queue;
794  l = &p->rqnt_queue_lock;
795  ast_mutex_lock(l);
796  break;
797 
798  default:
799  queue = &p->cmd_queue;
800  l = &p->cmd_queue_lock;
801  ast_mutex_lock(l);
802  break;
803  }
804  }
805 
806  if (!(r = ast_malloc(sizeof(*r)))) {
807  ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
808  ast_mutex_unlock(l);
809  return -1;
810  }
811  memcpy(r, req, sizeof(*r));
812 
813  if (!(*queue)) {
814  ast_debug(1, "Posting Request:\n%s to %s:%d\n", req->data,
815  ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
816 
817  res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
818  } else {
819  ast_debug(1, "Queueing Request:\n%s to %s:%d\n", req->data,
820  ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
821  }
822 
823  /* XXX find tail. We could also keep tail in the data struct for faster access */
824  for (t = *queue; t && t->next; t = t->next);
825 
826  r->next = NULL;
827  if (t)
828  t->next = r;
829  else
830  *queue = r;
831 
832  ast_mutex_unlock(l);
833 
834  return res;
835 }
836 
837 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
838 {
839  int res;
840  struct mgcp_endpoint *p;
841  struct mgcp_subchannel *sub;
842  char tone[50] = "";
843  const char *distinctive_ring = NULL;
844  struct varshead *headp;
845  struct ast_var_t *current;
846 
847  ast_debug(3, "MGCP mgcp_call(%s)\n", ast->name);
848  sub = ast->tech_pvt;
849  p = sub->parent;
850  headp = &ast->varshead;
851  AST_LIST_TRAVERSE(headp,current,entries) {
852  /* Check whether there is an ALERT_INFO variable */
853  if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {
854  distinctive_ring = ast_var_value(current);
855  }
856  }
857 
858  ast_mutex_lock(&sub->lock);
859  switch (p->hookstate) {
860  case MGCP_OFFHOOK:
861  if (!ast_strlen_zero(distinctive_ring)) {
862  snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
863  ast_debug(3, "MGCP distinctive callwait %s\n", tone);
864  } else {
865  ast_copy_string(tone, (p->ncs ? "L/wt1" : "L/wt"), sizeof(tone));
866  ast_debug(3, "MGCP normal callwait %s\n", tone);
867  }
868  break;
869  case MGCP_ONHOOK:
870  default:
871  if (!ast_strlen_zero(distinctive_ring)) {
872  snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
873  ast_debug(3, "MGCP distinctive ring %s\n", tone);
874  } else {
875  ast_copy_string(tone, "L/rg", sizeof(tone));
876  ast_debug(3, "MGCP default ring\n");
877  }
878  break;
879  }
880 
881  if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
882  ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
883  ast_mutex_unlock(&sub->lock);
884  return -1;
885  }
886 
887  res = 0;
888  sub->outgoing = 1;
889  sub->cxmode = MGCP_CX_RECVONLY;
891  if (p->type == TYPE_LINE) {
892  if (!sub->rtp) {
893  start_rtp(sub);
894  } else {
896  }
897 
898  if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
899  /* try to prevent a callwait from disturbing the other connection */
900  sub->next->cxmode = MGCP_CX_RECVONLY;
902  }
903 
905  S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""),
906  S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""));
908 
909  if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
910  /* Put the connection back in sendrecv */
911  sub->next->cxmode = MGCP_CX_SENDRECV;
913  }
914  } else {
915  ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
916  res = -1;
917  }
918  ast_mutex_unlock(&sub->lock);
919  return res;
920 }
921 
922 static int mgcp_hangup(struct ast_channel *ast)
923 {
924  struct mgcp_subchannel *sub = ast->tech_pvt;
925  struct mgcp_endpoint *p = sub->parent;
926  struct ast_channel *bridged;
927 
928  ast_debug(1, "mgcp_hangup(%s)\n", ast->name);
929  if (!ast->tech_pvt) {
930  ast_debug(1, "Asked to hangup channel not connected\n");
931  return 0;
932  }
933  if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
934  ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n");
935  return 0;
936  }
937  ast_mutex_lock(&sub->lock);
938  ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
939 
940  if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
941  /* check whether other channel is active. */
942  if (!sub->next->owner) {
943  if (p->dtmfmode & MGCP_DTMF_HYBRID) {
944  p->dtmfmode &= ~MGCP_DTMF_INBAND;
945  }
946  ast_debug(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
947  ast_dsp_free(p->dsp);
948  p->dsp = NULL;
949  }
950  }
951 
952  sub->owner = NULL;
953 
954  /* for deleting gate */
955  if (p->pktcgatealloc && sub->gate) {
956  sub->gate->gate_open = NULL;
957  sub->gate->gate_remove = NULL;
958  sub->gate->got_dq_gi = NULL;
959  sub->gate->tech_pvt = NULL;
960  if (sub->gate->state == GATE_ALLOC_PROGRESS || sub->gate->state == GATE_ALLOCATED) {
961  ast_pktccops_gate_alloc(GATE_DEL, sub->gate, 0, 0, 0, 0, 0, 0, NULL, NULL);
962  } else {
963  sub->gate->deltimer = time(NULL) + 5;
964  }
965  sub->gate = NULL;
966  }
967 
968  if (!ast_strlen_zero(sub->cxident)) {
970  }
971  sub->cxident[0] = '\0';
972  if ((sub == p->sub) && sub->next->owner) {
973  if (p->hookstate == MGCP_OFFHOOK) {
974  if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
975  /* ncs fix! */
976  bridged = ast_bridged_channel(sub->next->owner);
977  transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"),
978  S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""),
979  S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, ""));
980  }
981  } else {
982  /* set our other connection as the primary and swith over to it */
983  p->sub = sub->next;
986  if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
987  bridged = ast_bridged_channel(sub->next->owner);
989  S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""),
990  S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, ""));
991  }
992  }
993 
994  } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
995  transmit_notify_request(sub, p->ncs ? "" : "L/v");
996  } else if (p->hookstate == MGCP_OFFHOOK) {
997  transmit_notify_request(sub, "L/ro");
998  } else {
999  transmit_notify_request(sub, "");
1000  }
1001 
1002  ast->tech_pvt = NULL;
1003  sub->alreadygone = 0;
1004  sub->outgoing = 0;
1005  sub->cxmode = MGCP_CX_INACTIVE;
1006  sub->callid[0] = '\0';
1007  if (p) {
1008  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
1009  }
1010  /* Reset temporary destination */
1011  memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
1012  if (sub->rtp) {
1014  sub->rtp = NULL;
1015  }
1016 
1018 
1019  if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
1020  p->hidecallerid = 0;
1021  if (p->hascallwaiting && !p->callwaiting) {
1022  ast_verb(3, "Enabling call waiting on %s\n", ast->name);
1023  p->callwaiting = -1;
1024  }
1025  if (has_voicemail(p)) {
1026  ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
1027  ast->name, p->name, p->parent->name);
1028  transmit_notify_request(sub, "L/vmwi(+)");
1029  } else {
1030  ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
1031  ast->name, p->name, p->parent->name);
1032  transmit_notify_request(sub, "L/vmwi(-)");
1033  }
1034  }
1035  ast_mutex_unlock(&sub->lock);
1036  return 0;
1037 }
1038 
1039 static char *handle_mgcp_show_endpoints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1040 {
1041  struct mgcp_gateway *mg;
1042  struct mgcp_endpoint *me;
1043  int hasendpoints = 0;
1044  struct ast_variable * v = NULL;
1045 
1046  switch (cmd) {
1047  case CLI_INIT:
1048  e->command = "mgcp show endpoints";
1049  e->usage =
1050  "Usage: mgcp show endpoints\n"
1051  " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
1052  return NULL;
1053  case CLI_GENERATE:
1054  return NULL;
1055  }
1056 
1057  if (a->argc != 3) {
1058  return CLI_SHOWUSAGE;
1059  }
1061  for (mg = gateways; mg; mg = mg->next) {
1062  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");
1063  for (me = mg->endpoints; me; me = me->next) {
1064  ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
1065  if (me->chanvars) {
1066  ast_cli(a->fd, " Variables:\n");
1067  for (v = me->chanvars ; v ; v = v->next) {
1068  ast_cli(a->fd, " %s = '%s'\n", v->name, v->value);
1069  }
1070  }
1071  hasendpoints = 1;
1072  }
1073  if (!hasendpoints) {
1074  ast_cli(a->fd, " << No Endpoints Defined >> ");
1075  }
1076  }
1078  return CLI_SUCCESS;
1079 }
1080 
1081 static char *handle_mgcp_audit_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1082 {
1083  struct mgcp_gateway *mg;
1084  struct mgcp_endpoint *me;
1085  int found = 0;
1086  char *ename,*gname, *c;
1087 
1088  switch (cmd) {
1089  case CLI_INIT:
1090  e->command = "mgcp audit endpoint";
1091  e->usage =
1092  "Usage: mgcp audit endpoint <endpointid>\n"
1093  " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
1094  " mgcp debug MUST be on to see the results of this command.\n";
1095  return NULL;
1096  case CLI_GENERATE:
1097  return NULL;
1098  }
1099 
1100  if (!mgcpdebug) {
1101  return CLI_SHOWUSAGE;
1102  }
1103  if (a->argc != 4)
1104  return CLI_SHOWUSAGE;
1105  /* split the name into parts by null */
1106  ename = ast_strdupa(a->argv[3]);
1107  for (gname = ename; *gname; gname++) {
1108  if (*gname == '@') {
1109  *gname = 0;
1110  gname++;
1111  break;
1112  }
1113  }
1114  if (gname[0] == '[') {
1115  gname++;
1116  }
1117  if ((c = strrchr(gname, ']'))) {
1118  *c = '\0';
1119  }
1121  for (mg = gateways; mg; mg = mg->next) {
1122  if (!strcasecmp(mg->name, gname)) {
1123  for (me = mg->endpoints; me; me = me->next) {
1124  if (!strcasecmp(me->name, ename)) {
1125  found = 1;
1127  break;
1128  }
1129  }
1130  if (found) {
1131  break;
1132  }
1133  }
1134  }
1135  if (!found) {
1136  ast_cli(a->fd, " << Could not find endpoint >> ");
1137  }
1139  return CLI_SUCCESS;
1140 }
1141 
1142 static char *handle_mgcp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1143 {
1144  switch (cmd) {
1145  case CLI_INIT:
1146  e->command = "mgcp set debug {on|off}";
1147  e->usage =
1148  "Usage: mgcp set debug {on|off}\n"
1149  " Enables/Disables dumping of MGCP packets for debugging purposes\n";
1150  return NULL;
1151  case CLI_GENERATE:
1152  return NULL;
1153  }
1154 
1155  if (a->argc != e->args)
1156  return CLI_SHOWUSAGE;
1157 
1158  if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
1159  mgcpdebug = 1;
1160  ast_cli(a->fd, "MGCP Debugging Enabled\n");
1161  } else if (!strncasecmp(a->argv[3], "off", 3)) {
1162  mgcpdebug = 0;
1163  ast_cli(a->fd, "MGCP Debugging Disabled\n");
1164  } else {
1165  return CLI_SHOWUSAGE;
1166  }
1167  return CLI_SUCCESS;
1168 }
1169 
1170 static struct ast_cli_entry cli_mgcp[] = {
1171  AST_CLI_DEFINE(handle_mgcp_audit_endpoint, "Audit specified MGCP endpoint"),
1172  AST_CLI_DEFINE(handle_mgcp_show_endpoints, "List defined MGCP endpoints"),
1173  AST_CLI_DEFINE(handle_mgcp_set_debug, "Enable/Disable MGCP debugging"),
1174  AST_CLI_DEFINE(mgcp_reload, "Reload MGCP configuration"),
1175 };
1176 
1177 static int mgcp_answer(struct ast_channel *ast)
1178 {
1179  int res = 0;
1180  struct mgcp_subchannel *sub = ast->tech_pvt;
1181  struct mgcp_endpoint *p = sub->parent;
1182 
1183  ast_mutex_lock(&sub->lock);
1184  sub->cxmode = MGCP_CX_SENDRECV;
1185  if (!sub->rtp) {
1186  start_rtp(sub);
1187  } else {
1189  }
1190  ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n",
1191  ast->name, p->name, p->parent->name, sub->id);
1192  if (ast->_state != AST_STATE_UP) {
1193  ast_setstate(ast, AST_STATE_UP);
1194  ast_debug(1, "mgcp_answer(%s)\n", ast->name);
1195  transmit_notify_request(sub, "");
1197  }
1198  ast_mutex_unlock(&sub->lock);
1199  return res;
1200 }
1201 
1202 static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
1203 {
1204  /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
1205  struct ast_frame *f;
1206 
1207  f = ast_rtp_instance_read(sub->rtp, 0);
1208  /* Don't send RFC2833 if we're not supposed to */
1209  if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
1210  return &ast_null_frame;
1211  if (sub->owner) {
1212  /* We already hold the channel lock */
1213  if (f->frametype == AST_FRAME_VOICE) {
1214  if (f->subclass.codec != sub->owner->nativeformats) {
1215  ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec));
1216  sub->owner->nativeformats = f->subclass.codec;
1219  }
1220  /* Courtesy fearnor aka alex@pilosoft.com */
1221  if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
1222 #if 0
1223  ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
1224 #endif
1225  f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
1226  }
1227  }
1228  }
1229  return f;
1230 }
1231 
1232 
1233 static struct ast_frame *mgcp_read(struct ast_channel *ast)
1234 {
1235  struct ast_frame *f;
1236  struct mgcp_subchannel *sub = ast->tech_pvt;
1237  ast_mutex_lock(&sub->lock);
1238  f = mgcp_rtp_read(sub);
1239  ast_mutex_unlock(&sub->lock);
1240  return f;
1241 }
1242 
1243 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
1244 {
1245  struct mgcp_subchannel *sub = ast->tech_pvt;
1246  int res = 0;
1247  char buf[256];
1248 
1249  if (frame->frametype != AST_FRAME_VOICE) {
1250  if (frame->frametype == AST_FRAME_IMAGE)
1251  return 0;
1252  else {
1253  ast_log(LOG_WARNING, "Can't send %u type frames with MGCP write\n", frame->frametype);
1254  return 0;
1255  }
1256  } else {
1257  if (!(frame->subclass.codec & ast->nativeformats)) {
1258  ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
1260  ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
1263  /* return -1; */
1264  }
1265  }
1266  if (sub) {
1267  ast_mutex_lock(&sub->lock);
1268  if (!sub->sdpsent && sub->gate) {
1269  if (sub->gate->state == GATE_ALLOCATED) {
1270  ast_debug(1, "GATE ALLOCATED, sending sdp\n");
1271  transmit_modify_with_sdp(sub, NULL, 0);
1272  }
1273  }
1274  if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
1275  if (sub->rtp) {
1276  res = ast_rtp_instance_write(sub->rtp, frame);
1277  }
1278  }
1279  ast_mutex_unlock(&sub->lock);
1280  }
1281  return res;
1282 }
1283 
1284 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1285 {
1286  struct mgcp_subchannel *sub = newchan->tech_pvt;
1287 
1288  ast_mutex_lock(&sub->lock);
1289  ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
1290  if (sub->owner != oldchan) {
1291  ast_mutex_unlock(&sub->lock);
1292  ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
1293  return -1;
1294  }
1295  sub->owner = newchan;
1296  ast_mutex_unlock(&sub->lock);
1297  return 0;
1298 }
1299 
1300 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit)
1301 {
1302  struct mgcp_subchannel *sub = ast->tech_pvt;
1303  struct mgcp_endpoint *p = sub->parent;
1304  int res = 0;
1305 
1306  ast_mutex_lock(&sub->lock);
1308  ast_debug(1, "Sending DTMF using inband/hybrid\n");
1309  res = -1; /* Let asterisk play inband indications */
1310  } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
1311  ast_debug(1, "Sending DTMF using RFC2833\n");
1312  ast_rtp_instance_dtmf_begin(sub->rtp, digit);
1313  } else {
1314  ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
1315  }
1316  ast_mutex_unlock(&sub->lock);
1317 
1318  return res;
1319 }
1320 
1321 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
1322 {
1323  struct mgcp_subchannel *sub = ast->tech_pvt;
1324  struct mgcp_endpoint *p = sub->parent;
1325  int res = 0;
1326  char tmp[4];
1327 
1328  ast_mutex_lock(&sub->lock);
1330  ast_debug(1, "Stopping DTMF using inband/hybrid\n");
1331  res = -1; /* Tell Asterisk to stop inband indications */
1332  } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
1333  ast_debug(1, "Stopping DTMF using RFC2833\n");
1334  if (sub->parent->ncs) {
1335  tmp[0] = digit;
1336  tmp[1] = '\0';
1337  } else {
1338  tmp[0] = 'D';
1339  tmp[1] = '/';
1340  tmp[2] = digit;
1341  tmp[3] = '\0';
1342  }
1343  transmit_notify_request(sub, tmp);
1344  ast_rtp_instance_dtmf_end(sub->rtp, digit);
1345  } else {
1346  ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
1347  }
1348  ast_mutex_unlock(&sub->lock);
1349 
1350  return res;
1351 }
1352 
1353 /*!
1354  * \brief mgcp_devicestate: channel callback for device status monitoring
1355  * \param data tech/resource name of MGCP device to query
1356  *
1357  * Callback for device state management in channel subsystem
1358  * to obtain device status (up/down) of a specific MGCP endpoint
1359  *
1360  * \return device status result (from devicestate.h) AST_DEVICE_INVALID (not available) or AST_DEVICE_UNKNOWN (available but unknown state)
1361  */
1362 static int mgcp_devicestate(void *data)
1363 {
1364  struct mgcp_gateway *g;
1365  struct mgcp_endpoint *e = NULL;
1366  char *tmp, *endpt, *gw;
1367  int ret = AST_DEVICE_INVALID;
1368 
1369  endpt = ast_strdupa(data);
1370  if ((tmp = strchr(endpt, '@'))) {
1371  *tmp++ = '\0';
1372  gw = tmp;
1373  } else
1374  goto error;
1375 
1377  for (g = gateways; g; g = g->next) {
1378  if (strcasecmp(g->name, gw) == 0) {
1379  e = g->endpoints;
1380  break;
1381  }
1382  }
1383 
1384  if (!e)
1385  goto error;
1386 
1387  for (; e; e = e->next) {
1388  if (strcasecmp(e->name, endpt) == 0) {
1389  break;
1390  }
1391  }
1392 
1393  if (!e)
1394  goto error;
1395 
1396  /*
1397  * As long as the gateway/endpoint is valid, we'll
1398  * assume that the device is available and its state
1399  * can be tracked.
1400  */
1401  ret = AST_DEVICE_UNKNOWN;
1402 
1403 error:
1405  return ret;
1406 }
1407 
1408 static char *control2str(int ind) {
1409  switch (ind) {
1410  case AST_CONTROL_HANGUP:
1411  return "Other end has hungup";
1412  case AST_CONTROL_RING:
1413  return "Local ring";
1414  case AST_CONTROL_RINGING:
1415  return "Remote end is ringing";
1416  case AST_CONTROL_ANSWER:
1417  return "Remote end has answered";
1418  case AST_CONTROL_BUSY:
1419  return "Remote end is busy";
1421  return "Make it go off hook";
1422  case AST_CONTROL_OFFHOOK:
1423  return "Line is off hook";
1425  return "Congestion (circuits busy)";
1426  case AST_CONTROL_FLASH:
1427  return "Flash hook";
1428  case AST_CONTROL_WINK:
1429  return "Wink";
1430  case AST_CONTROL_OPTION:
1431  return "Set a low-level option";
1432  case AST_CONTROL_RADIO_KEY:
1433  return "Key Radio";
1435  return "Un-Key Radio";
1436  }
1437  return "UNKNOWN";
1438 }
1439 
1440 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
1441 {
1442  struct mgcp_subchannel *sub = ast->tech_pvt;
1443  int res = 0;
1444 
1445  ast_debug(3, "MGCP asked to indicate %d '%s' condition on channel %s\n",
1446  ind, control2str(ind), ast->name);
1447  ast_mutex_lock(&sub->lock);
1448  switch(ind) {
1449  case AST_CONTROL_RINGING:
1450 #ifdef DLINK_BUGGY_FIRMWARE
1451  transmit_notify_request(sub, "rt");
1452 #else
1453  if (!sub->sdpsent) { /* will hide the inband progress!!! */
1454  transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt");
1455  }
1456 #endif
1457  break;
1458  case AST_CONTROL_BUSY:
1459  transmit_notify_request(sub, "L/bz");
1460  break;
1462  /* We do not currently support resetting of the Interdigit Timer, so treat
1463  * Incomplete control frames as a congestion response
1464  */
1466  transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg");
1467  break;
1468  case AST_CONTROL_HOLD:
1469  ast_moh_start(ast, data, NULL);
1470  break;
1471  case AST_CONTROL_UNHOLD:
1472  ast_moh_stop(ast);
1473  break;
1474  case AST_CONTROL_SRCUPDATE:
1476  break;
1477  case AST_CONTROL_SRCCHANGE:
1479  break;
1480  case AST_CONTROL_PROGRESS:
1483  case -1:
1484  transmit_notify_request(sub, "");
1485  break;
1486  default:
1487  ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
1488  res = -1;
1489  }
1490  ast_mutex_unlock(&sub->lock);
1491  return res;
1492 }
1493 
1494 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, const char *linkedid)
1495 {
1496  struct ast_channel *tmp;
1497  struct ast_variable *v = NULL;
1498  struct mgcp_endpoint *i = sub->parent;
1499  int fmt;
1500 
1501  tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, linkedid, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
1502  if (tmp) {
1503  tmp->tech = &mgcp_tech;
1504  tmp->nativeformats = i->capability;
1505  if (!tmp->nativeformats) {
1506  tmp->nativeformats = capability;
1507  }
1508  fmt = ast_best_codec(tmp->nativeformats);
1509  if (sub->rtp) {
1510  ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
1511  }
1513  i->dsp = ast_dsp_new();
1515  /* this is to prevent clipping of dtmf tones during dsp processing */
1517  } else {
1518  i->dsp = NULL;
1519  }
1520  if (state == AST_STATE_RING)
1521  tmp->rings = 1;
1522  tmp->writeformat = fmt;
1523  tmp->rawwriteformat = fmt;
1524  tmp->readformat = fmt;
1525  tmp->rawreadformat = fmt;
1526  tmp->tech_pvt = sub;
1527  if (!ast_strlen_zero(i->language))
1528  ast_string_field_set(tmp, language, i->language);
1529  if (!ast_strlen_zero(i->accountcode))
1530  ast_string_field_set(tmp, accountcode, i->accountcode);
1531  if (i->amaflags)
1532  tmp->amaflags = i->amaflags;
1533  sub->owner = tmp;
1535  tmp->callgroup = i->callgroup;
1536  tmp->pickupgroup = i->pickupgroup;
1538  ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
1539  ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
1540 
1541  /* Don't use ast_set_callerid() here because it will
1542  * generate a needless NewCallerID event */
1543  if (!ast_strlen_zero(i->cid_num)) {
1544  tmp->caller.ani.number.valid = 1;
1545  tmp->caller.ani.number.str = ast_strdup(i->cid_num);
1546  }
1547 
1548  if (!i->adsi) {
1550  }
1551  tmp->priority = 1;
1552 
1553  /* Set channel variables for this call from configuration */
1554  for (v = i->chanvars ; v ; v = v->next) {
1555  char valuebuf[1024];
1556  pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
1557  }
1558 
1559  if (sub->rtp) {
1561  }
1562  if (state != AST_STATE_DOWN) {
1563  if (ast_pbx_start(tmp)) {
1564  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
1565  ast_hangup(tmp);
1566  tmp = NULL;
1567  }
1568  }
1569  ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
1570  tmp->name, ast_state2str(state));
1571  } else {
1572  ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
1573  }
1574  return tmp;
1575 }
1576 
1577 static char *get_sdp_by_line(char* line, char *name, int nameLen)
1578 {
1579  if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
1580  char *r = line + nameLen + 1;
1581  while (*r && (*r < 33)) ++r;
1582  return r;
1583  }
1584  return "";
1585 }
1586 
1587 static char *get_sdp(struct mgcp_request *req, char *name)
1588 {
1589  int x;
1590  int len = strlen(name);
1591  char *r;
1592 
1593  for (x = 0; x < req->lines; x++) {
1594  r = get_sdp_by_line(req->line[x], name, len);
1595  if (r[0] != '\0') return r;
1596  }
1597  return "";
1598 }
1599 
1600 static void sdpLineNum_iterator_init(int *iterator)
1601 {
1602  *iterator = 0;
1603 }
1604 
1605 static char *get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
1606 {
1607  int len = strlen(name);
1608  char *r;
1609  while (*iterator < req->lines) {
1610  r = get_sdp_by_line(req->line[(*iterator)++], name, len);
1611  if (r[0] != '\0') return r;
1612  }
1613  return "";
1614 }
1615 
1616 static char *__get_header(struct mgcp_request *req, char *name, int *start, char *def)
1617 {
1618  int x;
1619  int len = strlen(name);
1620  char *r;
1621  for (x = *start; x < req->headers; x++) {
1622  if (!strncasecmp(req->header[x], name, len) &&
1623  (req->header[x][len] == ':')) {
1624  r = req->header[x] + len + 1;
1625  while (*r && (*r < 33)) {
1626  r++;
1627  }
1628  *start = x + 1;
1629  return r;
1630  }
1631  }
1632  /* Don't return NULL, so get_header is always a valid pointer */
1633  return def;
1634 }
1635 
1636 static char *get_header(struct mgcp_request *req, char *name)
1637 {
1638  int start = 0;
1639  return __get_header(req, name, &start, "");
1640 }
1641 
1642 /*! \brief get_csv: (SC:) get comma separated value */
1643 static char *get_csv(char *c, int *len, char **next)
1644 {
1645  char *s;
1646 
1647  *next = NULL, *len = 0;
1648  if (!c) return NULL;
1649 
1650  while (*c && (*c < 33 || *c == ',')) {
1651  c++;
1652  }
1653 
1654  s = c;
1655  while (*c && (*c >= 33 && *c != ',')) {
1656  c++, (*len)++;
1657  }
1658  *next = c;
1659 
1660  if (*len == 0) {
1661  s = NULL, *next = NULL;
1662  }
1663 
1664  return s;
1665 }
1666 
1667 static struct mgcp_gateway *find_realtime_gw(char *name, char *at, struct sockaddr_in *sin)
1668 {
1669  struct mgcp_gateway *g = NULL;
1670  struct ast_variable *mgcpgwconfig = NULL;
1671  struct ast_variable *gwv, *epname = NULL;
1672  struct mgcp_endpoint *e;
1673  char lines[256];
1674  int i, j;
1675 
1676  ast_debug(1, "*** find Realtime MGCPGW\n");
1677 
1678  if (!(i = ast_check_realtime("mgcpgw")) || !(j = ast_check_realtime("mgcpep"))) {
1679  return NULL;
1680  }
1681 
1682  if (ast_strlen_zero(at)) {
1683  ast_debug(1, "null gw name\n");
1684  return NULL;
1685  }
1686 
1687  if (!(mgcpgwconfig = ast_load_realtime("mgcpgw", "name", at, NULL))) {
1688  return NULL;
1689  }
1690 
1691  /*!
1692  * \note This is a fairly odd way of instantiating lines. Instead of each
1693  * line created by virtue of being in the database (and loaded via
1694  * ast_load_realtime_multientry), this code forces a specific order with a
1695  * "lines" entry in the "mgcpgw" record. This has benefits, because as with
1696  * chan_dahdi, values are inherited across definitions. The downside is
1697  * that it's not as clear what the values will be simply by looking at a
1698  * single row in the database, and it's probable that the sanest configuration
1699  * should have the first column in the "mgcpep" table be "clearvars", with a
1700  * static value of "all", if any variables are set at all. It may be worth
1701  * making this assumption explicit in the code in the future, and then just
1702  * using ast_load_realtime_multientry for the "mgcpep" records.
1703  */
1704  lines[0] = '\0';
1705  for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
1706  if (!strcasecmp(gwv->name, "lines")) {
1707  ast_copy_string(lines, gwv->value, sizeof(lines));
1708  break;
1709  }
1710  }
1711  /* Position gwv at the end of the list */
1712  for (gwv = gwv && gwv->next ? gwv : mgcpgwconfig; gwv->next; gwv = gwv->next);
1713 
1714  if (!ast_strlen_zero(lines)) {
1716  AST_APP_ARG(line)[100];
1717  );
1718  AST_STANDARD_APP_ARGS(args, lines);
1719  for (i = 0; i < args.argc; i++) {
1720  gwv->next = ast_load_realtime("mgcpep", "name", at, "line", args.line[i], NULL);
1721 
1722  /* Remove "line" AND position gwv at the end of the list. */
1723  for (epname = NULL; gwv->next; gwv = gwv->next) {
1724  if (!strcasecmp(gwv->next->name, "line")) {
1725  /* Remove it from the list */
1726  epname = gwv->next;
1727  gwv->next = gwv->next->next;
1728  }
1729  }
1730  /* Since "line" instantiates the configuration, we have to move it to the end. */
1731  if (epname) {
1732  gwv->next = epname;
1733  epname->next = NULL;
1734  gwv = gwv->next;
1735  }
1736  }
1737  }
1738  for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
1739  ast_debug(1, "MGCP Realtime var: %s => %s\n", gwv->name, gwv->value);
1740  }
1741 
1742  if (mgcpgwconfig) {
1743  g = build_gateway(at, mgcpgwconfig);
1744  ast_variables_destroy(mgcpgwconfig);
1745  }
1746  if (g) {
1747  g->next = gateways;
1748  g->realtime = 1;
1749  gateways = g;
1750  for (e = g->endpoints; e; e = e->next) {
1752  e->needaudit = 0;
1753  }
1754  }
1755  return g;
1756 }
1757 
1758 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
1759 {
1760  struct mgcp_endpoint *p = NULL;
1761  struct mgcp_subchannel *sub = NULL;
1762  struct mgcp_gateway *g;
1763  char tmp[256] = "";
1764  char *at = NULL, *c;
1765  int found = 0;
1766  if (name) {
1767  ast_copy_string(tmp, name, sizeof(tmp));
1768  at = strchr(tmp, '@');
1769  if (!at) {
1770  ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
1771  return NULL;
1772  }
1773  *at++ = '\0';
1774  }
1776  if (at && (at[0] == '[')) {
1777  at++;
1778  c = strrchr(at, ']');
1779  if (c) {
1780  *c = '\0';
1781  }
1782  }
1783  for (g = gateways ? gateways : find_realtime_gw(name, at, sin); g; g = g->next ? g->next : find_realtime_gw(name, at, sin)) {
1784  if ((!name || !strcasecmp(g->name, at)) &&
1785  (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
1786  /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */
1787  if (sin && g->dynamic && name) {
1788  if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1789  (g->addr.sin_port != sin->sin_port)) {
1790  memcpy(&g->addr, sin, sizeof(g->addr));
1791  {
1792  struct ast_sockaddr tmp1, tmp2;
1793  struct sockaddr_in tmp3 = {0,};
1794 
1795  tmp3.sin_addr = g->ourip;
1796  ast_sockaddr_from_sin(&tmp1, &g->addr);
1797  ast_sockaddr_from_sin(&tmp2, &tmp3);
1798  if (ast_ouraddrfor(&tmp1, &tmp2)) {
1799  memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
1800  }
1801  ast_sockaddr_to_sin(&tmp2, &tmp3);
1802  g->ourip = tmp3.sin_addr;
1803  }
1804  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));
1805  }
1806  /* not dynamic, check if the name matches */
1807  } else if (name) {
1808  if (strcasecmp(g->name, at)) {
1809  g = g->next;
1810  continue;
1811  }
1812  /* not dynamic, no name, check if the addr matches */
1813  } else if (!name && sin) {
1814  if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1815  (g->addr.sin_port != sin->sin_port)) {
1816  if(!g->next)
1817  g = find_realtime_gw(name, at, sin);
1818  else
1819  g = g->next;
1820  continue;
1821  }
1822  } else {
1823  continue;
1824  }
1825  for (p = g->endpoints; p; p = p->next) {
1826  ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name);
1827  if (msgid) {
1828  sub = p->sub;
1829  found = 1;
1830  break;
1831  } else if (name && !strcasecmp(p->name, tmp)) {
1832  ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
1833  p->name, g->name, p->sub->id);
1834  sub = p->sub;
1835  found = 1;
1836  break;
1837  }
1838  }
1839  if (sub && found) {
1840  ast_mutex_lock(&sub->lock);
1841  break;
1842  }
1843  }
1844  }
1846  if (!sub) {
1847  if (name) {
1848  if (g) {
1849  ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
1850  } else {
1851  ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
1852  }
1853  }
1854  }
1855  return sub;
1856 }
1857 
1858 static void parse(struct mgcp_request *req)
1859 {
1860  /* Divide fields by NULL's */
1861  char *c;
1862  int f = 0;
1863  c = req->data;
1864 
1865  /* First header starts immediately */
1866  req->header[f] = c;
1867  for (; *c; c++) {
1868  if (*c == '\n') {
1869  /* We've got a new header */
1870  *c = 0;
1871  ast_debug(3, "Header: %s (%d)\n", req->header[f], (int) strlen(req->header[f]));
1872  if (ast_strlen_zero(req->header[f])) {
1873  /* Line by itself means we're now in content */
1874  c++;
1875  break;
1876  }
1877  if (f >= MGCP_MAX_HEADERS - 1) {
1878  ast_log(LOG_WARNING, "Too many MGCP headers...\n");
1879  } else {
1880  f++;
1881  }
1882  req->header[f] = c + 1;
1883  } else if (*c == '\r') {
1884  /* Ignore but eliminate \r's */
1885  *c = 0;
1886  }
1887  }
1888  /* Check for last header */
1889  if (!ast_strlen_zero(req->header[f])) {
1890  f++;
1891  }
1892  req->headers = f;
1893  /* Now we process any mime content */
1894  f = 0;
1895  req->line[f] = c;
1896  for (; *c; c++) {
1897  if (*c == '\n') {
1898  /* We've got a new line */
1899  *c = 0;
1900  ast_debug(3, "Line: %s (%d)\n", req->line[f], (int) strlen(req->line[f]));
1901  if (f >= MGCP_MAX_LINES - 1) {
1902  ast_log(LOG_WARNING, "Too many SDP lines...\n");
1903  } else {
1904  f++;
1905  }
1906  req->line[f] = c + 1;
1907  } else if (*c == '\r') {
1908  /* Ignore and eliminate \r's */
1909  *c = 0;
1910  }
1911  }
1912  /* Check for last line */
1913  if (!ast_strlen_zero(req->line[f])) {
1914  f++;
1915  }
1916  req->lines = f;
1917  /* Parse up the initial header */
1918  c = req->header[0];
1919  while (*c && *c < 33) c++;
1920  /* First the verb */
1921  req->verb = c;
1922  while (*c && (*c > 32)) c++;
1923  if (*c) {
1924  *c = '\0';
1925  c++;
1926  while (*c && (*c < 33)) c++;
1927  req->identifier = c;
1928  while (*c && (*c > 32)) c++;
1929  if (*c) {
1930  *c = '\0';
1931  c++;
1932  while (*c && (*c < 33)) c++;
1933  req->endpoint = c;
1934  while (*c && (*c > 32)) c++;
1935  if (*c) {
1936  *c = '\0';
1937  c++;
1938  while (*c && (*c < 33)) c++;
1939  req->version = c;
1940  while (*c && (*c > 32)) c++;
1941  while (*c && (*c < 33)) c++;
1942  while (*c && (*c > 32)) c++;
1943  *c = '\0';
1944  }
1945  }
1946  }
1947 
1948  ast_debug(1, "Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
1949  req->verb, req->identifier, req->endpoint, req->version);
1950  ast_debug(1, "%d headers, %d lines\n", req->headers, req->lines);
1951  if (*c) {
1952  ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
1953  }
1954 }
1955 
1956 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
1957 {
1958  char *m;
1959  char *c;
1960  char *a;
1961  char host[258];
1962  int len = 0;
1963  int portno;
1964  format_t peercapability;
1965  int peerNonCodecCapability;
1966  struct sockaddr_in sin;
1967  struct ast_sockaddr sin_tmp;
1968  char *codecs;
1969  struct ast_hostent ahp; struct hostent *hp;
1970  int codec, codec_count=0;
1971  int iterator;
1972  struct mgcp_endpoint *p = sub->parent;
1973  char tmp1[256], tmp2[256], tmp3[256];
1974 
1975  /* Get codec and RTP info from SDP */
1976  m = get_sdp(req, "m");
1977  c = get_sdp(req, "c");
1978  if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
1979  ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
1980  return -1;
1981  }
1982  if (sscanf(c, "IN IP4 %256s", host) != 1) {
1983  ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
1984  return -1;
1985  }
1986  /* XXX This could block for a long time, and block the main thread! XXX */
1987  hp = ast_gethostbyname(host, &ahp);
1988  if (!hp) {
1989  ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
1990  return -1;
1991  }
1992  if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1 || !len) {
1993  ast_log(LOG_WARNING, "Malformed media stream descriptor: %s\n", m);
1994  return -1;
1995  }
1996  sin.sin_family = AF_INET;
1997  memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
1998  sin.sin_port = htons(portno);
1999  ast_sockaddr_from_sin(&sin_tmp, &sin);
2000  ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2001  ast_debug(3, "Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
2002  /* Scan through the RTP payload types specified in a "m=" line: */
2004  codecs = ast_strdupa(m + len);
2005  while (!ast_strlen_zero(codecs)) {
2006  if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
2007  if (codec_count) {
2008  break;
2009  }
2010  ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
2011  return -1;
2012  }
2014  codec_count++;
2015  codecs += len;
2016  }
2017 
2018  /* Next, scan through each "a=rtpmap:" line, noting each */
2019  /* specified RTP payload type (with corresponding MIME subtype): */
2020  sdpLineNum_iterator_init(&iterator);
2021  while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
2022  char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
2023  if (sscanf(a, "rtpmap: %30d %127[^/]/", &codec, mimeSubtype) != 2)
2024  continue;
2025  /* Note: should really look at the 'freq' and '#chans' params too */
2026  ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0);
2027  }
2028 
2029  /* Now gather all of the codecs that were asked for: */
2030  ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), &peercapability, &peerNonCodecCapability);
2031  p->capability = capability & peercapability;
2032  ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n",
2033  ast_getformatname_multiple(tmp1, sizeof(tmp1), capability),
2034  ast_getformatname_multiple(tmp2, sizeof(tmp2), peercapability),
2035  ast_getformatname_multiple(tmp3, sizeof(tmp3), p->capability));
2036  ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n",
2037  nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
2038  if (!p->capability) {
2039  ast_log(LOG_WARNING, "No compatible codecs!\n");
2040  return -1;
2041  }
2042  return 0;
2043 }
2044 
2045 static int add_header(struct mgcp_request *req, const char *var, const char *value)
2046 {
2047  if (req->len >= sizeof(req->data) - 4) {
2048  ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
2049  return -1;
2050  }
2051  if (req->lines) {
2052  ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
2053  return -1;
2054  }
2055  req->header[req->headers] = req->data + req->len;
2056  snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
2057  req->len += strlen(req->header[req->headers]);
2058  if (req->headers < MGCP_MAX_HEADERS) {
2059  req->headers++;
2060  } else {
2061  ast_log(LOG_WARNING, "Out of header space\n");
2062  return -1;
2063  }
2064  return 0;
2065 }
2066 
2067 static int add_line(struct mgcp_request *req, char *line)
2068 {
2069  if (req->len >= sizeof(req->data) - 4) {
2070  ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
2071  return -1;
2072  }
2073  if (!req->lines) {
2074  /* Add extra empty return */
2075  ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
2076  req->len += strlen(req->data + req->len);
2077  }
2078  req->line[req->lines] = req->data + req->len;
2079  snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
2080  req->len += strlen(req->line[req->lines]);
2081  if (req->lines < MGCP_MAX_LINES) {
2082  req->lines++;
2083  } else {
2084  ast_log(LOG_WARNING, "Out of line space\n");
2085  return -1;
2086  }
2087  return 0;
2088 }
2089 
2090 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
2091 {
2092  /* Initialize a response */
2093  if (req->headers || req->len) {
2094  ast_log(LOG_WARNING, "Request already initialized?!?\n");
2095  return -1;
2096  }
2097  req->header[req->headers] = req->data + req->len;
2098  snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
2099  req->len += strlen(req->header[req->headers]);
2100  if (req->headers < MGCP_MAX_HEADERS) {
2101  req->headers++;
2102  } else {
2103  ast_log(LOG_WARNING, "Out of header space\n");
2104  }
2105  return 0;
2106 }
2107 
2108 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb, unsigned int oseq)
2109 {
2110  /* Initialize a response */
2111  if (req->headers || req->len) {
2112  ast_log(LOG_WARNING, "Request already initialized?!?\n");
2113  return -1;
2114  }
2115  req->header[req->headers] = req->data + req->len;
2116  /* check if we need brackets around the gw name */
2117  if (p->parent->isnamedottedip) {
2118  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" : "");
2119  } else {
2120 + 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" : "");
2121  }
2122  req->len += strlen(req->header[req->headers]);
2123  if (req->headers < MGCP_MAX_HEADERS) {
2124  req->headers++;
2125  } else {
2126  ast_log(LOG_WARNING, "Out of header space\n");
2127  }
2128  return 0;
2129 }
2130 
2131 
2132 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
2133 {
2134  memset(resp, 0, sizeof(*resp));
2135  init_resp(resp, msg, req, msgrest);
2136  return 0;
2137 }
2138 
2139 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
2140 {
2141  unsigned int oseq;
2142  memset(req, 0, sizeof(struct mgcp_request));
2144  oseq_global++;
2145  if (oseq_global > 999999999) {
2146  oseq_global = 1;
2147  }
2148  oseq = oseq_global;
2150  init_req(p, req, verb, oseq);
2151  return oseq;
2152 }
2153 
2154 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
2155 {
2156  struct mgcp_request resp;
2157  struct mgcp_endpoint *p = sub->parent;
2158  struct mgcp_response *mgr;
2159 
2160  if (!sub) {
2161  return -1;
2162  }
2163 
2164  respprep(&resp, p, msg, req, msgrest);
2165  if (!(mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1))) {
2166  return send_response(sub, &resp);
2167  }
2168  /* Store MGCP response in case we have to retransmit */
2169  sscanf(req->identifier, "%30d", &mgr->seqno);
2170  time(&mgr->whensent);
2171  mgr->len = resp.len;
2172  memcpy(mgr->buf, resp.data, resp.len);
2173  mgr->buf[resp.len] = '\0';
2174  mgr->next = p->parent->responses;
2175  p->parent->responses = mgr;
2176 
2177  return send_response(sub, &resp);
2178 }
2179 
2180 
2181 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
2182 {
2183  int len;
2184  int codec;
2185  char costr[80];
2186  struct sockaddr_in sin;
2187  struct ast_sockaddr sin_tmp;
2188  char v[256];
2189  char s[256];
2190  char o[256];
2191  char c[256];
2192  char t[256];
2193  char m[256] = "";
2194  char a[1024] = "";
2195  format_t x;
2196  struct sockaddr_in dest = { 0, };
2197  struct ast_sockaddr dest_tmp;
2198  struct mgcp_endpoint *p = sub->parent;
2199  /* XXX We break with the "recommendation" and send our IP, in order that our
2200  peer doesn't have to ast_gethostbyname() us XXX */
2201  len = 0;
2202  if (!sub->rtp) {
2203  ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
2204  return -1;
2205  }
2206  ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp);
2207  ast_sockaddr_to_sin(&sin_tmp, &sin);
2208  if (rtp) {
2209  ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp);
2210  ast_sockaddr_to_sin(&dest_tmp, &dest);
2211  } else {
2212  if (sub->tmpdest.sin_addr.s_addr) {
2213  dest.sin_addr = sub->tmpdest.sin_addr;
2214  dest.sin_port = sub->tmpdest.sin_port;
2215  /* Reset temporary destination */
2216  memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
2217  } else {
2218  dest.sin_addr = p->parent->ourip;
2219  dest.sin_port = sin.sin_port;
2220  }
2221  }
2222  ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
2223  ast_copy_string(v, "v=0\r\n", sizeof(v));
2224  snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
2225  ast_copy_string(s, "s=session\r\n", sizeof(s));
2226  snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
2227  ast_copy_string(t, "t=0 0\r\n", sizeof(t));
2228  snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
2229  for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
2230  if (!(x & AST_FORMAT_AUDIO_MASK)) {
2231  /* Audio is now discontiguous */
2232  continue;
2233  }
2234  if (p->capability & x) {
2235  ast_debug(1, "Answering with capability %s\n", ast_getformatname(x));
2237  if (codec > -1) {
2238  snprintf(costr, sizeof(costr), " %d", codec);
2239  strncat(m, costr, sizeof(m) - strlen(m) - 1);
2240  snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, x, 0));
2241  strncat(a, costr, sizeof(a) - strlen(a) - 1);
2242  }
2243  }
2244  }
2245  for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
2246  if (p->nonCodecCapability & x) {
2247  ast_debug(1, "Answering with non-codec capability %d\n", (int) x);
2249  if (codec > -1) {
2250  snprintf(costr, sizeof(costr), " %d", codec);
2251  strncat(m, costr, sizeof(m) - strlen(m) - 1);
2252  snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, x, 0));
2253  strncat(a, costr, sizeof(a) - strlen(a) - 1);
2254  if (x == AST_RTP_DTMF) {
2255  /* Indicate we support DTMF... Not sure about 16,
2256  but MSN supports it so dang it, we will too... */
2257  snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
2258  strncat(a, costr, sizeof(a) - strlen(a) - 1);
2259  }
2260  }
2261  }
2262  }
2263  strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
2264  len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
2265  snprintf(costr, sizeof(costr), "%d", len);
2266  add_line(resp, v);
2267  add_line(resp, o);
2268  add_line(resp, s);
2269  add_line(resp, c);
2270  add_line(resp, t);
2271  add_line(resp, m);
2272  add_line(resp, a);
2273  return 0;
2274 }
2275 
2277 {
2278  struct mgcp_request resp;
2279  char local[256];
2280  char tmp[80];
2281  struct mgcp_endpoint *p = sub->parent;
2282  format_t x;
2283  struct ast_sockaddr sub_tmpdest_tmp;
2284  unsigned int oseq;
2285 
2286  if (ast_strlen_zero(sub->cxident) && rtp) {
2287  /* We don't have a CXident yet, store the destination and
2288  wait a bit */
2289  ast_rtp_instance_get_remote_address(rtp, &sub_tmpdest_tmp);
2290  ast_sockaddr_to_sin(&sub_tmpdest_tmp, &sub->tmpdest);
2291  return 0;
2292  }
2293  ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
2294  for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
2295  if (!(x & AST_FORMAT_AUDIO_MASK)) {
2296  /* No longer contiguous */
2297  continue;
2298  }
2299  if (p->capability & x) {
2300  snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
2301  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2302  }
2303  }
2304 
2305  if (sub->gate) {
2306  if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
2307  snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
2308  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2309  sub->sdpsent = 1;
2310  } else {
2311  /* oops wait */
2312  ast_debug(1, "Waiting for opened gate...\n");
2313  sub->sdpsent = 0;
2314  return 0;
2315  }
2316  }
2317 
2318 
2319  oseq = reqprep(&resp, p, "MDCX");
2320  add_header(&resp, "C", sub->callid);
2321  add_header(&resp, "L", local);
2322  add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2323  /* X header should not be sent. kept for compatibility */
2324  add_header(&resp, "X", sub->txident);
2325  add_header(&resp, "I", sub->cxident);
2326  /*add_header(&resp, "S", "");*/
2327  add_sdp(&resp, sub, rtp);
2328  /* fill in new fields */
2329  resp.cmd = MGCP_CMD_MDCX;
2330  resp.trid = oseq;
2331  return send_request(p, sub, &resp, oseq);
2332 }
2333 
2334 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
2335 {
2336  struct mgcp_request resp;
2337  char local[256];
2338  char tmp[80];
2339  int x;
2340  struct mgcp_endpoint *p = sub->parent;
2341  unsigned int oseq;
2342 
2343  ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
2344  p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2345 
2346  ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
2347 
2348  for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
2349  if (!(x & AST_FORMAT_AUDIO_MASK)) {
2350  /* No longer contiguous */
2351  continue;
2352  }
2353  if (p->capability & x) {
2354  snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
2355  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2356  }
2357  }
2358 
2359  if (sub->gate) {
2360  if(sub->gate->state == GATE_ALLOCATED) {
2361  snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
2362  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2363  }
2364  }
2365  sub->sdpsent = 1;
2366  oseq = reqprep(&resp, p, "CRCX");
2367  add_header(&resp, "C", sub->callid);
2368  add_header(&resp, "L", local);
2369  add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2370  /* X header should not be sent. kept for compatibility */
2371  add_header(&resp, "X", sub->txident);
2372  /*add_header(&resp, "S", "");*/
2373  add_sdp(&resp, sub, rtp);
2374  /* fill in new fields */
2375  resp.cmd = MGCP_CMD_CRCX;
2376  resp.trid = oseq;
2377  return send_request(p, sub, &resp, oseq);
2378 }
2379 
2380 static int mgcp_pktcgate_remove(struct cops_gate *gate)
2381 {
2382  struct mgcp_subchannel *sub = gate->tech_pvt;
2383 
2384  if (!sub) {
2385  return 1;
2386  }
2387 
2388  ast_mutex_lock(&sub->lock);
2389  ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid);
2390  if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) {
2391  sub->gate = NULL;
2392  if (sub->owner) {
2394  ast_channel_unlock(sub->owner);
2395  }
2396  } else {
2397  sub->gate = NULL;
2398  }
2399  ast_mutex_unlock(&sub->lock);
2400  return 1;
2401 }
2402 
2403 static int mgcp_pktcgate_open(struct cops_gate *gate)
2404 {
2405  struct mgcp_subchannel *sub = gate->tech_pvt;
2406  if (!sub) {
2407  return 1;
2408  }
2409  ast_mutex_lock(&sub->lock);
2410  ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid);
2411  if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0);
2412  ast_mutex_unlock(&sub->lock);
2413  return 1;
2414 }
2415 
2416 static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub)
2417 {
2418  struct mgcp_endpoint *p = sub->parent;
2419  sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr),
2420  8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove);
2421 
2422  if (!sub->gate) {
2423  return 0;
2424  }
2425  sub->gate->tech_pvt = sub;
2427  return 1;
2428 }
2429 
2431 {
2432  struct mgcp_request resp;
2433  char local[256];
2434  char tmp[80];
2435  format_t x;
2436  struct mgcp_endpoint *p = sub->parent;
2437  unsigned int oseq;
2438 
2439  ast_copy_string(local, "p:20, s:off, e:on", sizeof(local));
2440 
2441  for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
2442  if (p->capability & x) {
2443  snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
2444  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2445  }
2446  }
2447 
2448  ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
2449  p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2450  sub->sdpsent = 0;
2451  oseq = reqprep(&resp, p, "CRCX");
2452  add_header(&resp, "C", sub->callid);
2453  add_header(&resp, "L", local);
2454  add_header(&resp, "M", "inactive");
2455  /* X header should not be sent. kept for compatibility */
2456  add_header(&resp, "X", sub->txident);
2457  /*add_header(&resp, "S", "");*/
2458  /* fill in new fields */
2459  resp.cmd = MGCP_CMD_CRCX;
2460  resp.trid = oseq;
2461  return send_request(p, sub, &resp, oseq);
2462 }
2463 
2464 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
2465 {
2466  struct mgcp_request resp;
2467  struct mgcp_endpoint *p = sub->parent;
2468  unsigned int oseq;
2469 
2470  ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2471  tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2472  ast_copy_string(p->curtone, tone, sizeof(p->curtone));
2473  oseq = reqprep(&resp, p, "RQNT");
2474  add_header(&resp, "X", p->rqnt_ident);
2475  switch (p->hookstate) {
2476  case MGCP_ONHOOK:
2477  add_header(&resp, "R", "L/hd(N)");
2478  break;
2479  case MGCP_OFFHOOK:
2480  add_header_offhook(sub, &resp, tone);
2481  break;
2482  }
2483  if (!ast_strlen_zero(tone)) {
2484  add_header(&resp, "S", tone);
2485  }
2486  /* fill in new fields */
2487  resp.cmd = MGCP_CMD_RQNT;
2488  resp.trid = oseq;
2489  return send_request(p, NULL, &resp, oseq);
2490 }
2491 
2492 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
2493 {
2494  struct mgcp_request resp;
2495  char tone2[256];
2496  char *l, *n;
2497  struct timeval t = ast_tvnow();
2498  struct ast_tm tm;
2499  struct mgcp_endpoint *p = sub->parent;
2500  unsigned int oseq;
2501 
2502  ast_localtime(&t, &tm, NULL);
2503  n = callername;
2504  l = callernum;
2505  if (!n)
2506  n = "";
2507  if (!l)
2508  l = "";
2509 
2510  /* Keep track of last callerid for blacklist and callreturn */
2511  ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
2512 
2513  snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
2514  tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
2515  ast_copy_string(p->curtone, tone, sizeof(p->curtone));
2516  oseq = reqprep(&resp, p, "RQNT");
2517  add_header(&resp, "X", p->rqnt_ident);
2518  switch (p->hookstate) {
2519  case MGCP_ONHOOK:
2520  add_header(&resp, "R", "L/hd(N)");
2521  break;
2522  case MGCP_OFFHOOK:
2523  add_header_offhook(sub, &resp, tone);
2524  break;
2525  }
2526  if (!ast_strlen_zero(tone2)) {
2527  add_header(&resp, "S", tone2);
2528  }
2529  ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2530  tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2531  /* fill in new fields */
2532  resp.cmd = MGCP_CMD_RQNT;
2533  resp.trid = oseq;
2534  return send_request(p, NULL, &resp, oseq);
2535 }
2536 
2538 {
2539  struct mgcp_request resp;
2540  struct mgcp_endpoint *p = sub->parent;
2541  format_t x;
2542  int fc = 1;
2543  char local[256];
2544  char tmp[80];
2545  unsigned int oseq;
2546 
2547  if (ast_strlen_zero(sub->cxident)) {
2548  /* We don't have a CXident yet, store the destination and
2549  wait a bit */
2550  return 0;
2551  }
2552  ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n",
2553  p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2554 
2555  ast_copy_string(local, "", sizeof(local));
2556  for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
2557  if (p->capability & x) {
2558  if (p->ncs && !fc) {
2559  p->capability = x; /* sb5120e bug */
2560  break;
2561  } else {
2562  fc = 0;
2563  snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
2564  }
2565  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2566  }
2567  }
2568 
2569  if (!sub->sdpsent) {
2570  if (sub->gate) {
2571  if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
2572  snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
2573  strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2574  } else {
2575  /* we still don't have gateid wait */
2576  return 0;
2577  }
2578  }
2579  }
2580 
2581  oseq = reqprep(&resp, p, "MDCX");
2582  add_header(&resp, "C", sub->callid);
2583  if (!sub->sdpsent) {
2584  add_header(&resp, "L", local);
2585  }
2586  add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2587  /* X header should not be sent. kept for compatibility */
2588  add_header(&resp, "X", sub->txident);
2589  add_header(&resp, "I", sub->cxident);
2590  switch (sub->parent->hookstate) {
2591  case MGCP_ONHOOK:
2592  add_header(&resp, "R", "L/hd(N)");
2593  break;
2594  case MGCP_OFFHOOK:
2595  add_header_offhook(sub, &resp, "");
2596  break;
2597  }
2598  if (!sub->sdpsent) {
2599  add_sdp(&resp, sub, NULL);
2600  sub->sdpsent = 1;
2601  }
2602  /* fill in new fields */
2603  resp.cmd = MGCP_CMD_MDCX;
2604  resp.trid = oseq;
2605  return send_request(p, sub, &resp, oseq);
2606 }
2607 
2608 
2609 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone)
2610 {
2611  struct mgcp_endpoint *p = sub->parent;
2612  char tone_indicate_end = 0;
2613 
2614  /* We also should check the tone to indicate, because it have no sense
2615  to request notify D/[0-9#*] (dtmf keys) if we are sending congestion
2616  tone for example G/cg */
2617  if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) {
2618  tone_indicate_end = 1;
2619  }
2620 
2621  if (p && p->sub && p->sub->owner &&
2622  p->sub->owner->_state >= AST_STATE_RINGING &&
2624  add_header(resp, "R", "L/hu(N),L/hf(N)");
2625 
2626  } else if (!tone_indicate_end){
2627  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)"));
2628  } else {
2629  ast_debug(1, "We don't want more digits if we will end the call\n");
2630  add_header(resp, "R", "L/hu(N),L/hf(N)");
2631  }
2632 }
2633 
2634 
2635 
2636 
2638 {
2639  struct mgcp_request resp;
2640  unsigned int oseq;
2641  oseq = reqprep(&resp, p, "AUEP");
2642  /* removed unknown param VS */
2643  /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
2644  add_header(&resp, "F", "A");
2645  /* fill in new fields */
2646  resp.cmd = MGCP_CMD_AUEP;
2647  resp.trid = oseq;
2648  return send_request(p, NULL, &resp, oseq);
2649 }
2650 
2652 {
2653  struct mgcp_endpoint *p = sub->parent;
2654  struct mgcp_request resp;
2655  unsigned int oseq;
2656 
2657  ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
2658  sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2659  oseq = reqprep(&resp, p, "DLCX");
2660  /* check if call id is avail */
2661  if (sub->callid[0])
2662  add_header(&resp, "C", sub->callid);
2663  /* X header should not be sent. kept for compatibility */
2664  add_header(&resp, "X", sub->txident);
2665  /* check if cxident is avail */
2666  if (sub->cxident[0])
2667  add_header(&resp, "I", sub->cxident);
2668  /* fill in new fields */
2669  resp.cmd = MGCP_CMD_DLCX;
2670  resp.trid = oseq;
2671  return send_request(p, sub, &resp, oseq);
2672 }
2673 
2674 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
2675 {
2676  struct mgcp_request resp;
2677  unsigned int oseq;
2678 
2679  ast_debug(3, "Delete connection %s %s@%s on callid: %s\n",
2680  cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
2681  oseq = reqprep(&resp, p, "DLCX");
2682  /* check if call id is avail */
2683  if (callid && *callid)
2684  add_header(&resp, "C", callid);
2685  /* check if cxident is avail */
2686  if (cxident && *cxident)
2687  add_header(&resp, "I", cxident);
2688  /* fill in new fields */
2689  resp.cmd = MGCP_CMD_DLCX;
2690  resp.trid = oseq;
2691  return send_request(p, p->sub, &resp, oseq);
2692 }
2693 
2694 /*! \brief dump_cmd_queues: (SC:) cleanup pending commands */
2695 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
2696 {
2697  struct mgcp_request *t, *q;
2698 
2699  if (p) {
2701  for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
2702  p->rqnt_queue = NULL;
2704 
2706  for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
2707  p->cmd_queue = NULL;
2709 
2711  for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
2712  p->sub->cx_queue = NULL;
2714 
2716  for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
2717  p->sub->next->cx_queue = NULL;
2719  } else if (sub) {
2721  for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
2722  sub->cx_queue = NULL;
2724  }
2725 }
2726 
2727 
2728 /*! \brief find_command: (SC:) remove command transaction from queue */
2729 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2730  struct mgcp_request **queue, ast_mutex_t *l, int ident)
2731 {
2732  struct mgcp_request *prev, *req;
2733 
2734  ast_mutex_lock(l);
2735  for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
2736  if (req->trid == ident) {
2737  /* remove from queue */
2738  if (!prev)
2739  *queue = req->next;
2740  else
2741  prev->next = req->next;
2742 
2743  /* send next pending command */
2744  if (*queue) {
2745  ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
2746  ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
2747 
2748  mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
2749  }
2750  break;
2751  }
2752  }
2753  ast_mutex_unlock(l);
2754  return req;
2755 }
2756 
2757 /* modified for new transport mechanism */
2758 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2759  int result, unsigned int ident, struct mgcp_request *resp)
2760 {
2761  char *c;
2762  struct mgcp_request *req;
2763  struct mgcp_gateway *gw = p->parent;
2764 
2765  if (result < 200) {
2766  /* provisional response */
2767  return;
2768  }
2769 
2770  if (p->slowsequence)
2771  req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2772  else if (sub)
2773  req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
2774  else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
2775  req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2776 
2777  if (!req) {
2778  ast_verb(3, "No command found on [%s] for transaction %u. Ignoring...\n",
2779  gw->name, ident);
2780  return;
2781  }
2782 
2783  if (p && (result >= 400) && (result <= 599)) {
2784  switch (result) {
2785  case 401:
2786  p->hookstate = MGCP_OFFHOOK;
2787  break;
2788  case 402:
2789  p->hookstate = MGCP_ONHOOK;
2790  break;
2791  case 406:
2792  ast_log(LOG_NOTICE, "Transaction %u timed out\n", ident);
2793  break;
2794  case 407:
2795  ast_log(LOG_NOTICE, "Transaction %u aborted\n", ident);
2796  break;
2797  }
2798  if (sub) {
2799  if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) {
2800  ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result);
2802  }
2803  if (sub->owner) {
2804  ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2805  result, p->name, p->parent->name, sub ? sub->id:-1);
2806  mgcp_queue_hangup(sub);
2807  }
2808  } else {
2809  if (p->sub->next->owner) {
2810  ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2811  result, p->name, p->parent->name, sub ? sub->id:-1);
2812  mgcp_queue_hangup(p->sub);
2813  }
2814 
2815  if (p->sub->owner) {
2816  ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2817  result, p->name, p->parent->name, sub ? sub->id:-1);
2818  mgcp_queue_hangup(p->sub);
2819  }
2820 
2821  dump_cmd_queues(p, NULL);
2822  }
2823  }
2824 
2825  if (resp) {
2826  /* responseAck: */
2827  if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) {
2828  if (sub) {
2829  transmit_response(sub, "000", resp, "OK");
2830  if (sub->owner && sub->owner->_state == AST_STATE_RINGING) {
2832  }
2833  }
2834  }
2835  if (req->cmd == MGCP_CMD_CRCX) {
2836  if ((c = get_header(resp, "I"))) {
2837  if (!ast_strlen_zero(c) && sub) {
2838  /* if we are hanging up do not process this conn. */
2839  if (sub->owner) {
2840  if (!ast_strlen_zero(sub->cxident)) {
2841  if (strcasecmp(c, sub->cxident)) {
2842  ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
2843  }
2844  }
2845  ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
2846  if (sub->tmpdest.sin_addr.s_addr) {
2847  transmit_modify_with_sdp(sub, NULL, 0);
2848  }
2849  } else {
2850  /* XXX delete this one
2851  callid and conn id may already be lost.
2852  so the following del conn may have a side effect of
2853  cleaning up the next subchannel */
2855  }
2856  }
2857  }
2858  }
2859 
2860  if (req->cmd == MGCP_CMD_AUEP) {
2861  /* check stale connection ids */
2862  if ((c = get_header(resp, "I"))) {
2863  char *v, *n;
2864  int len;
2865  while ((v = get_csv(c, &len, &n))) {
2866  if (len) {
2867  if (strncasecmp(v, p->sub->cxident, len) &&
2868  strncasecmp(v, p->sub->next->cxident, len)) {
2869  /* connection id not found. delete it */
2870  char cxident[80] = "";
2871 
2872  if (len > (sizeof(cxident) - 1))
2873  len = sizeof(cxident) - 1;
2874  ast_copy_string(cxident, v, len);
2875  ast_verb(3, "Non existing connection id %s on %s@%s \n",
2876  cxident, p->name, gw->name);
2877  transmit_connection_del_w_params(p, NULL, cxident);
2878  }
2879  }
2880  c = n;
2881  }
2882  }
2883 
2884  /* Try to determine the hookstate returned from an audit endpoint command */
2885  if ((c = get_header(resp, "ES"))) {
2886  if (!ast_strlen_zero(c)) {
2887  if (strstr(c, "hu")) {
2888  if (p->hookstate != MGCP_ONHOOK) {
2889  /* XXX cleanup if we think we are offhook XXX */
2890  if ((p->sub->owner || p->sub->next->owner ) &&
2891  p->hookstate == MGCP_OFFHOOK)
2892  mgcp_queue_hangup(sub);
2893  p->hookstate = MGCP_ONHOOK;
2894 
2895  /* update the requested events according to the new hookstate */
2896  transmit_notify_request(p->sub, "");
2897 
2898  ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
2899  }
2900  } else if (strstr(c, "hd")) {
2901  if (p->hookstate != MGCP_OFFHOOK) {
2902  p->hookstate = MGCP_OFFHOOK;
2903 
2904  /* update the requested events according to the new hookstate */
2905  transmit_notify_request(p->sub, "");
2906 
2907  ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
2908  }
2909  }
2910  }
2911  }
2912  }
2913 
2914  if (resp && resp->lines) {
2915  /* do not process sdp if we are hanging up. this may be a late response */
2916  if (sub && sub->owner) {
2917  if (!sub->rtp)
2918  start_rtp(sub);
2919  if (sub->rtp)
2920  process_sdp(sub, resp);
2921  }
2922  }
2923  }
2924 
2925  ast_free(req);
2926 }
2927 
2928 static void start_rtp(struct mgcp_subchannel *sub)
2929 {
2930  struct ast_sockaddr bindaddr_tmp;
2931 
2932  ast_mutex_lock(&sub->lock);
2933  /* check again to be on the safe side */
2934  if (sub->rtp) {
2936  sub->rtp = NULL;
2937  }
2938  /* Allocate the RTP now */
2939  ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
2940  sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
2941  if (sub->rtp && sub->owner)
2942  ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
2943  if (sub->rtp) {
2944  ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
2946  }
2947  /* Make a call*ID */
2948  snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", (unsigned long)ast_random(), sub->txident);
2949  /* Transmit the connection create */
2950  if(!sub->parent->pktcgatealloc) {
2951  transmit_connect_with_sdp(sub, NULL);
2952  } else {
2953  transmit_connect(sub);
2954  sub->gate = NULL;
2955  if(!mgcp_alloc_pktcgate(sub))
2956  mgcp_queue_hangup(sub);
2957  }
2958  ast_mutex_unlock(&sub->lock);
2959 }
2960 
2961 static void *mgcp_ss(void *data)
2962 {
2963  struct ast_channel *chan = data;
2964  struct mgcp_subchannel *sub = chan->tech_pvt;
2965  struct mgcp_endpoint *p = sub->parent;
2966  /* char exten[AST_MAX_EXTENSION] = ""; */
2967  int len = 0;
2968  int timeout = firstdigittimeout;
2969  int res= 0;
2970  int getforward = 0;
2971  int loop_pause = 100;
2972 
2973  len = strlen(p->dtmf_buf);
2974 
2975  while (len < AST_MAX_EXTENSION - 1) {
2976  ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name);
2977  res = 1; /* Assume that we will get a digit */
2978  while (strlen(p->dtmf_buf) == len) {
2979  ast_safe_sleep(chan, loop_pause);
2980  timeout -= loop_pause;
2981  if (timeout <= 0){
2982  res = 0;
2983  break;
2984  }
2985  res = 1;
2986  }
2987 
2988  timeout = 0;
2989  len = strlen(p->dtmf_buf);
2990 
2991  if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) {
2992  /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2993  ast_indicate(chan, -1);
2994  } else {
2995  /* XXX Redundant? We should already be playing dialtone */
2996  /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
2997  transmit_notify_request(sub, "L/dl");
2998  }
2999  if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
3000  if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
3001  if (getforward) {
3002  /* Record this as the forwarding extension */
3003  ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward));
3004  ast_verb(3, "Setting call forward to '%s' on channel %s\n",
3005  p->call_forward, chan->name);
3006  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3007  transmit_notify_request(sub, "L/sl");
3008  if (res)
3009  break;
3010  usleep(500000);
3011  /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
3012  ast_indicate(chan, -1);
3013  sleep(1);
3014  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3015  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
3016  transmit_notify_request(sub, "L/dl");
3017  len = 0;
3018  getforward = 0;
3019  } else {
3020  /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
3021  ast_indicate(chan, -1);
3022  ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten));
3023  chan->dialed.number.str = ast_strdup(p->dtmf_buf);
3024  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3025  ast_set_callerid(chan,
3026  p->hidecallerid ? "" : p->cid_num,
3027  p->hidecallerid ? "" : p->cid_name,
3028  chan->caller.ani.number.valid ? NULL : p->cid_num);
3030  /*dahdi_enable_ec(p);*/
3031  if (p->dtmfmode & MGCP_DTMF_HYBRID) {
3032  p->dtmfmode |= MGCP_DTMF_INBAND;
3033  ast_indicate(chan, -1);
3034  }
3035  res = ast_pbx_run(chan);
3036  if (res) {
3037  ast_log(LOG_WARNING, "PBX exited non-zero\n");
3038  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
3039  /*transmit_notify_request(p, "nbz", 1);*/
3040  transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
3041  }
3042  return NULL;
3043  }
3044  } else {
3045  /* It's a match, but they just typed a digit, and there is an ambiguous match,
3046  so just set the timeout to matchdigittimeout and wait some more */
3047  timeout = matchdigittimeout;
3048  }
3049  } else if (res == 0) {
3050  ast_debug(1, "not enough digits (and no ambiguous match)...\n");
3051  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
3052  transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
3053  /*dahdi_wait_event(p->subs[index].zfd);*/
3054  ast_hangup(chan);
3055  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3056  return NULL;
3057  } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) {
3058  ast_verb(3, "Disabling call waiting on %s\n", chan->name);
3059  /* Disable call waiting if enabled */
3060  p->callwaiting = 0;
3061  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3062  transmit_notify_request(sub, "L/sl");
3063  len = 0;
3064  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3065  timeout = firstdigittimeout;
3066  } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) {
3067  /* Scan all channels and see if any there
3068  * ringing channqels with that have call groups
3069  * that equal this channels pickup group
3070  */
3071  if (ast_pickup_call(chan)) {
3072  ast_log(LOG_WARNING, "No call pickup possible...\n");
3073  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
3074  transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
3075  }
3076  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3077  ast_hangup(chan);
3078  return NULL;
3079  } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) {
3080  ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
3081  /* Disable Caller*ID if enabled */
3082  p->hidecallerid = 1;
3083  ast_set_callerid(chan, "", "", NULL);
3084  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3085  transmit_notify_request(sub, "L/sl");
3086  len = 0;
3087  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3088  timeout = firstdigittimeout;
3089  } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) {
3090  res = 0;
3091  if (!ast_strlen_zero(p->lastcallerid)) {
3092  res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
3093  }
3094  if (!res)
3095  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3096  transmit_notify_request(sub, "L/sl");
3097  break;
3098  } else if (!strcmp(p->dtmf_buf, "*78")) {
3099  /* Do not disturb */
3100  ast_verb(3, "Enabled DND on channel %s\n", chan->name);
3101  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3102  transmit_notify_request(sub, "L/sl");
3103  p->dnd = 1;
3104  getforward = 0;
3105  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3106  len = 0;
3107  } else if (!strcmp(p->dtmf_buf, "*79")) {
3108  /* Do not disturb */
3109  ast_verb(3, "Disabled DND on channel %s\n", chan->name);
3110  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3111  transmit_notify_request(sub, "L/sl");
3112  p->dnd = 0;
3113  getforward = 0;
3114  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3115  len = 0;
3116  } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) {
3117  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3118  transmit_notify_request(sub, "L/sl");
3119  getforward = 1;
3120  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3121  len = 0;
3122  } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) {
3123  ast_verb(3, "Cancelling call forwarding on channel %s\n", chan->name);
3124  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3125  transmit_notify_request(sub, "L/sl");
3126  memset(p->call_forward, 0, sizeof(p->call_forward));
3127  getforward = 0;
3128  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3129  len = 0;
3130  } else if (ast_parking_ext_valid(p->dtmf_buf, chan, chan->context) &&
3131  sub->next->owner && ast_bridged_channel(sub->next->owner)) {
3132  /* This is a three way call, the main call being a real channel,
3133  and we're parking the first call. */
3135  p->dtmf_buf, chan->context, 0, NULL);
3136  ast_verb(3, "Parking call to '%s'\n", chan->name);
3137  break;
3138  } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) {
3139  ast_verb(3, "Blacklisting number %s\n", p->lastcallerid);
3140  res = ast_db_put("blacklist", p->lastcallerid, "1");
3141  if (!res) {
3142  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3143  transmit_notify_request(sub, "L/sl");
3144  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3145  len = 0;
3146  }
3147  } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) {
3148  ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
3149  /* Enable Caller*ID if enabled */
3150  p->hidecallerid = 0;
3151  ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
3152  /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
3153  transmit_notify_request(sub, "L/sl");
3154  len = 0;
3155  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3156  timeout = firstdigittimeout;
3157  } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1,
3158  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
3159  && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
3160  ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf,
3161  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
3162  chan->context);
3163  break;
3164  }
3165  if (!timeout)
3166  timeout = gendigittimeout;
3167  if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf))
3168  /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
3169  ast_indicate(chan, -1);
3170  }
3171 #if 0
3172  for (;;) {
3173  res = ast_waitfordigit(chan, to);
3174  if (!res) {
3175  ast_debug(1, "Timeout...\n");
3176  break;
3177  }
3178  if (res < 0) {
3179  ast_debug(1, "Got hangup...\n");
3180  ast_hangup(chan);
3181  break;
3182  }
3183  exten[pos++] = res;
3184  if (!ast_ignore_pattern(chan->context, exten))
3185  ast_indicate(chan, -1);
3186  if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
3187  if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
3188  to = 3000;
3189  else
3190  to = 8000;
3191  } else
3192  break;
3193  }
3194  if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
3195  ast_copy_string(chan->exten, exten, sizeof(chan->exten)1);
3196  if (!p->rtp) {
3197  start_rtp(p);
3198  }
3200  chan->rings = 1;
3201  if (ast_pbx_run(chan)) {
3202  ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
3203  } else {
3204  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3205  return NULL;
3206  }
3207  }
3208 #endif
3209  ast_hangup(chan);
3210  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3211  return NULL;
3212 }
3213 
3214 static int attempt_transfer(struct mgcp_endpoint *p)
3215 {
3216  /* *************************
3217  * I hope this works.
3218  * Copied out of chan_zap
3219  * Cross your fingers
3220  * *************************/
3221 
3222  /* In order to transfer, we need at least one of the channels to
3223  actually be in a call bridge. We can't conference two applications
3224  together (but then, why would we want to?) */
3225  if (ast_bridged_channel(p->sub->owner)) {
3226  /* The three-way person we're about to transfer to could still be in MOH, so
3227  stop if now if appropriate */
3228  if (ast_bridged_channel(p->sub->next->owner))
3230  if (p->sub->owner->_state == AST_STATE_RINGING) {
3232  }
3234  ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3236  return -1;
3237  }
3238  /* Orphan the channel */
3239  unalloc_sub(p->sub->next);
3240  } else if (ast_bridged_channel(p->sub->next->owner)) {
3241  if (p->sub->owner->_state == AST_STATE_RINGING) {
3243  }
3246  ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3248  return -1;
3249  }
3250  /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
3251  ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
3252  p->sub = p->sub->next;
3253  unalloc_sub(p->sub->next);
3254  /* Tell the caller not to hangup */
3255  return 1;
3256  } else {
3257  ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3258  p->sub->owner->name, p->sub->next->owner->name);
3260  if (p->sub->next->owner) {
3261  p->sub->next->alreadygone = 1;
3262  mgcp_queue_hangup(p->sub->next);
3263  }
3264  }
3265  return 0;
3266 }
3267 
3268 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
3269 {
3270  struct mgcp_endpoint *p = sub->parent;
3271  struct ast_channel *c;
3272  pthread_t t;
3273 
3274  /* Off hook / answer */
3275  if (sub->outgoing) {
3276  /* Answered */
3277  if (sub->owner) {
3278  if (ast_bridged_channel(sub->owner))
3280  sub->cxmode = MGCP_CX_SENDRECV;
3281  if (!sub->rtp) {
3282  start_rtp(sub);
3283  } else {
3285  }
3286  /*transmit_notify_request(sub, "aw");*/
3287  transmit_notify_request(sub, "");
3289  }
3290  } else {
3291  /* Start switch */
3292  /*sub->cxmode = MGCP_CX_SENDRECV;*/
3293  if (!sub->owner) {
3294  if (!sub->rtp) {
3295  start_rtp(sub);
3296  } else {
3298  }
3299  if (p->immediate) {
3300  /* The channel is immediately up. Start right away */
3301 #ifdef DLINK_BUGGY_FIRMWARE
3302  transmit_notify_request(sub, "rt");
3303 #else
3304  transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt");
3305 #endif
3306  c = mgcp_new(sub, AST_STATE_RING, NULL);
3307  if (!c) {
3308  ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
3309  transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
3310  ast_hangup(c);
3311  }
3312  } else {
3313  if (has_voicemail(p)) {
3314  transmit_notify_request(sub, "L/sl");
3315  } else {
3316  transmit_notify_request(sub, "L/dl");
3317  }
3318  c = mgcp_new(sub, AST_STATE_DOWN, NULL);
3319  if (c) {
3320  if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) {
3321  ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
3322  ast_hangup(c);
3323  }
3324  } else {
3325  ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
3326  }
3327  }
3328  } else {
3329  if (p->hookstate == MGCP_OFFHOOK) {
3330  ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
3331  } else {
3332  ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
3333  ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
3334  }
3335  if (ast_bridged_channel(sub->owner))
3337  sub->cxmode = MGCP_CX_SENDRECV;
3338  if (!sub->rtp) {
3339  start_rtp(sub);
3340  } else {
3342  }
3343  /*transmit_notify_request(sub, "aw");*/
3344  transmit_notify_request(sub, "");
3345  /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
3346  }
3347  }
3348 }
3349 
3350 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
3351 {
3352  char *ev, *s;
3353  struct ast_frame f = { 0, };
3354  struct mgcp_endpoint *p = sub->parent;
3355  struct mgcp_gateway *g = NULL;
3356  int res;
3357 
3358  ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
3359  /* Clear out potential response */
3360  if (!strcasecmp(req->verb, "RSIP")) {
3361  /* Test if this RSIP request is just a keepalive */
3362  if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
3363  ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name);
3364  transmit_response(sub, "200", req, "OK");
3365  } else {
3366  dump_queue(p->parent, p);
3367  dump_cmd_queues(p, NULL);
3368 
3369  if ((strcmp(p->name, p->parent->wcardep) != 0)) {
3370  ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name);
3371  }
3372  /* For RSIP on wildcard we reset all endpoints */
3373  if (!strcmp(p->name, p->parent->wcardep)) {
3374  /* Reset all endpoints */
3375  struct mgcp_endpoint *tmp_ep;
3376 
3377  g = p->parent;
3378  for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) {
3379  /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/
3380  if (strcmp(tmp_ep->name, g->wcardep) != 0) {
3381  struct mgcp_subchannel *tmp_sub, *first_sub;
3382  ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
3383 
3384  first_sub = tmp_ep->sub;
3385  tmp_sub = tmp_ep->sub;
3386  while (tmp_sub) {
3387  mgcp_queue_hangup(tmp_sub);
3388  tmp_sub = tmp_sub->next;
3389  if (tmp_sub == first_sub)
3390  break;
3391  }
3392  }
3393  }
3394  } else if (sub->owner) {
3395  mgcp_queue_hangup(sub);
3396  }
3397  transmit_response(sub, "200", req, "OK");
3398  /* We don't send NTFY or AUEP to wildcard ep */
3399  if (strcmp(p->name, p->parent->wcardep) != 0) {
3400  transmit_notify_request(sub, "");
3401  /* Audit endpoint.
3402  Idea is to prevent lost lines due to race conditions
3403  */
3405  }
3406  }
3407  } else if (!strcasecmp(req->verb, "NTFY")) {
3408  /* Acknowledge and be sure we keep looking for the same things */
3409  transmit_response(sub, "200", req, "OK");
3410  /* Notified of an event */
3411  ev = get_header(req, "O");
3412  s = strchr(ev, '/');
3413  if (s) ev = s + 1;
3414  ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
3415  /* Keep looking for events unless this was a hangup */
3416  if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
3418  }
3419  if (!strcasecmp(ev, "hd")) {
3420  p->hookstate = MGCP_OFFHOOK;
3421  sub->cxmode = MGCP_CX_SENDRECV;
3422 
3423  if (p) {
3424  /* When the endpoint have a Off hook transition we allways
3425  starts without any previous dtmfs */
3426  memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
3427  }
3428 
3429  handle_hd_hf(sub, ev);
3430  } else if (!strcasecmp(ev, "hf")) {
3431  /* We can assume we are offhook if we received a hookflash */
3432  /* First let's just do call wait and ignore threeway */
3433  /* We're currently in charge */
3434  if (p->hookstate != MGCP_OFFHOOK) {
3435  /* Cisco c7940 sends hf even if the phone is onhook */
3436  /* Thanks to point on IRC for pointing this out */
3437  return -1;
3438  }
3439  /* do not let * conference two down channels */
3440  if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
3441  return -1;
3442 
3443  if (p->callwaiting || p->transfer || p->threewaycalling) {
3444  ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
3445  p->sub = p->sub->next;
3446 
3447  /* transfer control to our next subchannel */
3448  if (!sub->next->owner) {
3449  /* plave the first call on hold and start up a new call */
3450  sub->cxmode = MGCP_CX_MUTE;
3451  ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3453  if (sub->owner && ast_bridged_channel(sub->owner))
3455  sub->next->cxmode = MGCP_CX_RECVONLY;
3456  handle_hd_hf(sub->next, ev);
3457  } else if (sub->owner && sub->next->owner) {
3458  /* We've got two active calls lets decide whether or not to conference or just flip flop */
3459  if ((!sub->outgoing) && (!sub->next->outgoing)) {
3460  /* We made both calls lets conferenct */
3461  ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n",
3462  sub->id, sub->next->id, p->name, p->parent->name);
3463  sub->cxmode = MGCP_CX_CONF;
3464  sub->next->cxmode = MGCP_CX_CONF;
3465  if (ast_bridged_channel(sub->next->owner))
3469  } else {
3470  /* Let's flipflop between calls */
3471  /* XXX Need to check for state up ??? */
3472  /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
3473  ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
3474  sub->id, sub->next->id, p->name, p->parent->name);
3475  sub->cxmode = MGCP_CX_MUTE;
3476  ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3478  if (ast_bridged_channel(sub->owner))
3480 
3481  if (ast_bridged_channel(sub->next->owner))
3483 
3484  handle_hd_hf(sub->next, ev);
3485  }
3486  } else {
3487  /* We've most likely lost one of our calls find an active call and bring it up */
3488  if (sub->owner) {
3489  p->sub = sub;
3490  } else if (sub->next->owner) {
3491  p->sub = sub->next;
3492  } else {
3493  /* We seem to have lost both our calls */
3494  /* XXX - What do we do now? */
3495  return -1;
3496  }
3497  if (ast_bridged_channel(p->sub->owner))
3499  p->sub->cxmode = MGCP_CX_SENDRECV;
3501  }
3502  } else {
3503  ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
3504  p->name, p->parent->name);
3505  }
3506  } else if (!strcasecmp(ev, "hu")) {
3507  p->hookstate = MGCP_ONHOOK;
3508  sub->cxmode = MGCP_CX_RECVONLY;
3509  ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
3510  /* Do we need to send MDCX before a DLCX ?
3511  if (sub->rtp) {
3512  transmit_modify_request(sub);
3513  }
3514  */
3515  if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
3516  /* We're allowed to transfer, we have two avtive calls and */
3517  /* we made at least one of the calls. Let's try and transfer */
3518  ast_mutex_lock(&p->sub->next->lock);
3519  res = attempt_transfer(p);
3520  if (res < 0) {
3521  if (p->sub->next->owner) {
3522  sub->next->alreadygone = 1;
3523  mgcp_queue_hangup(sub->next);
3524  }
3525  } else if (res) {
3526  ast_log(LOG_WARNING, "Transfer attempt failed\n");
3527  ast_mutex_unlock(&p->sub->next->lock);
3528  return -1;
3529  }
3530  ast_mutex_unlock(&p->sub->next->lock);
3531  } else {
3532  /* Hangup the current call */
3533  /* If there is another active call, mgcp_hangup will ring the phone with the other call */
3534  if (sub->owner) {
3535  sub->alreadygone = 1;
3536  mgcp_queue_hangup(sub);
3537  } else {
3538  ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
3539  p->name, p->parent->name, sub->id);
3540  /* Instruct the other side to remove the connection since it apparently *
3541  * still thinks the channel is active. *
3542  * For Cisco IAD2421 /BAK/ */
3544  }
3545  }
3546  if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
3547  p->hidecallerid = 0;
3548  if (p->hascallwaiting && !p->callwaiting) {
3549  ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
3550  p->callwaiting = -1;
3551  }
3552  if (has_voicemail(p)) {
3553  ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
3554  transmit_notify_request(sub, "L/vmwi(+)");
3555  } else {
3556  ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
3557  transmit_notify_request(sub, "L/vmwi(-)");
3558  }
3559  }
3560  } else if ((strlen(ev) == 1) &&
3561  (((ev[0] >= '0') && (ev[0] <= '9')) ||
3562  ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
3563  (ev[0] == '*') || (ev[0] == '#'))) {
3564  if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) {
3566  f.subclass.integer = ev[0];
3567  f.src = "mgcp";
3568  /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
3569  mgcp_queue_frame(sub, &f);
3570  ast_mutex_lock(&sub->next->lock);
3571  if (sub->next->owner)
3572  mgcp_queue_frame(sub->next, &f);
3573  ast_mutex_unlock(&sub->next->lock);
3574  if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) {
3575  memset(p->curtone, 0, sizeof(p->curtone));
3576  }
3577  } else {
3578  p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
3579  p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
3580  }
3581  } else if (!strcasecmp(ev, "T")) {
3582  /* Digit timeout -- unimportant */
3583  } else if (!strcasecmp(ev, "ping")) {
3584  /* ping -- unimportant */
3585  } else {
3586  ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
3587  }
3588  } else {
3589  ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
3590  transmit_response(sub, "510", req, "Unknown verb");
3591  }
3592  return 0;
3593 }
3594 
3595 static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
3596 {
3597  int seqno=0;
3598  time_t now;
3599  struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL;
3600  time(&now);
3601  if (sscanf(req->identifier, "%30d", &seqno) != 1) {
3602  seqno = 0;
3603  }
3604  for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) {
3605  if (now - cur->whensent > RESPONSE_TIMEOUT) {
3606  /* Delete this entry */
3607  if (prev)
3608  prev->next = next;
3609  else
3610  sub->parent->parent->responses = next;
3611  ast_free(cur);
3612  } else {
3613  if (seqno == cur->seqno)
3614  answer = cur;
3615  prev = cur;
3616  }
3617  }
3618  if (answer) {
3619  resend_response(sub, answer);
3620  return 1;
3621  }
3622  return 0;
3623 }
3624 
3625 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
3626 {
3627  struct mgcp_request req;
3628  struct sockaddr_in sin;
3629  struct mgcp_subchannel *sub;
3630  int res;
3631  socklen_t len;
3632  int result;
3633  int ident;
3634  len = sizeof(sin);
3635  memset(&req, 0, sizeof(req));
3636  res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
3637  if (res < 0) {
3638  if (errno != ECONNREFUSED)
3639  ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
3640  return 1;
3641  }
3642  req.data[res] = '\0';
3643  req.len = res;
3644  ast_debug(1, "MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
3645  parse(&req);
3646  if (req.headers < 1) {
3647  /* Must have at least one header */
3648  return 1;
3649  }
3650  if (ast_strlen_zero(req.identifier)) {
3651  ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
3652  return 1;
3653  }
3654 
3655  if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) {
3656  if (result < 200) {
3657  ast_debug(1, "Ignoring provisional response on transaction %d\n", ident);
3658  return 1;
3659  }
3660  /* Try to find who this message is for, if it's important */
3661  sub = find_subchannel_and_lock(NULL, ident, &sin);
3662  if (sub) {
3663  struct mgcp_gateway *gw = sub->parent->parent;
3664  struct mgcp_message *cur, *prev;
3665 
3666  ast_mutex_unlock(&sub->lock);
3667  ast_mutex_lock(&gw->msgs_lock);
3668  for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
3669  if (cur->seqno == ident) {
3670  ast_debug(1, "Got response back on transaction %d\n", ident);
3671  if (prev)
3672  prev->next = cur->next;
3673  else
3674  gw->msgs = cur->next;
3675  break;
3676  }
3677  }
3678 
3679  /* stop retrans timer if the queue is empty */
3680  if (!gw->msgs) {
3681  AST_SCHED_DEL(sched, gw->retransid);
3682  }
3683 
3685  if (cur) {
3686  handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
3687  ast_free(cur);
3688  return 1;
3689  }
3690 
3691  ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
3692  gw->name, ident);
3693  }
3694  } else {
3695  if (ast_strlen_zero(req.endpoint) ||
3696  ast_strlen_zero(req.version) ||
3697  ast_strlen_zero(req.verb)) {
3698  ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
3699  return 1;
3700  }
3701  /* Process request, with iflock held */
3702  sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
3703  if (sub) {
3704  /* look first to find a matching response in the queue */
3705  if (!find_and_retrans(sub, &req))
3706  /* pass the request off to the currently mastering subchannel */
3707  handle_request(sub, &req, &sin);
3708  ast_mutex_unlock(&sub->lock);
3709  }
3710  }
3711  return 1;
3712 }
3713 
3714 static int *mgcpsock_read_id = NULL;
3715 
3717 {
3718  struct mgcp_endpoint *enext, *e;
3719  struct mgcp_subchannel *s, *sub;
3720  int i, prune = 1;
3721 
3722  if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) {
3724  return 0;
3725  }
3726 
3727  for (e = g->endpoints; e; e = e->next) {
3728  ast_mutex_lock(&e->lock);
3730  prune = 0;
3731  } else if (e->rqnt_queue || e->cmd_queue) {
3732  prune = 0;
3733  }
3734  s = e->sub;
3735  for (i = 0; (i < MAX_SUBS) && s; i++) {
3736  ast_mutex_lock(&s->lock);
3737  if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) {
3738  prune = 0;
3739  } else if (s->cx_queue) {
3740  prune = 0;
3741  }
3742  s = s->next;
3743  }
3744  }
3745 
3746  for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) {
3747  for (i = 0; (i < MAX_SUBS) && sub; i++) {
3748  s = sub;
3749  sub = sub->next;
3750  ast_mutex_unlock(&s->lock);
3752  if (prune) {
3753  ast_mutex_destroy(&s->lock);
3755  free(s);
3756  }
3757  }
3758  ast_mutex_unlock(&e->lock);
3761  if (prune) {
3762  ast_mutex_destroy(&e->lock);
3765  free(e);
3766  }
3767  }
3768  if (prune) {
3769  ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name);
3770  }
3771  return prune;
3772 }
3773 
3774 static void *do_monitor(void *data)
3775 {
3776  int res;
3777  int reloading;
3778  struct mgcp_gateway *g, *gprev;
3779  /*struct mgcp_gateway *g;*/
3780  /*struct mgcp_endpoint *e;*/
3781  /*time_t thispass = 0, lastpass = 0;*/
3782  time_t lastrun = 0;
3783 
3784  /* Add an I/O event to our UDP socket */
3785  if (mgcpsock > -1) {
3786  mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
3787  }
3788  /* This thread monitors all the frame relay interfaces which are not yet in use
3789  (and thus do not have a separate thread) indefinitely */
3790  /* From here on out, we die whenever asked */
3791  for (;;) {
3792  /* Check for a reload request */
3794  reloading = mgcp_reloading;
3795  mgcp_reloading = 0;
3797  if (reloading) {
3798  ast_verb(1, "Reloading MGCP\n");
3799  reload_config(1);
3800  /* Add an I/O event to our UDP socket */
3801  if (mgcpsock > -1 && !mgcpsock_read_id) {
3802  mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
3803  }
3804  }
3805 
3806  /* Check for interfaces needing to be killed */
3807  /* Don't let anybody kill us right away. Nobody should lock the interface list
3808  and wait for the monitor list, but the other way around is okay. */
3810  /* Lock the network interface */
3812 
3813 #if 0
3814  /* XXX THIS IS COMPLETELY HOSED */
3815  /* The gateway goes into a state of panic */
3816  /* If the vmwi indicator is sent while it is reseting interfaces */
3817  lastpass = thispass;
3818  thispass = time(NULL);
3819  g = gateways;
3820  while(g) {
3821  if (thispass != lastpass) {
3822  e = g->endpoints;
3823  while(e) {
3824  if (e->type == TYPE_LINE) {
3825  res = has_voicemail(e);
3826  if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
3827  if (res) {
3828  transmit_notify_request(e, "L/vmwi(+)");
3829  } else {
3830  transmit_notify_request(e, "L/vmwi(-)");
3831  }
3832  e->msgstate = res;
3833  e->onhooktime = thispass;
3834  }
3835  }
3836  e = e->next;
3837  }
3838  }
3839  g = g->next;
3840  }
3841 #endif
3842  /* pruning unused realtime gateways, running in every 60 seconds*/
3843  if(time(NULL) > (lastrun + 60)) {
3845  g = gateways;
3846  gprev = NULL;
3847  while(g) {
3848  if(g->realtime) {
3850  if(gprev) {
3851  gprev->next = g->next;
3852  } else {
3853  gateways = g->next;
3854  }
3857  free(g);
3858  } else {
3860  gprev = g;
3861  }
3862  } else {
3863  gprev = g;
3864  }
3865  g = g->next;
3866  }
3868  lastrun = time(NULL);
3869  }
3870  /* Okay, now that we know what to do, release the network lock */
3872  /* And from now on, we're okay to be killed, so release the monitor lock as well */
3874  pthread_testcancel();
3875  /* Wait for sched or io */
3876  res = ast_sched_wait(sched);
3877  /* copied from chan_sip.c */
3878  if ((res < 0) || (res > 1000)) {
3879  res = 1000;
3880  }
3881  res = ast_io_wait(io, res);
3883  if (res >= 0) {
3884  ast_sched_runq(sched);
3885  }
3887  }
3888  /* Never reached */
3889  return NULL;
3890 }
3891 
3892 static int restart_monitor(void)
3893 {
3894  /* If we're supposed to be stopped -- stay stopped */
3895  if (monitor_thread == AST_PTHREADT_STOP)
3896  return 0;
3897  if (ast_mutex_lock(&monlock)) {
3898  ast_log(LOG_WARNING, "Unable to lock monitor\n");
3899  return -1;
3900  }
3901  if (monitor_thread == pthread_self()) {
3903  ast_log(LOG_WARNING, "Cannot kill myself\n");
3904  return -1;
3905  }
3906  if (monitor_thread != AST_PTHREADT_NULL) {
3907  /* Wake up the thread */
3908  pthread_kill(monitor_thread, SIGURG);
3909  } else {
3910  /* Start a new monitor */
3911  if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
3913  ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
3914  return -1;
3915  }
3916  }
3918  return 0;
3919 }
3920 
3921 static struct ast_channel *mgcp_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
3922 {
3923  struct mgcp_subchannel *sub;
3924  struct ast_channel *tmpc = NULL;
3925  char tmp[256];
3926  char *dest = data;
3927 
3928  format &= capability;
3929  if (!format) {
3930  ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format));
3931  /*return NULL;*/
3932  }
3933  ast_copy_string(tmp, dest, sizeof(tmp));
3934  if (ast_strlen_zero(tmp)) {
3935  ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
3936  return NULL;
3937  }
3938  if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) {
3939  ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
3940  *cause = AST_CAUSE_UNREGISTERED;
3941  return NULL;
3942  }
3943 
3944  ast_verb(3, "MGCP mgcp_request(%s)\n", tmp);
3945  ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
3946  sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
3947  /* Must be busy */
3948  if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
3949  ((!sub->parent->callwaiting) && (sub->owner)) ||
3950  (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
3951  if (sub->parent->hookstate == MGCP_ONHOOK) {
3952  if (has_voicemail(sub->parent)) {
3953  transmit_notify_request(sub,"L/vmwi(+)");
3954  } else {
3955  transmit_notify_request(sub,"L/vmwi(-)");
3956  }
3957  }
3958  *cause = AST_CAUSE_BUSY;
3959  ast_mutex_unlock(&sub->lock);
3960  return NULL;
3961  }
3962  tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
3963  ast_mutex_unlock(&sub->lock);
3964  if (!tmpc)
3965  ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
3966  restart_monitor();
3967  return tmpc;
3968 }
3969 
3970 /* modified for reload support */
3971 /*! \brief build_gateway: parse mgcp.conf and create gateway/endpoint structures */
3972 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
3973 {
3974  struct mgcp_gateway *gw;
3975  struct mgcp_endpoint *e;
3976  struct mgcp_subchannel *sub;
3977  struct ast_variable *chanvars = NULL;
3978 
3979  /*char txident[80];*/
3980  int i=0, y=0;
3981  int gw_reload = 0;
3982  int ep_reload = 0;
3983  directmedia = DIRECTMEDIA;
3984 
3985  /* locate existing gateway */
3986  for (gw = gateways; gw; gw = gw->next) {
3987  if (!strcasecmp(cat, gw->name)) {
3988  /* gateway already exists */
3989  gw->delme = 0;
3990  gw_reload = 1;
3991  break;
3992  }
3993  }
3994 
3995  if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) {
3996  return NULL;
3997  }
3998 
3999  if (!gw_reload) {
4000  gw->expire = -1;
4001  gw->realtime = 0;
4002  gw->retransid = -1;
4003  ast_mutex_init(&gw->msgs_lock);
4004  ast_copy_string(gw->name, cat, sizeof(gw->name));
4005  /* check if the name is numeric ip */
4006  if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
4007  gw->isnamedottedip = 1;
4008  }
4009  for (; v; v = v->next) {
4010  if (!strcasecmp(v->name, "host")) {
4011  if (!strcasecmp(v->value, "dynamic")) {
4012  /* They'll register with us */
4013  gw->dynamic = 1;
4014  memset(&gw->addr.sin_addr, 0, 4);
4015  if (gw->addr.sin_port) {
4016  /* If we've already got a port, make it the default rather than absolute */
4017  gw->defaddr.sin_port = gw->addr.sin_port;
4018  gw->addr.sin_port = 0;
4019  }
4020  } else {
4021  /* Non-dynamic. Make sure we become that way if we're not */
4022  AST_SCHED_DEL(sched, gw->expire);
4023  gw->dynamic = 0;
4024  {
4025  struct ast_sockaddr tmp;
4026 
4027  ast_sockaddr_from_sin(&tmp, &gw->addr);
4028  if (ast_get_ip(&tmp, v->value)) {
4029  if (!gw_reload) {
4031  ast_free(gw);
4032  }
4033  return NULL;
4034  }
4035  ast_sockaddr_to_sin(&tmp, &gw->addr);
4036  }
4037  }
4038  } else if (!strcasecmp(v->name, "defaultip")) {
4039  struct ast_sockaddr tmp;
4040 
4041  ast_sockaddr_from_sin(&tmp, &gw->defaddr);
4042  if (ast_get_ip(&tmp, v->value)) {
4043  if (!gw_reload) {
4045  ast_free(gw);
4046  }
4047  return NULL;
4048  }
4049  ast_sockaddr_to_sin(&tmp, &gw->defaddr);
4050  } else if (!strcasecmp(v->name, "permit") ||
4051  !strcasecmp(v->name, "deny")) {
4052  gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL);
4053  } else if (!strcasecmp(v->name, "port")) {
4054  gw->addr.sin_port = htons(atoi(v->value));
4055  } else if (!strcasecmp(v->name, "context")) {
4056  ast_copy_string(context, v->value, sizeof(context));
4057  } else if (!strcasecmp(v->name, "dtmfmode")) {
4058  if (!strcasecmp(v->value, "inband"))
4059  dtmfmode = MGCP_DTMF_INBAND;
4060  else if (!strcasecmp(v->value, "rfc2833"))
4061  dtmfmode = MGCP_DTMF_RFC2833;
4062  else if (!strcasecmp(v->value, "hybrid"))
4063  dtmfmode = MGCP_DTMF_HYBRID;
4064  else if (!strcasecmp(v->value, "none"))
4065  dtmfmode = 0;
4066  else
4067  ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
4068  } else if (!strcasecmp(v->name, "nat")) {
4069  nat = ast_true(v->value);
4070  } else if (!strcasecmp(v->name, "ncs")) {
4071  ncs = ast_true(v->value);
4072  } else if (!strcasecmp(v->name, "hangupongateremove")) {
4073  hangupongateremove = ast_true(v->value);
4074  } else if (!strcasecmp(v->name, "pktcgatealloc")) {
4075  pktcgatealloc = ast_true(v->value);
4076  } else if (!strcasecmp(v->name, "callerid")) {
4077  if (!strcasecmp(v->value, "asreceived")) {
4078  cid_num[0] = '\0';
4079  cid_name[0] = '\0';
4080  } else {
4081  ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
4082  }
4083  } else if (!strcasecmp(v->name, "language")) {
4084  ast_copy_string(language, v->value, sizeof(language));
4085  } else if (!strcasecmp(v->name, "accountcode")) {
4086  ast_copy_string(accountcode, v->value, sizeof(accountcode));
4087  } else if (!strcasecmp(v->name, "amaflags")) {
4088  y = ast_cdr_amaflags2int(v->value);
4089  if (y < 0) {
4090  ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
4091  } else {
4092  amaflags = y;
4093  }
4094  } else if (!strcasecmp(v->name, "setvar")) {
4095  chanvars = add_var(v->value, chanvars);
4096  } else if (!strcasecmp(v->name, "clearvars")) {
4097  if (chanvars) {
4098  ast_variables_destroy(chanvars);
4099  chanvars = NULL;
4100  }
4101  } else if (!strcasecmp(v->name, "musiconhold")) {
4102  ast_copy_string(musicclass, v->value, sizeof(musicclass));
4103  } else if (!strcasecmp(v->name, "parkinglot")) {
4104  ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
4105  } else if (!strcasecmp(v->name, "callgroup")) {
4106  cur_callergroup = ast_get_group(v->value);
4107  } else if (!strcasecmp(v->name, "pickupgroup")) {
4108  cur_pickupgroup = ast_get_group(v->value);
4109  } else if (!strcasecmp(v->name, "immediate")) {
4110  immediate = ast_true(v->value);
4111  } else if (!strcasecmp(v->name, "cancallforward")) {
4112  cancallforward = ast_true(v->value);
4113  } else if (!strcasecmp(v->name, "singlepath")) {
4114  singlepath = ast_true(v->value);
4115  } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
4116  directmedia = ast_true(v->value);
4117  } else if (!strcasecmp(v->name, "mailbox")) {
4118  ast_copy_string(mailbox, v->value, sizeof(mailbox));
4119  } else if (!strcasecmp(v->name, "hasvoicemail")) {
4120  if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
4121  ast_copy_string(mailbox, gw->name, sizeof(mailbox));
4122  }
4123  } else if (!strcasecmp(v->name, "adsi")) {
4124  adsi = ast_true(v->value);
4125  } else if (!strcasecmp(v->name, "callreturn")) {
4126  callreturn = ast_true(v->value);
4127  } else if (!strcasecmp(v->name, "callwaiting")) {
4128  callwaiting = ast_true(v->value);
4129  } else if (!strcasecmp(v->name, "slowsequence")) {
4130  slowsequence = ast_true(v->value);
4131  } else if (!strcasecmp(v->name, "transfer")) {
4132  transfer = ast_true(v->value);
4133  } else if (!strcasecmp(v->name, "threewaycalling")) {
4134  threewaycalling = ast_true(v->value);
4135  } else if (!strcasecmp(v->name, "wcardep")) {
4136  /* locate existing endpoint */
4137  for (e = gw->endpoints; e; e = e->next) {
4138  if (!strcasecmp(v->value, e->name)) {
4139  /* endpoint already exists */
4140  e->delme = 0;
4141  ep_reload = 1;
4142  break;
4143  }
4144  }
4145 
4146  if (!e) {
4147  /* Allocate wildcard endpoint */
4148  e = ast_calloc(1, sizeof(*e));
4149  ep_reload = 0;
4150  }
4151 
4152  if (e) {
4153  if (!ep_reload) {
4154  memset(e, 0, sizeof(struct mgcp_endpoint));
4155  ast_mutex_init(&e->lock);
4158  ast_copy_string(e->name, v->value, sizeof(e->name));
4159  e->needaudit = 1;
4160  }
4161  ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
4162  /* XXX Should we really check for uniqueness?? XXX */
4163  ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
4164  ast_copy_string(e->context, context, sizeof(e->context));
4165  ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
4166  ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
4167  ast_copy_string(e->language, language, sizeof(e->language));
4168  ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
4169  ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
4170  ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
4171  if (!ast_strlen_zero(e->mailbox)) {
4172  char *mbox, *cntx;
4173  cntx = mbox = ast_strdupa(e->mailbox);
4174  strsep(&cntx, "@");
4175  if (ast_strlen_zero(cntx)) {
4176  cntx = "default";
4177  }
4178  e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "MGCP MWI subscription", NULL,
4183  }
4184  snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", (unsigned long)ast_random());
4185  e->msgstate = -1;
4186  e->amaflags = amaflags;
4187  e->capability = capability;
4188  e->parent = gw;
4189  e->ncs = ncs;
4190  e->dtmfmode = dtmfmode;
4191  if (!ep_reload && e->sub && e->sub->rtp) {
4192  e->dtmfmode |= MGCP_DTMF_INBAND;
4193  }
4194  e->adsi = adsi;
4195  e->type = TYPE_LINE;
4196  e->immediate = immediate;
4199  e->callreturn = callreturn;
4201  e->singlepath = singlepath;
4202  e->directmedia = directmedia;
4203  e->callwaiting = callwaiting;
4206  e->transfer = transfer;
4208  e->onhooktime = time(NULL);
4209  /* ASSUME we're onhook */
4210  e->hookstate = MGCP_ONHOOK;
4211  e->chanvars = copy_vars(chanvars);
4212  if (!ep_reload) {
4213  /*snprintf(txident, sizeof(txident), "%08lx", (unsigned long)ast_random());*/
4214  for (i = 0; i < MAX_SUBS; i++) {
4215  sub = ast_calloc(1, sizeof(*sub));
4216  if (sub) {
4217  ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
4218  ast_mutex_init(&sub->lock);
4220  sub->parent = e;
4221  sub->id = i;
4222  snprintf(sub->txident, sizeof(sub->txident), "%08lx", (unsigned long)ast_random());
4223  /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/
4224  sub->cxmode = MGCP_CX_INACTIVE;
4225  sub->nat = nat;
4226  sub->gate = NULL;
4227  sub->sdpsent = 0;
4228  sub->next = e->sub;
4229  e->sub = sub;
4230  } else {
4231  /* XXX Should find a way to clean up our memory */
4232  ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
4233  return NULL;
4234  }
4235  }
4236  /* Make out subs a circular linked list so we can always sping through the whole bunch */
4237  /* find the end of the list */
4238  for (sub = e->sub; sub && sub->next; sub = sub->next);
4239  /* set the last sub->next to the first sub */
4240  sub->next = e->sub;
4241 
4242  e->next = gw->endpoints;
4243  gw->endpoints = e;
4244  }
4245  }
4246  } else if (!strcasecmp(v->name, "trunk") ||
4247  !strcasecmp(v->name, "line")) {
4248 
4249  /* locate existing endpoint */
4250  for (e = gw->endpoints; e; e = e->next) {
4251  if (!strcasecmp(v->value, e->name)) {
4252  /* endpoint already exists */
4253  e->delme = 0;
4254  ep_reload = 1;
4255  break;
4256  }
4257  }
4258 
4259  if (!e) {
4260  e = ast_calloc(1, sizeof(*e));
4261  ep_reload = 0;
4262  }
4263 
4264  if (e) {
4265  if (!ep_reload) {
4266  ast_mutex_init(&e->lock);
4269  ast_copy_string(e->name, v->value, sizeof(e->name));
4270  e->needaudit = 1;
4271  }
4272  /* XXX Should we really check for uniqueness?? XXX */
4273  ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
4274  ast_copy_string(e->context, context, sizeof(e->context));
4275  ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
4276  ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
4277  ast_copy_string(e->language, language, sizeof(e->language));
4278  ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
4279  ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
4280  ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
4281  if (!ast_strlen_zero(mailbox)) {
4282  ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
4283  }
4284  if (!ep_reload) {
4285  /* XXX potential issue due to reload */
4286  e->msgstate = -1;
4287  e->parent = gw;
4288  }
4289  e->amaflags = amaflags;
4290  e->capability = capability;
4291  e->dtmfmode = dtmfmode;
4292  e->ncs = ncs;
4295  e->adsi = adsi;
4296  e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE;
4297  e->immediate = immediate;
4300  e->callreturn = callreturn;
4302  e->directmedia = directmedia;
4303  e->singlepath = singlepath;
4304  e->callwaiting = callwaiting;
4307  e->transfer = transfer;
4309 
4310  /* If we already have a valid chanvars, it's not a new endpoint (it's a reload),
4311  so first, free previous mem
4312  */
4313  if (e->chanvars) {
4315  e->chanvars = NULL;
4316  }
4317  e->chanvars = copy_vars(chanvars);
4318 
4319  if (!ep_reload) {
4320  e->onhooktime = time(NULL);
4321  /* ASSUME we're onhook */
4322  e->hookstate = MGCP_ONHOOK;
4323  snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", (unsigned long)ast_random());
4324  }
4325 
4326  for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
4327  if (!ep_reload) {
4328  sub = ast_calloc(1, sizeof(*sub));
4329  } else {
4330  if (!sub) {
4331  sub = e->sub;
4332  } else {
4333  sub = sub->next;
4334  }
4335  }
4336 
4337  if (sub) {
4338  if (!ep_reload) {
4339  ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
4340  ast_mutex_init(&sub->lock);
4342  ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
4343  sub->parent = e;
4344  sub->id = i;
4345  snprintf(sub->txident, sizeof(sub->txident), "%08lx", (unsigned long)ast_random());
4346  sub->cxmode = MGCP_CX_INACTIVE;
4347  sub->next = e->sub;
4348  e->sub = sub;
4349  }
4350  sub->nat = nat;
4351  } else {
4352  /* XXX Should find a way to clean up our memory */
4353  ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
4354  return NULL;
4355  }
4356  }
4357  if (!ep_reload) {
4358  /* Make out subs a circular linked list so we can always sping through the whole bunch */
4359  /* find the end of the list */
4360  for (sub = e->sub; sub && sub->next; sub = sub->next);
4361  /* set the last sub->next to the first sub */
4362  sub->next = e->sub;
4363 
4364  e->next = gw->endpoints;
4365  gw->endpoints = e;
4366  }
4367  }
4368  } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) {
4369  /* just eliminate realtime warnings */
4370  } else {
4371  ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
4372  }
4373  }
4374  if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
4375  ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
4376  if (!gw_reload) {
4378  ast_free(gw);
4379  }
4380 
4381  /* Return NULL */
4382  gw_reload = 1;
4383  } else {
4384  gw->defaddr.sin_family = AF_INET;
4385  gw->addr.sin_family = AF_INET;
4386  if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) {
4387  gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
4388  }
4389  if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) {
4390  gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
4391  }
4392  {
4393  struct ast_sockaddr tmp1, tmp2;
4394  struct sockaddr_in tmp3 = {0,};
4395 
4396  tmp3.sin_addr = gw->ourip;
4397  ast_sockaddr_from_sin(&tmp1, &gw->addr);
4398  ast_sockaddr_from_sin(&tmp2, &tmp3);
4399  if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) {
4400  memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
4401  } else {
4402  ast_sockaddr_to_sin(&tmp2, &tmp3);
4403  gw->ourip = tmp3.sin_addr;
4404  }
4405  }
4406  }
4407 
4408  if (chanvars) {
4409  ast_variables_destroy(chanvars);
4410  chanvars = NULL;
4411  }
4412  return (gw_reload ? NULL : gw);
4413 }
4414 
4415 static enum ast_rtp_glue_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
4416 {
4417  struct mgcp_subchannel *sub = NULL;
4418 
4419  if (!(sub = chan->tech_pvt) || !(sub->rtp))
4421 
4422  *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL;
4423 
4424  if (sub->parent->directmedia)
4426  else
4428 }
4429 
4430 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, format_t codecs, int nat_active)
4431 {
4432  /* XXX Is there such thing as video support with MGCP? XXX */
4433  struct mgcp_subchannel *sub;
4434  sub = chan->tech_pvt;
4435  if (sub && !sub->alreadygone) {
4436  transmit_modify_with_sdp(sub, rtp, codecs);
4437  return 0;
4438  }
4439  return -1;
4440 }
4441 
4443 {
4444  struct mgcp_subchannel *sub = chan->tech_pvt;
4445  struct mgcp_endpoint *p = sub->parent;
4446  return p->capability;
4447 }
4448 
4449 static struct ast_rtp_glue mgcp_rtp_glue = {
4450  .type = "MGCP",
4451  .get_rtp_info = mgcp_get_rtp_peer,
4452  .update_peer = mgcp_set_rtp_peer,
4453  .get_codec = mgcp_get_codec,
4454 };
4455 
4456 
4457 static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen)
4458 {
4459  struct mgcp_subchannel *sub = chan->tech_pvt;
4460  int res = 0;
4461 
4462  /* Sanity check */
4463  if (!chan || chan->tech != &mgcp_tech) {
4464  ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n");
4465  return -1;
4466  }
4467 
4468  if (!strcasecmp(args, "ncs")) {
4469  snprintf(buf, buflen, "%s", sub->parent->ncs ? "yes":"no");
4470  } else {
4471  res = -1;
4472  }
4473  return res;
4474 }
4475 
4476 
4477 static void destroy_endpoint(struct mgcp_endpoint *e)
4478 {
4479  struct mgcp_subchannel *sub = e->sub->next, *s;
4480  int i;
4481 
4482  for (i = 0; i < MAX_SUBS; i++) {
4483  ast_mutex_lock(&sub->lock);
4484  if (!ast_strlen_zero(sub->cxident)) {
4486  }
4487  if (sub->rtp) {
4489  sub->rtp = NULL;
4490  }
4491  memset(sub->magic, 0, sizeof(sub->magic));
4492  mgcp_queue_hangup(sub);
4493  dump_cmd_queues(NULL, sub);
4494  if(sub->gate) {
4495  sub->gate->tech_pvt = NULL;
4496  sub->gate->got_dq_gi = NULL;
4497  sub->gate->gate_remove = NULL;
4498  sub->gate->gate_open = NULL;
4499  }
4500  ast_mutex_unlock(&sub->lock);
4501  sub = sub->next;
4502  }
4503 
4504  if (e->dsp) {
4505  ast_dsp_free(e->dsp);
4506  }
4507 
4508  dump_queue(e->parent, e);
4509  dump_cmd_queues(e, NULL);
4510 
4511  sub = e->sub;
4512  for (i = 0; (i < MAX_SUBS) && sub; i++) {
4513  s = sub;
4514  sub = sub->next;
4515  ast_mutex_destroy(&s->lock);
4516  ast_mutex_destroy(&s->cx_queue_lock);
4517  ast_free(s);
4518  }
4519 
4520  if (e->mwi_event_sub)
4522 
4523  if (e->chanvars) {
4525  e->chanvars = NULL;
4526  }
4527 
4528  ast_mutex_destroy(&e->lock);
4531  ast_free(e);
4532 }
4533 
4534 static void destroy_gateway(struct mgcp_gateway *g)
4535 {
4536  if (g->ha)
4537  ast_free_ha(g->ha);
4538 
4539  dump_queue(g, NULL);
4540 
4541  ast_free(g);
4542 }
4543 
4544 static void prune_gateways(void)
4545 {
4546  struct mgcp_gateway *g, *z, *r;
4547  struct mgcp_endpoint *e, *p, *t;
4548 
4550 
4551  /* prune gateways */
4552  for (z = NULL, g = gateways; g;) {
4553  /* prune endpoints */
4554  for (p = NULL, e = g->endpoints; e; ) {
4555  if (!g->realtime && (e->delme || g->delme)) {
4556  t = e;
4557  e = e->next;
4558  if (!p)
4559  g->endpoints = e;
4560  else
4561  p->next = e;
4562  destroy_endpoint(t);
4563  } else {
4564  p = e;
4565  e = e->next;
4566  }
4567  }
4568 
4569  if (g->delme) {
4570  r = g;
4571  g = g->next;
4572  if (!z)
4573  gateways = g;
4574  else
4575  z->next = g;
4576 
4577  destroy_gateway(r);
4578  } else {
4579  z = g;
4580  g = g->next;
4581  }
4582  }
4583 
4585 }
4586 
4587 static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
4588 {
4589  struct ast_variable *tmpvar = NULL;
4590  char *varname = ast_strdupa(buf), *varval = NULL;
4591 
4592  if ((varval = strchr(varname, '='))) {
4593  *varval++ = '\0';
4594  if ((tmpvar = ast_variable_new(varname, varval, ""))) {
4595  tmpvar->next = list;
4596  list = tmpvar;
4597  }
4598  }
4599  return list;
4600 }
4601 
4602 /*! \brief
4603  * duplicate a list of channel variables, \return the copy.
4604  */
4605 static struct ast_variable *copy_vars(struct ast_variable *src)
4606 {
4607  struct ast_variable *res = NULL, *tmp, *v = NULL;
4608 
4609  for (v = src ; v ; v = v->next) {
4610  if ((tmp = ast_variable_new(v->name, v->value, v->file))) {
4611  tmp->next = res;
4612  res = tmp;
4613  }
4614  }
4615  return res;
4616 }
4617 
4618 
4619 static int reload_config(int reload)
4620 {
4621  struct ast_config *cfg;
4622  struct ast_variable *v;
4623  struct mgcp_gateway *g;
4624  struct mgcp_endpoint *e;
4625  char *cat;
4626  struct ast_hostent ahp;
4627  struct hostent *hp;
4628  int format;
4629  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
4630 
4631  if (gethostname(ourhost, sizeof(ourhost)-1)) {
4632  ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
4633  return 0;
4634  }
4635  cfg = ast_config_load(config, config_flags);
4636 
4637  /* We *must* have a config file otherwise stop immediately */
4638  if (!cfg) {
4639  ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
4640  return 0;
4641  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
4642  return 0;
4643  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
4644  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
4645  return 0;
4646  }
4647 
4648  memset(&bindaddr, 0, sizeof(bindaddr));
4649  dtmfmode = 0;
4650 
4651  /* Copy the default jb config over global_jbconf */
4652  memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
4653 
4654  for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
4655  /* handle jb conf */
4656  if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
4657  continue;
4658  }
4659 
4660  /* Create the interface list */
4661  if (!strcasecmp(v->name, "bindaddr")) {
4662  if (!(hp = ast_gethostbyname(v->value, &ahp))) {
4663  ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
4664  } else {
4665  memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
4666  }
4667  } else if (!strcasecmp(v->name, "allow")) {
4668  format = ast_getformatbyname(v->value);
4669  if (format < 1) {
4670  ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
4671  } else {
4672  capability |= format;
4673  }
4674  } else if (!strcasecmp(v->name, "disallow")) {
4675  format = ast_getformatbyname(v->value);
4676  if (format < 1) {
4677  ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
4678  } else {
4679  capability &= ~format;
4680  }
4681  } else if (!strcasecmp(v->name, "tos")) {
4682  if (ast_str2tos(v->value, &qos.tos)) {
4683  ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
4684  }
4685  } else if (!strcasecmp(v->name, "tos_audio")) {
4686  if (ast_str2tos(v->value, &qos.tos_audio))
4687  ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
4688  } else if (!strcasecmp(v->name, "cos")) {
4689  if (ast_str2cos(v->value, &qos.cos))
4690  ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
4691  } else if (!strcasecmp(v->name, "cos_audio")) {
4692  if (ast_str2cos(v->value, &qos.cos_audio))
4693  ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
4694  } else if (!strcasecmp(v->name, "port")) {
4695  if (sscanf(v->value, "%5d", &ourport) == 1) {
4696  bindaddr.sin_port = htons(ourport);
4697  } else {
4698  ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
4699  }
4700  } else if (!strcasecmp(v->name, "firstdigittimeout")) {
4701  firstdigittimeout = atoi(v->value);
4702  } else if (!strcasecmp(v->name, "gendigittimeout")) {
4703  gendigittimeout = atoi(v->value);
4704  } else if (!strcasecmp(v->name, "matchdigittimeout")) {
4705  matchdigittimeout = atoi(v->value);
4706  }
4707  }
4708 
4709  /* mark existing entries for deletion */
4711  for (g = gateways; g; g = g->next) {
4712  g->delme = 1;
4713  for (e = g->endpoints; e; e = e->next) {
4714  e->delme = 1;
4715  }
4716  }
4718 
4719  for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
4720  if (strcasecmp(cat, "general")) {
4722  if ((g = build_gateway(cat, ast_variable_browse(cfg, cat)))) {
4723  ast_verb(3, "Added gateway '%s'\n", g->name);
4724  g->next = gateways;
4725  gateways = g;
4726  }
4728 
4729  /* FS: process queue and IO */
4730  if (monitor_thread == pthread_self()) {
4731  if (sched) ast_sched_runq(sched);
4732  if (io) ast_io_wait(io, 10);
4733  }
4734  }
4735  }
4736 
4737  /* prune deleted entries etc. */
4738  prune_gateways();
4739 
4740  if (ntohl(bindaddr.sin_addr.s_addr)) {
4741  memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
4742  } else {
4743  hp = ast_gethostbyname(ourhost, &ahp);
4744  if (!hp) {
4745  ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
4746  ast_config_destroy(cfg);
4747  return 0;
4748  }
4749  memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
4750  }
4751  if (!ntohs(bindaddr.sin_port))
4752  bindaddr.sin_port = htons(DEFAULT_MGCP_CA_PORT);
4753  bindaddr.sin_family = AF_INET;
4755  if (mgcpsock > -1)
4756  close(mgcpsock);
4757 
4758  if (mgcpsock_read_id != NULL)
4759  ast_io_remove(io, mgcpsock_read_id);
4760  mgcpsock_read_id = NULL;
4761 
4762  mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
4763  if (mgcpsock < 0) {
4764  ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
4765  } else {
4766  if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
4767  ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
4768  ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
4769  strerror(errno));
4770  close(mgcpsock);
4771  mgcpsock = -1;
4772  } else {
4773  ast_verb(2, "MGCP Listening on %s:%d\n",
4774  ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
4775  ast_netsock_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP");
4776  }
4777  }
4779  ast_config_destroy(cfg);
4780 
4781  /* send audit only to the new endpoints */
4782  for (g = gateways; g; g = g->next) {
4783  for (e = g->endpoints; e && e->needaudit; e = e->next) {
4784  e->needaudit = 0;
4786  ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
4787  }
4788  }
4789 
4790  return 0;
4791 }
4792 
4793 /*! \brief load_module: PBX load module - initialization ---*/
4794 static int load_module(void)
4795 {
4796  if (!(sched = sched_context_create())) {
4797  ast_log(LOG_WARNING, "Unable to create schedule context\n");
4798  return AST_MODULE_LOAD_FAILURE;
4799  }
4800 
4801  if (!(io = io_context_create())) {
4802  ast_log(LOG_WARNING, "Unable to create I/O context\n");
4803  sched_context_destroy(sched);
4804  return AST_MODULE_LOAD_FAILURE;
4805  }
4806 
4807  if (reload_config(0))
4808  return AST_MODULE_LOAD_DECLINE;
4809 
4810  /* Make sure we can register our mgcp channel type */
4811  if (ast_channel_register(&mgcp_tech)) {
4812  ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
4813  io_context_destroy(io);
4814  sched_context_destroy(sched);
4815  return AST_MODULE_LOAD_FAILURE;
4816  }
4817 
4818  ast_rtp_glue_register(&mgcp_rtp_glue);
4819  ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
4820 
4821  /* And start the monitor for the first time */
4822  restart_monitor();
4823 
4824  return AST_MODULE_LOAD_SUCCESS;
4825 }
4826 
4827 static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4828 {
4829  static int deprecated = 0;
4830 
4831  if (e) {
4832  switch (cmd) {
4833  case CLI_INIT:
4834  e->command = "mgcp reload";
4835  e->usage =
4836  "Usage: mgcp reload\n"
4837  " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n";
4838  return NULL;
4839  case CLI_GENERATE:
4840  return NULL;
4841  }
4842  }
4843 
4844  if (!deprecated && a && a->argc > 0) {
4845  ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n");
4846  deprecated = 1;
4847  }
4848 
4850  if (mgcp_reloading) {
4851  ast_verbose("Previous mgcp reload not yet done\n");
4852  } else {
4853  mgcp_reloading = 1;
4854  }
4856  restart_monitor();
4857  return CLI_SUCCESS;
4858 }
4859 
4860 static int reload(void)
4861 {
4862  mgcp_reload(NULL, 0, NULL);
4863  return 0;
4864 }
4865 
4866 static int unload_module(void)
4867 {
4868  struct mgcp_endpoint *e;
4869  struct mgcp_gateway *g;
4870 
4871  /* Check to see if we're reloading */
4873  ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n");
4874  return -1;
4875  } else {
4876  mgcp_reloading = 1;
4878  }
4879 
4880  /* First, take us out of the channel loop */
4881  ast_channel_unregister(&mgcp_tech);
4882 
4883  /* Shut down the monitoring thread */
4884  if (!ast_mutex_lock(&monlock)) {
4885  if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
4886  pthread_cancel(monitor_thread);
4887  pthread_kill(monitor_thread, SIGURG);
4888  pthread_join(monitor_thread, NULL);
4889  }
4890  monitor_thread = AST_PTHREADT_STOP;
4892  } else {
4893  ast_log(LOG_WARNING, "Unable to lock the monitor\n");
4894  /* We always want to leave this in a consistent state */
4895  ast_channel_register(&mgcp_tech);
4896  mgcp_reloading = 0;
4897  mgcp_reload(NULL, 0, NULL);
4898  return -1;
4899  }
4900 
4901  if (!ast_mutex_lock(&gatelock)) {
4902  for (g = gateways; g; g = g->next) {
4903  g->delme = 1;
4904  for (e = g->endpoints; e; e = e->next) {
4905  e->delme = 1;
4906  }
4907  }
4908 
4909  prune_gateways();
4911  } else {
4912  ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
4913  /* We always want to leave this in a consistent state */
4914  ast_channel_register(&mgcp_tech);
4915  /* Allow the monitor to restart */
4916  monitor_thread = AST_PTHREADT_NULL;
4917  mgcp_reloading = 0;
4918  mgcp_reload(NULL, 0, NULL);
4919  return -1;
4920  }
4921 
4922  close(mgcpsock);
4923  ast_rtp_glue_unregister(&mgcp_rtp_glue);
4924  ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
4925  sched_context_destroy(sched);
4926 
4927  return 0;
4928 }
4929 
4930 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Media Gateway Control Protocol (MGCP)",
4931  .load = load_module,
4932  .unload = unload_module,
4933  .reload = reload,
4934  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
4935  .nonoptreq = "res_pktccops",
4936  );
static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
Definition: chan_mgcp.c:545
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:273
static const char *const mgcp_cxmodes[]
Definition: chan_mgcp.c:132
static char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:155
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1569
unsigned long long ast_group_t
Definition: channel.h:175
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
#define TYPE_LINE
Definition: chan_mgcp.c:323
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7051
static int adsi
Definition: chan_mgcp.c:201
static void start_rtp(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2928
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Definition: pbx.c:5420
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Definition: dsp.c:1392
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
Main Channel structure associated with a channel.
Definition: channel.h:742
static int slowsequence
Definition: chan_mgcp.c:182
Music on hold handling.
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
struct cops_gate * gate
Definition: chan_mgcp.c:315
static int mgcpsock
Definition: chan_mgcp.c:425
An event.
Definition: event.c:85
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp)
Definition: chan_mgcp.c:2758
static int dtmfmode
Definition: chan_mgcp.c:160
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
Definition: chan_mgcp.c:615
static ast_mutex_t gatelock
gatelock: mutex for gateway/endpoint lists
Definition: chan_mgcp.c:423
const char *const type
Definition: channel.h:508
static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
Definition: chan_mgcp.c:1243
Asterisk locking-related definitions:
char callid[80]
Definition: chan_mgcp.c:306
Asterisk main include file. File version handling, generic pbx functions.
int rings
Definition: channel.h:840
char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:333
unsigned int trid
Definition: chan_mgcp.c:258
static ast_group_t cur_pickupgroup
Definition: chan_mgcp.c:167
static int firstdigittimeout
Definition: chan_mgcp.c:207
char * str
Subscriber phone number (Malloced)
Definition: channel.h:336
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
char lastcallerid[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:335
static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
Definition: chan_mgcp.c:2181
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
Definition: channel.c:1601
struct ast_frame ast_null_frame
Definition: frame.c:131
char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:334
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int hascallwaiting
Definition: chan_mgcp.c:346
char * strsep(char **str, const char *delims)
static char * handle_mgcp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mgcp.c:1142
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1093
static int restart_monitor(void)
Definition: chan_mgcp.c:3892
int priority
Definition: channel.h:841
struct mgcp_endpoint * owner_ep
Definition: chan_mgcp.c:264
struct mgcp_request * cx_queue
Definition: chan_mgcp.c:308
#define TYPE_TRUNK
Definition: chan_mgcp.c:322
int state
Definition: pktccops.h:59
ast_mutex_t cmd_queue_lock
Definition: chan_mgcp.c:378
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:3972
#define ast_strdup(a)
Definition: astmm.h:109
void ast_rtp_instance_change_source(struct ast_rtp_instance *instance)
Indicate a new source of audio has dropped in and the ssrc should change.
Definition: rtp_engine.c:767
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int slowsequence
Definition: chan_mgcp.c:362
static unsigned int oseq_global
Definition: chan_mgcp.c:203
format_t writeformat
Definition: channel.h:854
struct mgcp_subchannel * sub
Definition: chan_mgcp.c:328
static unsigned int tos
Definition: chan_h323.c:146
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:422
static int * mgcpsock_read_id
Definition: chan_mgcp.c:3714
static int unalloc_sub(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:517
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
#define MAX_SUBS
Definition: chan_mgcp.c:284
int(* gate_remove)(struct cops_gate *gate)
Definition: pktccops.h:65
struct cops_gate * ast_pktccops_gate_alloc(int cmd, struct cops_gate *gate, uint32_t mta, uint32_t actcount, float bitrate, uint32_t psize, uint32_t ssip, uint16_t ssport, int(*const got_dq_gi)(struct cops_gate *gate), int(*const gate_remove)(struct cops_gate *gate))
Definition: res_pktccops.c:470
static char * mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mgcp.c:4827
#define DEFAULT_MGCP_GW_PORT
Definition: chan_mgcp.c:116
Device state management.
static int callwaiting
Definition: chan_mgcp.c:178
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
#define MAX_MUSICCLASS
Definition: channel.h:139
static struct ast_frame * mgcp_rtp_read(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:1202
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:89
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:938
int hidecallerid
Definition: chan_mgcp.c:355
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1650
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:338
void * tech_pvt
Definition: channel.h:744
static char * get_csv(char *c, int *len, char **next)
get_csv: (SC:) get comma separated value
Definition: chan_mgcp.c:1643
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
Channel Variables.
Convenient Signal Processing routines.
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define MGCP_DTMF_RFC2833
Definition: chan_mgcp.c:112
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:69
static char * get_header(struct mgcp_request *req, char *name)
Definition: chan_mgcp.c:1636
int ast_app_has_voicemail(const char *mailbox, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to &quot;INBOX&quot;. If folder is &quot;INBOX&quot;, includes the number of messages in the &quot;Urgent&quot; folder.
Definition: app.c:421
char * ast_get_encoded_str(const char *stream, char *result, size_t result_len)
Decode a stream of encoded control or extended ASCII characters.
Definition: app.c:2197
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:483
static void destroy_gateway(struct mgcp_gateway *g)
Definition: chan_mgcp.c:4534
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:485
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
struct mgcp_request * next
Definition: chan_mgcp.c:259
char * identifier
Definition: chan_mgcp.c:249
static int nat
Definition: chan_mgcp.c:161
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:577
int lineno
Definition: config.h:87
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
Definition: chan_mgcp.c:837
char dtmf_buf[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:336
struct ast_dsp * ast_dsp_new(void)
Definition: dsp.c:1607
#define AST_FRAME_DTMF
Definition: frame.h:128
time_t deltimer
Definition: pktccops.h:62
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
Definition: chan_mgcp.c:2334
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static const char config[]
Definition: chan_mgcp.c:110
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
Set QoS parameters on an RTP session.
Definition: rtp_engine.c:774
int cancallforward
Definition: chan_mgcp.c:350
#define var
Definition: ast_expr2f.c:606
#define MGCP_DTMF_INBAND
Definition: chan_mgcp.c:113
static int load_module(void)
load_module: PBX load module - initialization —
Definition: chan_mgcp.c:4794
#define AST_MAX_ACCOUNT_CODE
Definition: cdr.h:73
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:374
static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:632
static struct ast_frame * mgcp_read(struct ast_channel *ast)
Definition: chan_mgcp.c:1233
char call_forward[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:337
format_t rawwriteformat
Definition: channel.h:856
static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
Definition: chan_mgcp.c:569
#define ast_rtp_glue_register(glue)
Definition: rtp_engine.h:476
static int mgcp_senddigit_begin(struct ast_channel *ast, char digit)
Definition: chan_mgcp.c:1300
static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
Definition: chan_mgcp.c:2139
#define AST_IO_IN
Definition: io.h:33
static int unload_module(void)
Definition: chan_mgcp.c:4866
static char ourhost[MAXHOSTNAMELEN]
Definition: chan_mgcp.c:231
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
Definition: channel.c:8415
Definition: cli.h:146
ast_mutex_t lock
Definition: chan_mgcp.c:297
struct ast_event * ast_event_get_cached(enum ast_event_type,...)
Retrieve an event from the cache.
Definition: event.c:1342
#define MGCP_CX_MUTE
Definition: chan_mgcp.c:128
static int mgcpdebug
Definition: chan_mgcp.c:235
static int callreturn
Definition: chan_mgcp.c:180
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:8650
Configuration File Parser.
int ast_netsock_set_qos(int netsocket, int tos, int cos, const char *desc)
Definition: netsock.c:158
char * str
Subscriber name (Malloced)
Definition: channel.h:214
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:157
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: config.c:2548
static void sdpLineNum_iterator_init(int *iterator)
Definition: chan_mgcp.c:1600
static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
Definition: chan_mgcp.c:2492
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
Definition: channel.c:1062
ast_group_t pickupgroup
Definition: chan_mgcp.c:344
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
struct sockaddr_in tmpdest
Definition: chan_mgcp.c:302
int(* gate_open)(struct cops_gate *gate)
Definition: pktccops.h:66
Number of new messages Used by: AST_EVENT_MWI Payload type: UINT.
Definition: event_defs.h:71
#define ast_mutex_lock(a)
Definition: lock.h:155
char curtone[80]
Definition: chan_mgcp.c:339
char rqnt_ident[80]
Definition: chan_mgcp.c:374
char * verb
Definition: chan_mgcp.c:248
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:907
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:2729
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
format_t nativeformats
Definition: channel.h:852
#define MAXHOSTNAMELEN
Definition: network.h:69
char * endpoint
Definition: chan_mgcp.c:250
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
Definition: acl.c:667
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, format_t codecs, int nat_active)
Definition: chan_mgcp.c:4430
const char * ast_state2str(enum ast_channel_state)
Gives the string form of a given channel state.
Definition: channel.c:1007
#define MGCP_ONHOOK
Definition: chan_mgcp.c:319
format_t codec
Definition: frame.h:137
const char * data
Definition: channel.h:755
static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
Definition: chan_mgcp.c:2154
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: features.c:7380
void * tech_pvt
Definition: pktccops.h:67
I/O Management (derived from Cheops-NG)
Common implementation-independent jitterbuffer stuff.
int value
Definition: syslog.c:39
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
struct mgcp_subchannel * next
Definition: chan_mgcp.c:316
const ast_string_field linkedid
Definition: channel.h:787
static struct ast_channel * mgcp_new(struct mgcp_subchannel *sub, int state, const char *linkedid)
Definition: chan_mgcp.c:1494
enum ast_channel_adsicpe adsicpe
Definition: channel.h:844
format_t rawreadformat
Definition: channel.h:855
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
Socket address structure.
Definition: netsock2.h:63
ast_mutex_t msgs_lock
Definition: chan_mgcp.c:411
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:157
ast_group_t pickupgroup
Definition: channel.h:819
#define ast_verb(level,...)
Definition: logger.h:243
static int transfer
Definition: chan_mgcp.c:187
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
const char * type
Definition: rtp_engine.h:395
static int transmit_audit_endpoint(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:2637
ast_group_t callgroup
Definition: channel.h:818
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:5415
static int threewaycalling
Definition: chan_mgcp.c:184
static void * do_monitor(void *data)
Definition: chan_mgcp.c:3774
static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
Definition: chan_mgcp.c:3268
#define MAX_LANGUAGE
Definition: channel.h:138
String fields in structures.
static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
Definition: chan_mgcp.c:1440
Utility functions.
int args
This gets set in ast_cli_register()
Definition: cli.h:179
static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_mgcp.c:1321
static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
Definition: chan_mgcp.c:2674
static const char * mbox(struct ast_vm_user *vmu, int id)
int hangupongateremove
Definition: chan_mgcp.c:360
static int cancallforward
Definition: chan_mgcp.c:189
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:426
mgcp_message: MGCP message for queuing up
Definition: chan_mgcp.c:263
static void prune_gateways(void)
Definition: chan_mgcp.c:4544
struct mgcp_response * responses
Definition: chan_mgcp.c:415
static char * handle_mgcp_show_endpoints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mgcp.c:1039
#define DEFAULT_MGCP_CA_PORT
Definition: chan_mgcp.c:117
internal representation of acl entries In principle user applications would have no need for this...
Definition: acl.h:48
Call Detail Record API.
#define AST_RTP_MAX
Definition: rtp_engine.h:224
char language[MAX_LANGUAGE]
Definition: chan_mgcp.c:332
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
char wcardep[30]
Definition: chan_mgcp.c:409
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
static void * mgcp_ss(void *data)
Definition: chan_mgcp.c:2961
char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:341
static ast_mutex_t netlock
Definition: chan_mgcp.c:217
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
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:705
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char name[80]
Definition: chan_mgcp.c:327
Context IE Used by AST_EVENT_MWI Payload type: str.
Definition: event_defs.h:121
const char * value
Definition: config.h:79
static int immediate
Definition: chan_mgcp.c:176
struct ast_module * self
Definition: module.h:227
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:377
struct in_addr ourip
Definition: chan_mgcp.c:398
static int mgcp_prune_realtime_gateway(struct mgcp_gateway *g)
Definition: chan_mgcp.c:3716
General Asterisk PBX channel definitions.
struct ast_party_dialed::@155 number
Dialed/Called number.
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
void io_context_destroy(struct io_context *ioc)
Destroys a context.
Definition: io.c:102
const char * src
Definition: frame.h:158
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:642
#define ast_mutex_trylock(a)
Definition: lock.h:157
Network socket handling.
const int fd
Definition: cli.h:153
#define AST_FORMAT_ALAW
Definition: frame.h:248
Definition: dsp.c:390
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
#define AST_PTHREADT_NULL
Definition: lock.h:65
struct sockaddr_in defaddr
Definition: chan_mgcp.c:397
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define MGCP_MAX_LINES
Definition: chan_mgcp.c:244
static int reload_config(int reload)
Definition: chan_mgcp.c:4619
static void destroy_endpoint(struct mgcp_endpoint *e)
Definition: chan_mgcp.c:4477
struct ast_variable * chanvars
Definition: chan_mgcp.c:387
Access Control of various sorts.
#define MGCP_OFFHOOK
Definition: chan_mgcp.c:320
Global IO variables are now in a struct in order to be made threadsafe.
Definition: io.c:66
static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2416
#define AST_MAX_EXTENSION
Definition: channel.h:135
static int transmit_connect(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2430
int datalen
Definition: frame.h:148
Scheduler Routines (derived from cheops)
struct mgcp_gateway * next
Definition: chan_mgcp.c:416
int tm_mon
Definition: localtime.h:40
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
#define MGCP_CX_SENDRECV
Definition: chan_mgcp.c:125
struct ast_channel * owner
Definition: chan_mgcp.c:299
#define MGCP_DTMF_HYBRID
Definition: chan_mgcp.c:114
long int ast_random(void)
Definition: utils.c:1640
struct mgcp_request * rqnt_queue
Definition: chan_mgcp.c:375
static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
Definition: chan_mgcp.c:1956
static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: chan_mgcp.c:1284
unsigned int cos_audio
Definition: chan_mgcp.c:173
char buf[0]
Definition: chan_mgcp.c:271
int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.c:391
static int amaflags
Definition: chan_mgcp.c:199
struct mgcp_message * msgs
Definition: chan_mgcp.c:410
static struct io_context * io
Definition: chan_mgcp.c:238
char name[80]
Definition: chan_mgcp.c:394
const char * name
Definition: config.h:77
static struct ast_channel_tech mgcp_tech
Definition: chan_mgcp.c:464
#define DIRECTMEDIA
Definition: chan_mgcp.c:91
static int reload(void)
Definition: chan_mgcp.c:4860
int nonCodecCapability
Definition: chan_mgcp.c:368
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7987
int tm_mday
Definition: localtime.h:39
PacketCable COPS.
static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno)
Definition: chan_mgcp.c:710
static int transmit_connection_del(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2651
int isnamedottedip
Definition: chan_mgcp.c:395
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
ast_rtp_glue_result
Definition: rtp_engine.h:125
char context[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:331
ast_group_t callgroup
Definition: chan_mgcp.c:343
static int mgcp_devicestate(void *data)
mgcp_devicestate: channel callback for device status monitoring
Definition: chan_mgcp.c:1362
int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options)
Record payload information that was seen in an a=rtpmap: SDP line.
Definition: rtp_engine.c:597
Structure to describe a channel &quot;technology&quot;, ie a channel driver See for examples: ...
Definition: channel.h:507
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_mgcp.c:329
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1558
struct ast_dsp * dsp
Definition: chan_mgcp.c:381
static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
Definition: chan_mgcp.c:558
int threewaycalling
Definition: chan_mgcp.c:348
struct ast_event_sub * mwi_event_sub
Definition: chan_mgcp.c:342
static struct sched_context * sched
Definition: chan_gtalk.c:227
Definition: logger.c:927
const char *const * argv
Definition: cli.h:155
static char language[MAX_LANGUAGE]
Definition: chan_mgcp.c:154
struct ast_party_dialed dialed
Dialed/Called information.
Definition: channel.h:797
static int gendigittimeout
Definition: chan_mgcp.c:210
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
format_t ast_getformatbyname(const char *name)
Gets a format from a name.
Definition: frame.c:641
static pthread_t monitor_thread
Definition: chan_mgcp.c:224
struct mgcp_response * next
Definition: chan_mgcp.c:280
char exten[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:330
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
static ast_mutex_t monlock
Definition: chan_mgcp.c:219
static struct ast_variable * add_var(const char *buf, struct ast_variable *list)
Definition: chan_mgcp.c:4587
uint32_t gateid
Definition: pktccops.h:55
#define LOG_ERROR
Definition: logger.h:155
static int nonCodecCapability
Definition: chan_mgcp.c:229
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void sched_context_destroy(struct sched_context *c)
destroys a schedule context Destroys (free&#39;s) the given sched_context structure
Definition: sched.c:267
int64_t format_t
Definition: frame_defs.h:32
#define free(a)
Definition: astmm.h:94
#define DEFAULT_RETRANS
Definition: chan_mgcp.c:119
static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone)
Definition: chan_mgcp.c:2609
static struct @350 args
ast_mutex_t cx_queue_lock
Definition: chan_mgcp.c:309
#define CLI_SHOWUSAGE
Definition: cli.h:44
static enum ast_rtp_glue_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
Definition: chan_mgcp.c:4415
int pktcgatealloc
Definition: chan_mgcp.c:359
struct mgcp_gateway * parent
Definition: chan_mgcp.c:389
static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb, unsigned int oseq)
Definition: chan_mgcp.c:2108
#define AST_FORMAT_ULAW
Definition: frame.h:246
#define MGCP_MAX_PACKET
Definition: chan_mgcp.c:118
static void mwi_event_cb(const struct ast_event *event, void *userdata)
Definition: chan_mgcp.c:484
Event subscription.
Definition: event.c:124
static int mgcp_reloading
Definition: chan_mgcp.c:420
static int attempt_transfer(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:3214
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define RESPONSE_TIMEOUT
Definition: chan_mgcp.c:274
int ast_cdr_amaflags2int(const char *flag)
Convert a string to a detail record AMA flag.
Definition: cdr.c:1105
enum ast_channel_state _state
Definition: channel.h:839
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
#define INADDR_NONE
Definition: chan_mgcp.c:94
ast_mutex_t lock
Definition: chan_mgcp.c:326
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
Begin sending a DTMF digit.
Definition: rtp_engine.c:736
const ast_string_field name
Definition: channel.h:787
char cxident[80]
Definition: chan_mgcp.c:305
static int singlepath
Definition: chan_mgcp.c:191
static char * get_sdp_by_line(char *line, char *name, int nameLen)
Definition: chan_mgcp.c:1577
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
struct sockaddr_in addr
Definition: chan_mgcp.c:396
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int ncs
Definition: chan_mgcp.c:162
int _softhangup
Definition: channel.h:832
int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
Get the IP address given a hostname.
Definition: acl.c:700
#define LOG_NOTICE
Definition: logger.h:133
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static struct ast_jb_conf global_jbconf
Definition: chan_mgcp.c:107
#define ast_channel_unlock(chan)
Definition: channel.h:2467
int errno
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
char buf[0]
Definition: chan_mgcp.c:281
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1642
static const char name[]
#define AST_MAX_CONTEXT
Definition: channel.h:136
struct ast_var_t::@158 entries
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
#define AST_CAUSE_UNREGISTERED
Definition: causes.h:153
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
unsigned long expire
Definition: chan_mgcp.c:267
#define AST_FORMAT_AUDIO_MASK
Definition: frame.h:274
void ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.c:447
ast_mutex_t rqnt_queue_lock
Definition: chan_mgcp.c:376
int ast_str2cos(const char *value, unsigned int *cos)
Convert a string to the appropriate COS value.
Definition: acl.c:653
static char * handle_mgcp_audit_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mgcp.c:1081
static struct ast_format f[]
Definition: format_g726.c:181
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
Definition: rtp_engine.c:786
static format_t capability
Definition: chan_mgcp.c:228
#define MGCP_MAX_HEADERS
Definition: chan_mgcp.c:243
static ast_group_t cur_callergroup
Definition: chan_mgcp.c:166
struct ast_ha * ha
Definition: chan_mgcp.c:402
format_t capability
Definition: chan_mgcp.c:367
char txident[80]
Definition: chan_mgcp.c:303
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:308
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const format_t code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:673
static int pktcgatealloc
Definition: chan_mgcp.c:163
struct mgcp_request * cmd_queue
Definition: chan_mgcp.c:377
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:58
static struct mgcp_gateway * gateways
int tm_hour
Definition: localtime.h:38
static struct mgcp_subchannel * find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
Definition: chan_mgcp.c:1758
char magic[6]
Definition: chan_mgcp.c:296
static const char type[]
Definition: chan_nbs.c:57
static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
dump_cmd_queues: (SC:) cleanup pending commands
Definition: chan_mgcp.c:2695
void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
Clear payload information from an RTP instance.
Definition: rtp_engine.c:488
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:430
Structure used to handle boolean flags.
Definition: utils.h:200
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:301
struct ast_rtp_instance * rtp
Definition: chan_mgcp.c:301
static int directmedia
Definition: chan_mgcp.c:193
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2631
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Definition: io.c:240
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:158
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:616
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_mgcp.c:195
int ast_sched_runq(struct sched_context *con)
Runs the queue.
Definition: sched.c:600
const char * usage
Definition: cli.h:171
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
static struct sockaddr_in bindaddr
Definition: chan_gtalk.c:225
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
Definition: event.c:1075
static struct ast_channel * mgcp_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
Definition: chan_mgcp.c:3921
struct mgcp_endpoint * parent
Definition: chan_mgcp.c:300
static struct ast_variable * copy_vars(struct ast_variable *src)
duplicate a list of channel variables,
Definition: chan_mgcp.c:4605
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
static char * __get_header(struct mgcp_request *req, char *name, int *start, char *def)
Definition: chan_mgcp.c:1616
static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
Definition: chan_mgcp.c:2464
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:223
#define CLI_SUCCESS
Definition: cli.h:43
#define AST_CAUSE_REQUESTED_CHAN_UNAVAIL
Definition: causes.h:124
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
Definition: utils.c:195
void ast_event_destroy(struct ast_event *event)
Destroy an event.
Definition: event.c:1314
static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen)
Definition: chan_mgcp.c:4457
struct sched_context * sched_context_create(void)
New schedule context.
Definition: sched.c:246
Channels have this property if they can create jitter; i.e. most VoIP channels.
Definition: channel.h:888
static int hangupongateremove
Definition: chan_mgcp.c:164
static struct ast_cli_entry cli_mgcp[]
Definition: chan_mgcp.c:1170
static int has_voicemail(struct mgcp_endpoint *p)
Definition: chan_mgcp.c:492
unsigned int tos_audio
Definition: chan_mgcp.c:171
Standard Command Line Interface.
static int mgcp_answer(struct ast_channel *ast)
Definition: chan_mgcp.c:1177
format_t readformat
Definition: channel.h:853
#define ast_calloc(a, b)
Definition: astmm.h:82
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
Definition: event.c:909
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static format_t mgcp_get_codec(struct ast_channel *chan)
Definition: chan_mgcp.c:4442
static ast_mutex_t mgcp_reload_lock
Definition: chan_mgcp.c:419
#define MAX_RETRANS
Definition: chan_mgcp.c:120
int(* got_dq_gi)(struct cops_gate *gate)
Definition: pktccops.h:64
static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
Definition: chan_mgcp.c:3595
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static struct ast_rtp_glue mgcp_rtp_glue
Definition: chan_mgcp.c:4449
static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
Definition: chan_mgcp.c:754
int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place Determine the number of s...
Definition: sched.c:334
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
#define AST_PTHREADT_STOP
Definition: lock.h:66
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Definition: rtp_engine.c:266
static char context[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:152
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define AST_CAUSE_BUSY
Definition: causes.h:148
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:5926
char * ast_getformatname_multiple(char *buf, size_t size, format_t format)
Get the names of a set of formats.
Definition: frame.c:591
char * line[MGCP_MAX_LINES]
Definition: chan_mgcp.c:255
Data structure associated with a single frame of data.
Definition: frame.h:142
Internal Asterisk hangup causes.
static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
Definition: chan_mgcp.c:649
int ast_masq_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
Park a call via a masqueraded channel.
Definition: features.c:1803
static int mgcp_pktcgate_open(struct cops_gate *gate)
Definition: chan_mgcp.c:2403
char * header[MGCP_MAX_HEADERS]
Definition: chan_mgcp.c:253
static struct mgcp_gateway * find_realtime_gw(char *name, char *at, struct sockaddr_in *sin)
Definition: chan_mgcp.c:1667
struct mgcp_message * next
Definition: chan_mgcp.c:270
static char * get_sdp_iterate(int *iterator, struct mgcp_request *req, char *name)
Definition: chan_mgcp.c:1605
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:399
static char * control2str(int ind)
Definition: chan_mgcp.c:1408
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:260
static int mgcp_pktcgate_remove(struct cops_gate *gate)
Definition: chan_mgcp.c:2380
static ast_mutex_t oseq_lock
Definition: chan_mgcp.c:204
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
Definition: channel.h:883
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:469
#define MGCP_CX_INACTIVE
Definition: chan_mgcp.c:129
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:629
static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, format_t codecs)
Definition: chan_mgcp.c:2276
static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
Definition: chan_mgcp.c:3350
int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
Determine if parking extension exists in a given context.
Definition: features.c:844
struct mgcp_endpoint * endpoints
Definition: chan_mgcp.c:401
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
enum ast_frame_type frametype
Definition: frame.h:144
struct ast_variable * next
Definition: config.h:82
static int mgcp_hangup(struct ast_channel *ast)
Definition: chan_mgcp.c:922
static int add_line(struct mgcp_request *req, char *line)
Definition: chan_mgcp.c:2067
#define DSP_DIGITMODE_NOQUELCH
Definition: dsp.h:34
static struct adsi_event events[]
Definition: app_adsiprog.c:78
#define MGCP_CX_CONF
Definition: chan_mgcp.c:126
#define ast_mutex_init(pmutex)
Definition: lock.h:152
#define ast_channel_trylock(chan)
Definition: channel.h:2468
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static int matchdigittimeout
Definition: chan_mgcp.c:213
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
#define ast_mutex_destroy(a)
Definition: lock.h:154
struct mgcp_endpoint * next
Definition: chan_mgcp.c:388
#define MGCP_SUBCHANNEL_MAGIC
Definition: chan_mgcp.c:295
static unsigned int cos
Definition: chan_h323.c:147
static char * get_sdp(struct mgcp_request *req, char *name)
Definition: chan_mgcp.c:1587
unsigned int seqno
Definition: chan_mgcp.c:268
static struct in_addr __ourip
Definition: chan_mgcp.c:232
static const char tdesc[]
Definition: chan_mgcp.c:109
static struct ast_jb_conf default_jbconf
Definition: chan_mgcp.c:99
Say numbers and dates (maybe words one day too)
static int transmit_modify_request(struct mgcp_subchannel *sub)
Definition: chan_mgcp.c:2537
#define AST_RTP_DTMF
Definition: rtp_engine.h:218
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Pluggable RTP Architecture.
#define MGCP_CX_RECVONLY
Definition: chan_mgcp.c:124
void ast_rtp_instance_update_source(struct ast_rtp_instance *instance)
Indicate that the RTP marker bit should be set on an RTP stream.
Definition: rtp_engine.c:760
#define ast_malloc(a)
Definition: astmm.h:91
char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:340
Asterisk module definitions.
static int mgcpsock_read(int *id, int fd, short events, void *ignore)
Definition: chan_mgcp.c:3625
static struct hostent * hp
Definition: chan_skinny.c:1048
int amaflags
Definition: channel.h:843
static snd_pcm_format_t format
Definition: chan_alsa.c:93
union ast_frame::@172 data
struct ast_channel_tech * tech
Definition: channel.h:743
char data[MGCP_MAX_PACKET]
Definition: chan_mgcp.c:256
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const format_t code)
Retrieve a payload based on whether it is an Asterisk format and the code.
Definition: rtp_engine.c:654
Persistant data storage (akin to *doze registry)
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
Definition: event.c:987
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
static int ourport
Definition: chan_mgcp.c:233
General jitterbuffer configuration.
Definition: abstract_jb.h:55
void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
Record payload information that was seen in an m= SDP line.
Definition: rtp_engine.c:532
struct varshead varshead
Definition: channel.h:817
static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
Definition: chan_mgcp.c:2090
const ast_string_field language
Definition: channel.h:787
static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
Definition: chan_mgcp.c:581
static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
Definition: chan_mgcp.c:2132
static int retrans_pkt(const void *data)
Definition: chan_mgcp.c:655
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
const char * ast_pickup_ext(void)
Determine system call pickup extension.
Definition: features.c:849
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
Definition: config.c:278
static struct @97 qos
int tm_min
Definition: localtime.h:37
Structure for mutex and tracking information.
Definition: lock.h:121
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1739
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, format_t *astformats, int *nonastformats)
Retrieve all formats that were found.
Definition: rtp_engine.c:636
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:379
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
Mailbox name.
Definition: event_defs.h:83
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int add_header(struct mgcp_request *req, const char *var, const char *value)
Definition: chan_mgcp.c:2045
char * version
Definition: chan_mgcp.c:251
enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
Bridge two channels that use RTP instances.
Definition: rtp_engine.c:1274
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: config.c:2587
time_t whensent
Definition: chan_mgcp.c:277
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit)
Stop sending a DTMF digit.
Definition: rtp_engine.c:741
struct mgcp_subchannel * owner_sub
Definition: chan_mgcp.c:265
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...
Definition: io.c:76