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