remove documentation of 'global' section in modules.conf, since it is no longer neede...
[asterisk-bristuff.git] / channels / chan_mgcp.c
blob94cb20f022bd69ad41ccbdbbb1508637daa6fd5c
1 /*
2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
19 /*! \file
21 * \brief Implementation of Media Gateway Control Protocol
23 * \author Mark Spencer <markster@digium.com>
25 * \par See also
26 * \arg \ref Config_mgcp
28 * \ingroup channel_drivers
31 #include "asterisk.h"
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35 #include <stdio.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <sys/socket.h>
39 #include <sys/ioctl.h>
40 #include <net/if.h>
41 #include <errno.h>
42 #include <stdlib.h>
43 #include <fcntl.h>
44 #include <netdb.h>
45 #include <sys/signal.h>
46 #include <signal.h>
47 #include <netinet/in.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/ip.h>
50 #include <arpa/inet.h>
51 #include <ctype.h>
53 #include "asterisk/lock.h"
54 #include "asterisk/channel.h"
55 #include "asterisk/config.h"
56 #include "asterisk/logger.h"
57 #include "asterisk/module.h"
58 #include "asterisk/pbx.h"
59 #include "asterisk/options.h"
60 #include "asterisk/lock.h"
61 #include "asterisk/sched.h"
62 #include "asterisk/io.h"
63 #include "asterisk/rtp.h"
64 #include "asterisk/acl.h"
65 #include "asterisk/callerid.h"
66 #include "asterisk/cli.h"
67 #include "asterisk/say.h"
68 #include "asterisk/cdr.h"
69 #include "asterisk/astdb.h"
70 #include "asterisk/features.h"
71 #include "asterisk/app.h"
72 #include "asterisk/musiconhold.h"
73 #include "asterisk/utils.h"
74 #include "asterisk/causes.h"
75 #include "asterisk/dsp.h"
76 #include "asterisk/devicestate.h"
77 #include "asterisk/stringfields.h"
78 #include "asterisk/abstract_jb.h"
80 #ifndef IPTOS_MINCOST
81 #define IPTOS_MINCOST 0x02
82 #endif
85 * Define to work around buggy dlink MGCP phone firmware which
86 * appears not to know that "rt" is part of the "G" package.
88 /* #define DLINK_BUGGY_FIRMWARE */
90 #define MGCPDUMPER
91 #define DEFAULT_EXPIRY 120
92 #define MAX_EXPIRY 3600
93 #define CANREINVITE 1
95 #ifndef INADDR_NONE
96 #define INADDR_NONE (in_addr_t)(-1)
97 #endif
99 /*! Global jitterbuffer configuration - by default, jb is disabled */
100 static struct ast_jb_conf default_jbconf =
102 .flags = 0,
103 .max_size = -1,
104 .resync_threshold = -1,
105 .impl = ""
107 static struct ast_jb_conf global_jbconf;
109 static const char tdesc[] = "Media Gateway Control Protocol (MGCP)";
110 static const char config[] = "mgcp.conf";
112 #define MGCP_DTMF_RFC2833 (1 << 0)
113 #define MGCP_DTMF_INBAND (1 << 1)
114 #define MGCP_DTMF_HYBRID (1 << 2)
116 #define DEFAULT_MGCP_GW_PORT 2427 /*!< From RFC 2705 */
117 #define DEFAULT_MGCP_CA_PORT 2727 /*!< From RFC 2705 */
118 #define MGCP_MAX_PACKET 1500 /*!< Also from RFC 2543, should sub headers tho */
119 #define DEFAULT_RETRANS 1000 /*!< How frequently to retransmit */
120 #define MAX_RETRANS 5 /*!< Try only 5 times for retransmissions */
122 /*! MGCP rtp stream modes { */
123 #define MGCP_CX_SENDONLY 0
124 #define MGCP_CX_RECVONLY 1
125 #define MGCP_CX_SENDRECV 2
126 #define MGCP_CX_CONF 3
127 #define MGCP_CX_CONFERENCE 3
128 #define MGCP_CX_MUTE 4
129 #define MGCP_CX_INACTIVE 4
130 /*! } */
132 static char *mgcp_cxmodes[] = {
133 "sendonly",
134 "recvonly",
135 "sendrecv",
136 "confrnce",
137 "inactive"
140 enum {
141 MGCP_CMD_EPCF,
142 MGCP_CMD_CRCX,
143 MGCP_CMD_MDCX,
144 MGCP_CMD_DLCX,
145 MGCP_CMD_RQNT,
146 MGCP_CMD_NTFY,
147 MGCP_CMD_AUEP,
148 MGCP_CMD_AUCX,
149 MGCP_CMD_RSIP
152 static char context[AST_MAX_EXTENSION] = "default";
154 static char language[MAX_LANGUAGE] = "";
155 static char musicclass[MAX_MUSICCLASS] = "";
156 static char cid_num[AST_MAX_EXTENSION] = "";
157 static char cid_name[AST_MAX_EXTENSION] = "";
159 static int dtmfmode = 0;
160 static int nat = 0;
162 static ast_group_t cur_callergroup = 0;
163 static ast_group_t cur_pickupgroup = 0;
165 static int tos = 0;
167 static int immediate = 0;
169 static int callwaiting = 0;
171 static int callreturn = 0;
173 static int slowsequence = 0;
175 static int threewaycalling = 0;
177 /*! This is for flashhook transfers */
178 static int transfer = 0;
180 static int cancallforward = 0;
182 static int singlepath = 0;
184 static int canreinvite = CANREINVITE;
186 static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
188 static char mailbox[AST_MAX_EXTENSION];
190 static int amaflags = 0;
192 static int adsi = 0;
194 static unsigned int oseq;
196 /*! Wait up to 16 seconds for first digit (FXO logic) */
197 static int firstdigittimeout = 16000;
199 /*! How long to wait for following digits (FXO logic) */
200 static int gendigittimeout = 8000;
202 /*! How long to wait for an extra digit, if there is an ambiguous match */
203 static int matchdigittimeout = 3000;
205 /*! Protect the monitoring thread, so only one process can kill or start it, and not
206 when it's doing something critical. */
207 AST_MUTEX_DEFINE_STATIC(netlock);
209 AST_MUTEX_DEFINE_STATIC(monlock);
211 /*! This is the thread for the monitor which checks for input on the channels
212 which are not currently in use. */
213 static pthread_t monitor_thread = AST_PTHREADT_NULL;
215 static int restart_monitor(void);
217 static int capability = AST_FORMAT_ULAW;
218 static int nonCodecCapability = AST_RTP_DTMF;
220 static char ourhost[MAXHOSTNAMELEN];
221 static struct in_addr __ourip;
222 static int ourport;
224 static int mgcpdebug = 0;
226 static struct sched_context *sched;
227 static struct io_context *io;
228 /*! The private structures of the mgcp channels are linked for
229 ! selecting outgoing channels */
231 #define MGCP_MAX_HEADERS 64
232 #define MGCP_MAX_LINES 64
234 struct mgcp_request {
235 int len;
236 char *verb;
237 char *identifier;
238 char *endpoint;
239 char *version;
240 int headers; /*!< MGCP Headers */
241 char *header[MGCP_MAX_HEADERS];
242 int lines; /*!< SDP Content */
243 char *line[MGCP_MAX_LINES];
244 char data[MGCP_MAX_PACKET];
245 int cmd; /*!< int version of verb = command */
246 unsigned int trid; /*!< int version of identifier = transaction id */
247 struct mgcp_request *next; /*!< next in the queue */
250 /*! \brief mgcp_message: MGCP message for queuing up */
251 struct mgcp_message {
252 struct mgcp_endpoint *owner_ep;
253 struct mgcp_subchannel *owner_sub;
254 int retrans;
255 unsigned long expire;
256 unsigned int seqno;
257 int len;
258 struct mgcp_message *next;
259 char buf[0];
262 #define RESPONSE_TIMEOUT 30 /*!< in seconds */
264 struct mgcp_response {
265 time_t whensent;
266 int len;
267 int seqno;
268 struct mgcp_response *next;
269 char buf[0];
272 #define MAX_SUBS 2
274 #define SUB_REAL 0
275 #define SUB_ALT 1
277 struct mgcp_subchannel {
278 /*! subchannel magic string.
279 Needed to prove that any subchannel pointer passed by asterisk
280 really points to a valid subchannel memory area.
281 Ugly.. But serves the purpose for the time being.
283 #define MGCP_SUBCHANNEL_MAGIC "!978!"
284 char magic[6];
285 ast_mutex_t lock;
286 int id;
287 struct ast_channel *owner;
288 struct mgcp_endpoint *parent;
289 struct ast_rtp *rtp;
290 struct sockaddr_in tmpdest;
291 char txident[80]; /*! \todo FIXME txident is replaced by rqnt_ident in endpoint.
292 This should be obsoleted */
293 char cxident[80];
294 char callid[80];
295 int cxmode;
296 struct mgcp_request *cx_queue; /*!< pending CX commands */
297 ast_mutex_t cx_queue_lock; /*!< CX queue lock */
298 int nat;
299 int iseq; /*!< Not used? RTP? */
300 int outgoing;
301 int alreadygone;
302 struct mgcp_subchannel *next; /*!< for out circular linked list */
305 #define MGCP_ONHOOK 1
306 #define MGCP_OFFHOOK 2
308 #define TYPE_TRUNK 1
309 #define TYPE_LINE 2
311 struct mgcp_endpoint {
312 ast_mutex_t lock;
313 char name[80];
314 struct mgcp_subchannel *sub; /*!< Pointer to our current connection, channel and stuff */
315 char accountcode[AST_MAX_ACCOUNT_CODE];
316 char exten[AST_MAX_EXTENSION]; /*!< Extention where to start */
317 char context[AST_MAX_EXTENSION];
318 char language[MAX_LANGUAGE];
319 char cid_num[AST_MAX_EXTENSION]; /*!< Caller*ID number */
320 char cid_name[AST_MAX_EXTENSION]; /*!< Caller*ID name */
321 char lastcallerid[AST_MAX_EXTENSION]; /*!< Last Caller*ID */
322 char call_forward[AST_MAX_EXTENSION]; /*!< Last Caller*ID */
323 char mailbox[AST_MAX_EXTENSION];
324 char musicclass[MAX_MUSICCLASS];
325 char curtone[80]; /*!< Current tone */
326 ast_group_t callgroup;
327 ast_group_t pickupgroup;
328 int callwaiting;
329 int hascallwaiting;
330 int transfer;
331 int threewaycalling;
332 int singlepath;
333 int cancallforward;
334 int canreinvite;
335 int callreturn;
336 int dnd; /* How does this affect callwait? Do we just deny a mgcp_request if we're dnd? */
337 int hascallerid;
338 int hidecallerid;
339 int dtmfmode;
340 int amaflags;
341 int type;
342 int slowsequence; /*!< MS: Sequence the endpoint as a whole */
343 int group;
344 int iseq; /*!< Not used? */
345 int lastout; /*!< tracking this on the subchannels. Is it needed here? */
346 int needdestroy; /*!< Not used? */
347 int capability;
348 int nonCodecCapability;
349 int onhooktime;
350 int msgstate; /*!< voicemail message state */
351 int immediate;
352 int hookstate;
353 int adsi;
354 char rqnt_ident[80]; /*!< request identifier */
355 struct mgcp_request *rqnt_queue; /*!< pending RQNT commands */
356 ast_mutex_t rqnt_queue_lock;
357 struct mgcp_request *cmd_queue; /*!< pending commands other than RQNT */
358 ast_mutex_t cmd_queue_lock;
359 int delme; /*!< needed for reload */
360 int needaudit; /*!< needed for reload */
361 struct ast_dsp *dsp; /*!< XXX Should there be a dsp/subchannel? XXX */
362 /* owner is tracked on the subchannels, and the *sub indicates whos in charge */
363 /* struct ast_channel *owner; */
364 /* struct ast_rtp *rtp; */
365 /* struct sockaddr_in tmpdest; */
366 /* message go the the endpoint and not the channel so they stay here */
367 struct mgcp_endpoint *next;
368 struct mgcp_gateway *parent;
371 static struct mgcp_gateway {
372 /* A gateway containing one or more endpoints */
373 char name[80];
374 int isnamedottedip; /*!< is the name FQDN or dotted ip */
375 struct sockaddr_in addr;
376 struct sockaddr_in defaddr;
377 struct in_addr ourip;
378 int dynamic;
379 int expire; /*!< XXX Should we ever expire dynamic registrations? XXX */
380 struct mgcp_endpoint *endpoints;
381 struct ast_ha *ha;
382 /* obsolete
383 time_t lastouttime;
384 int lastout;
385 int messagepending;
387 /* Wildcard endpoint name */
388 char wcardep[30];
389 struct mgcp_message *msgs; /*!< gw msg queue */
390 ast_mutex_t msgs_lock; /*!< queue lock */
391 int retransid; /*!< retrans timer id */
392 int delme; /*!< needed for reload */
393 struct mgcp_response *responses;
394 struct mgcp_gateway *next;
395 } *gateways;
397 AST_MUTEX_DEFINE_STATIC(mgcp_reload_lock);
398 static int mgcp_reloading = 0;
400 /*! \brief gatelock: mutex for gateway/endpoint lists */
401 AST_MUTEX_DEFINE_STATIC(gatelock);
403 static int mgcpsock = -1;
405 static struct sockaddr_in bindaddr;
407 static struct ast_frame *mgcp_read(struct ast_channel *ast);
408 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
409 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
410 static int transmit_modify_request(struct mgcp_subchannel *sub);
411 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
412 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs);
413 static int transmit_connection_del(struct mgcp_subchannel *sub);
414 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
415 static void start_rtp(struct mgcp_subchannel *sub);
416 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
417 int result, unsigned int ident, struct mgcp_request *resp);
418 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
419 static int mgcp_do_reload(void);
420 static int mgcp_reload(int fd, int argc, char *argv[]);
422 static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause);
423 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout);
424 static int mgcp_hangup(struct ast_channel *ast);
425 static int mgcp_answer(struct ast_channel *ast);
426 static struct ast_frame *mgcp_read(struct ast_channel *ast);
427 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame);
428 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
429 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
430 static int mgcp_senddigit(struct ast_channel *ast, char digit);
431 static int mgcp_devicestate(void *data);
433 static const struct ast_channel_tech mgcp_tech = {
434 .type = "MGCP",
435 .description = tdesc,
436 .capabilities = AST_FORMAT_ULAW,
437 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
438 .requester = mgcp_request,
439 .devicestate = mgcp_devicestate,
440 .call = mgcp_call,
441 .hangup = mgcp_hangup,
442 .answer = mgcp_answer,
443 .read = mgcp_read,
444 .write = mgcp_write,
445 .indicate = mgcp_indicate,
446 .fixup = mgcp_fixup,
447 .send_digit = mgcp_senddigit,
448 .bridge = ast_rtp_bridge,
451 static int has_voicemail(struct mgcp_endpoint *p)
453 return ast_app_has_voicemail(p->mailbox, NULL);
456 static int unalloc_sub(struct mgcp_subchannel *sub)
458 struct mgcp_endpoint *p = sub->parent;
459 if (p->sub == sub) {
460 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
461 return -1;
463 ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
465 sub->owner = NULL;
466 if (!ast_strlen_zero(sub->cxident)) {
467 transmit_connection_del(sub);
469 sub->cxident[0] = '\0';
470 sub->callid[0] = '\0';
471 sub->cxmode = MGCP_CX_INACTIVE;
472 sub->outgoing = 0;
473 sub->alreadygone = 0;
474 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
475 if (sub->rtp) {
476 ast_rtp_destroy(sub->rtp);
477 sub->rtp = NULL;
479 dump_cmd_queues(NULL, sub); /* SC */
480 return 0;
483 /* modified for new transport mechanism */
484 static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
486 int res;
487 if (gw->addr.sin_addr.s_addr)
488 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
489 else
490 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
491 if (res != len) {
492 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
494 return res;
497 static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
499 struct mgcp_endpoint *p = sub->parent;
500 int res;
501 if (mgcpdebug) {
502 ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
504 res = __mgcp_xmit(p->parent, resp->buf, resp->len);
505 if (res > 0)
506 res = 0;
507 return res;
510 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
512 struct mgcp_endpoint *p = sub->parent;
513 int res;
514 if (mgcpdebug) {
515 ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
517 res = __mgcp_xmit(p->parent, req->data, req->len);
518 if (res > 0)
519 res = 0;
520 return res;
523 /* modified for new transport framework */
524 static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
526 struct mgcp_message *cur, *q = NULL, *w, *prev;
528 ast_mutex_lock(&gw->msgs_lock);
529 prev = NULL, cur = gw->msgs;
530 while (cur) {
531 if (!p || cur->owner_ep == p) {
532 if (prev)
533 prev->next = cur->next;
534 else
535 gw->msgs = cur->next;
537 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
538 gw->name, cur->seqno);
540 w = cur;
541 cur = cur->next;
542 if (q) {
543 w->next = q;
544 } else {
545 w->next = NULL;
547 q = w;
548 } else {
549 prev = cur, cur=cur->next;
552 ast_mutex_unlock(&gw->msgs_lock);
554 while (q) {
555 cur = q;
556 q = q->next;
557 free(cur);
561 static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
563 for(;;) {
564 if (sub->owner) {
565 if (!ast_mutex_trylock(&sub->owner->lock)) {
566 ast_queue_frame(sub->owner, f);
567 ast_mutex_unlock(&sub->owner->lock);
568 break;
569 } else {
570 ast_mutex_unlock(&sub->lock);
571 usleep(1);
572 ast_mutex_lock(&sub->lock);
574 } else
575 break;
579 static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
581 for(;;) {
582 if (sub->owner) {
583 if (!ast_mutex_trylock(&sub->owner->lock)) {
584 ast_queue_hangup(sub->owner);
585 ast_mutex_unlock(&sub->owner->lock);
586 break;
587 } else {
588 ast_mutex_unlock(&sub->lock);
589 usleep(1);
590 ast_mutex_lock(&sub->lock);
592 } else
593 break;
597 static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
599 struct ast_frame f = { AST_FRAME_CONTROL, };
600 f.subclass = control;
601 return mgcp_queue_frame(sub, &f);
604 static int retrans_pkt(void *data)
606 struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
607 struct mgcp_message *cur, *exq = NULL, *w, *prev;
608 int res = 0;
610 /* find out expired msgs */
611 ast_mutex_lock(&gw->msgs_lock);
613 prev = NULL, cur = gw->msgs;
614 while (cur) {
615 if (cur->retrans < MAX_RETRANS) {
616 cur->retrans++;
617 if (mgcpdebug) {
618 ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
619 cur->retrans, cur->seqno, gw->name);
621 __mgcp_xmit(gw, cur->buf, cur->len);
623 prev = cur;
624 cur = cur->next;
625 } else {
626 if (prev)
627 prev->next = cur->next;
628 else
629 gw->msgs = cur->next;
631 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
632 cur->seqno, gw->name);
634 w = cur;
635 cur = cur->next;
637 if (exq) {
638 w->next = exq;
639 } else {
640 w->next = NULL;
642 exq = w;
646 if (!gw->msgs) {
647 gw->retransid = -1;
648 res = 0;
649 } else {
650 res = 1;
652 ast_mutex_unlock(&gw->msgs_lock);
654 while (exq) {
655 cur = exq;
656 /* time-out transaction */
657 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
658 exq = exq->next;
659 free(cur);
662 return res;
665 /* modified for the new transaction mechanism */
666 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
667 char *data, int len, unsigned int seqno)
669 struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
670 struct mgcp_message *cur;
671 struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
672 struct timeval tv;
674 if (!msg) {
675 return -1;
677 if (!gw) {
678 return -1;
680 /* SC
681 time(&t);
682 if (gw->messagepending && (gw->lastouttime + 20 < t)) {
683 ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d, lastouttime: %ld, now: %ld. Dumping pending queue\n",
684 gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
685 dump_queue(sub->parent);
688 msg->owner_sub = sub;
689 msg->owner_ep = p;
690 msg->seqno = seqno;
691 msg->next = NULL;
692 msg->len = len;
693 msg->retrans = 0;
694 memcpy(msg->buf, data, msg->len);
696 ast_mutex_lock(&gw->msgs_lock);
697 cur = gw->msgs;
698 if (cur) {
699 while(cur->next)
700 cur = cur->next;
701 cur->next = msg;
702 } else {
703 gw->msgs = msg;
706 if (gettimeofday(&tv, NULL) < 0) {
707 /* This shouldn't ever happen, but let's be sure */
708 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
709 } else {
710 msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
712 if (gw->retransid == -1)
713 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
715 ast_mutex_unlock(&gw->msgs_lock);
716 /* SC
717 if (!gw->messagepending) {
718 gw->messagepending = 1;
719 gw->lastout = seqno;
720 gw->lastouttime = t;
722 __mgcp_xmit(gw, msg->buf, msg->len);
723 /* XXX Should schedule retransmission XXX */
724 /* SC
725 } else
726 ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
728 return 0;
731 /* modified for new transport */
732 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
733 struct mgcp_request *req, unsigned int seqno)
735 int res = 0;
736 struct mgcp_request **queue, *q, *r, *t;
737 ast_mutex_t *l;
739 ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);
740 if (p->slowsequence) {
741 queue = &p->cmd_queue;
742 l = &p->cmd_queue_lock;
743 ast_mutex_lock(l);
744 } else {
745 switch (req->cmd) {
746 case MGCP_CMD_DLCX:
747 queue = &sub->cx_queue;
748 l = &sub->cx_queue_lock;
749 ast_mutex_lock(l);
750 q = sub->cx_queue;
751 /* delete pending cx cmds */
752 while (q) {
753 r = q->next;
754 free(q);
755 q = r;
757 *queue = NULL;
758 break;
760 case MGCP_CMD_CRCX:
761 case MGCP_CMD_MDCX:
762 queue = &sub->cx_queue;
763 l = &sub->cx_queue_lock;
764 ast_mutex_lock(l);
765 break;
767 case MGCP_CMD_RQNT:
768 queue = &p->rqnt_queue;
769 l = &p->rqnt_queue_lock;
770 ast_mutex_lock(l);
771 break;
773 default:
774 queue = &p->cmd_queue;
775 l = &p->cmd_queue_lock;
776 ast_mutex_lock(l);
777 break;
781 r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
782 if (!r) {
783 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
784 ast_mutex_unlock(l);
785 return -1;
787 memcpy(r, req, sizeof(struct mgcp_request));
789 if (!(*queue)) {
790 if (mgcpdebug) {
791 ast_verbose("Posting Request:\n%s to %s:%d\n", req->data,
792 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
795 res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
796 } else {
797 if (mgcpdebug) {
798 ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data,
799 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
803 /* XXX find tail. We could also keep tail in the data struct for faster access */
804 for (t = *queue; t && t->next; t = t->next);
806 r->next = NULL;
807 if (t)
808 t->next = r;
809 else
810 *queue = r;
812 ast_mutex_unlock(l);
814 return res;
817 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
819 int res;
820 struct mgcp_endpoint *p;
821 struct mgcp_subchannel *sub;
822 char tone[50] = "";
823 const char *distinctive_ring = NULL;
824 struct varshead *headp;
825 struct ast_var_t *current;
827 if (mgcpdebug) {
828 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);
830 sub = ast->tech_pvt;
831 p = sub->parent;
832 headp = &ast->varshead;
833 AST_LIST_TRAVERSE(headp,current,entries) {
834 /* Check whether there is an ALERT_INFO variable */
835 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {
836 distinctive_ring = ast_var_value(current);
840 ast_mutex_lock(&sub->lock);
841 switch (p->hookstate) {
842 case MGCP_OFFHOOK:
843 if (!ast_strlen_zero(distinctive_ring)) {
844 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
845 if (mgcpdebug) {
846 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive callwait %s\n", tone);
848 } else {
849 snprintf(tone, sizeof(tone), "L/wt");
850 if (mgcpdebug) {
851 ast_verbose(VERBOSE_PREFIX_3 "MGCP normal callwait %s\n", tone);
854 break;
855 case MGCP_ONHOOK:
856 default:
857 if (!ast_strlen_zero(distinctive_ring)) {
858 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
859 if (mgcpdebug) {
860 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive ring %s\n", tone);
862 } else {
863 snprintf(tone, sizeof(tone), "L/rg");
864 if (mgcpdebug) {
865 ast_verbose(VERBOSE_PREFIX_3 "MGCP default ring\n");
868 break;
871 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
872 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
873 ast_mutex_unlock(&sub->lock);
874 return -1;
877 res = 0;
878 sub->outgoing = 1;
879 sub->cxmode = MGCP_CX_RECVONLY;
880 if (p->type == TYPE_LINE) {
881 if (!sub->rtp) {
882 start_rtp(sub);
883 } else {
884 transmit_modify_request(sub);
887 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
888 /* try to prevent a callwait from disturbing the other connection */
889 sub->next->cxmode = MGCP_CX_RECVONLY;
890 transmit_modify_request(sub->next);
893 transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
894 ast_setstate(ast, AST_STATE_RINGING);
896 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
897 /* Put the connection back in sendrecv */
898 sub->next->cxmode = MGCP_CX_SENDRECV;
899 transmit_modify_request(sub->next);
901 } else {
902 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
903 res = -1;
905 ast_mutex_unlock(&sub->lock);
906 ast_queue_control(ast, AST_CONTROL_RINGING);
907 return res;
910 static int mgcp_hangup(struct ast_channel *ast)
912 struct mgcp_subchannel *sub = ast->tech_pvt;
913 struct mgcp_endpoint *p = sub->parent;
915 if (option_debug) {
916 ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
918 if (!ast->tech_pvt) {
919 ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
920 return 0;
922 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
923 ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
924 return 0;
926 ast_mutex_lock(&sub->lock);
927 if (mgcpdebug) {
928 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
931 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
932 /* check whether other channel is active. */
933 if (!sub->next->owner) {
934 if (p->dtmfmode & MGCP_DTMF_HYBRID)
935 p->dtmfmode &= ~MGCP_DTMF_INBAND;
936 if (mgcpdebug) {
937 ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
939 ast_dsp_free(p->dsp);
940 p->dsp = NULL;
944 sub->owner = NULL;
945 if (!ast_strlen_zero(sub->cxident)) {
946 transmit_connection_del(sub);
948 sub->cxident[0] = '\0';
949 if ((sub == p->sub) && sub->next->owner) {
950 if (p->hookstate == MGCP_OFFHOOK) {
951 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
952 transmit_notify_request_with_callerid(p->sub, "L/wt", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
954 } else {
955 /* set our other connection as the primary and swith over to it */
956 p->sub = sub->next;
957 p->sub->cxmode = MGCP_CX_RECVONLY;
958 transmit_modify_request(p->sub);
959 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
960 transmit_notify_request_with_callerid(p->sub, "L/rg", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
964 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
965 transmit_notify_request(sub, "L/v");
966 } else if (p->hookstate == MGCP_OFFHOOK) {
967 transmit_notify_request(sub, "L/ro");
968 } else {
969 transmit_notify_request(sub, "");
972 ast->tech_pvt = NULL;
973 sub->alreadygone = 0;
974 sub->outgoing = 0;
975 sub->cxmode = MGCP_CX_INACTIVE;
976 sub->callid[0] = '\0';
977 /* Reset temporary destination */
978 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
979 if (sub->rtp) {
980 ast_rtp_destroy(sub->rtp);
981 sub->rtp = NULL;
984 ast_module_unref(ast_module_info->self);
986 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
987 p->hidecallerid = 0;
988 if (p->hascallwaiting && !p->callwaiting) {
989 if (option_verbose > 2)
990 ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on %s\n", ast->name);
991 p->callwaiting = -1;
993 if (has_voicemail(p)) {
994 if (mgcpdebug) {
995 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
996 ast->name, p->name, p->parent->name);
998 transmit_notify_request(sub, "L/vmwi(+)");
999 } else {
1000 if (mgcpdebug) {
1001 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
1002 ast->name, p->name, p->parent->name);
1004 transmit_notify_request(sub, "L/vmwi(-)");
1007 ast_mutex_unlock(&sub->lock);
1008 return 0;
1011 static int mgcp_show_endpoints(int fd, int argc, char *argv[])
1013 struct mgcp_gateway *g;
1014 struct mgcp_endpoint *e;
1015 int hasendpoints = 0;
1017 if (argc != 3)
1018 return RESULT_SHOWUSAGE;
1019 ast_mutex_lock(&gatelock);
1020 g = gateways;
1021 while(g) {
1022 e = g->endpoints;
1023 ast_cli(fd, "Gateway '%s' at %s (%s)\n", g->name, g->addr.sin_addr.s_addr ? ast_inet_ntoa(g->addr.sin_addr) : ast_inet_ntoa(g->defaddr.sin_addr), g->dynamic ? "Dynamic" : "Static");
1024 while(e) {
1025 /* Don't show wilcard endpoint */
1026 if (strcmp(e->name, g->wcardep) !=0)
1027 ast_cli(fd, " -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
1028 hasendpoints = 1;
1029 e = e->next;
1031 if (!hasendpoints) {
1032 ast_cli(fd, " << No Endpoints Defined >> ");
1034 g = g->next;
1036 ast_mutex_unlock(&gatelock);
1037 return RESULT_SUCCESS;
1040 static char show_endpoints_usage[] =
1041 "Usage: mgcp show endpoints\n"
1042 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
1044 static struct ast_cli_entry cli_show_endpoints =
1045 { { "mgcp", "show", "endpoints", NULL }, mgcp_show_endpoints, "Show defined MGCP endpoints", show_endpoints_usage };
1047 static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
1049 struct mgcp_gateway *g;
1050 struct mgcp_endpoint *e;
1051 int found = 0;
1052 char *ename,*gname, *c;
1054 if (!mgcpdebug) {
1055 return RESULT_SHOWUSAGE;
1057 if (argc != 4)
1058 return RESULT_SHOWUSAGE;
1059 /* split the name into parts by null */
1060 ename = argv[3];
1061 gname = ename;
1062 while (*gname) {
1063 if (*gname == '@') {
1064 *gname = 0;
1065 gname++;
1066 break;
1068 gname++;
1070 if (gname[0] == '[')
1071 gname++;
1072 if ((c = strrchr(gname, ']')))
1073 *c = '\0';
1074 ast_mutex_lock(&gatelock);
1075 g = gateways;
1076 while(g) {
1077 if (!strcasecmp(g->name, gname)) {
1078 e = g->endpoints;
1079 while(e) {
1080 if (!strcasecmp(e->name, ename)) {
1081 found = 1;
1082 transmit_audit_endpoint(e);
1083 break;
1085 e = e->next;
1087 if (found) {
1088 break;
1091 g = g->next;
1093 if (!found) {
1094 ast_cli(fd, " << Could not find endpoint >> ");
1096 ast_mutex_unlock(&gatelock);
1097 return RESULT_SUCCESS;
1100 static char audit_endpoint_usage[] =
1101 "Usage: mgcp audit endpoint <endpointid>\n"
1102 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
1103 " mgcp debug MUST be on to see the results of this command.\n";
1105 static struct ast_cli_entry cli_audit_endpoint =
1106 { { "mgcp", "audit", "endpoint", NULL }, mgcp_audit_endpoint, "Audit specified MGCP endpoint", audit_endpoint_usage };
1108 static int mgcp_answer(struct ast_channel *ast)
1110 int res = 0;
1111 struct mgcp_subchannel *sub = ast->tech_pvt;
1112 struct mgcp_endpoint *p = sub->parent;
1114 ast_mutex_lock(&sub->lock);
1115 sub->cxmode = MGCP_CX_SENDRECV;
1116 if (!sub->rtp) {
1117 start_rtp(sub);
1118 } else {
1119 transmit_modify_request(sub);
1121 /* verbose level check */
1122 if (option_verbose > 2) {
1123 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n",
1124 ast->name, p->name, p->parent->name, sub->id);
1126 if (ast->_state != AST_STATE_UP) {
1127 ast_setstate(ast, AST_STATE_UP);
1128 if (option_debug)
1129 ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
1130 transmit_notify_request(sub, "");
1131 transmit_modify_request(sub);
1133 ast_mutex_unlock(&sub->lock);
1134 return res;
1137 static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
1139 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
1140 struct ast_frame *f;
1142 f = ast_rtp_read(sub->rtp);
1143 /* Don't send RFC2833 if we're not supposed to */
1144 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
1145 return &ast_null_frame;
1146 if (sub->owner) {
1147 /* We already hold the channel lock */
1148 if (f->frametype == AST_FRAME_VOICE) {
1149 if (f->subclass != sub->owner->nativeformats) {
1150 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
1151 sub->owner->nativeformats = f->subclass;
1152 ast_set_read_format(sub->owner, sub->owner->readformat);
1153 ast_set_write_format(sub->owner, sub->owner->writeformat);
1155 /* Courtesy fearnor aka alex@pilosoft.com */
1156 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
1157 #if 0
1158 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
1159 #endif
1160 f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
1164 return f;
1168 static struct ast_frame *mgcp_read(struct ast_channel *ast)
1170 struct ast_frame *f;
1171 struct mgcp_subchannel *sub = ast->tech_pvt;
1172 ast_mutex_lock(&sub->lock);
1173 f = mgcp_rtp_read(sub);
1174 ast_mutex_unlock(&sub->lock);
1175 return f;
1178 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
1180 struct mgcp_subchannel *sub = ast->tech_pvt;
1181 int res = 0;
1182 if (frame->frametype != AST_FRAME_VOICE) {
1183 if (frame->frametype == AST_FRAME_IMAGE)
1184 return 0;
1185 else {
1186 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
1187 return 0;
1189 } else {
1190 if (!(frame->subclass & ast->nativeformats)) {
1191 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
1192 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
1193 return -1;
1196 if (sub) {
1197 ast_mutex_lock(&sub->lock);
1198 if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
1199 if (sub->rtp) {
1200 res = ast_rtp_write(sub->rtp, frame);
1203 ast_mutex_unlock(&sub->lock);
1205 return res;
1208 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1210 struct mgcp_subchannel *sub = newchan->tech_pvt;
1212 ast_mutex_lock(&sub->lock);
1213 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
1214 if (sub->owner != oldchan) {
1215 ast_mutex_unlock(&sub->lock);
1216 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
1217 return -1;
1219 sub->owner = newchan;
1220 ast_mutex_unlock(&sub->lock);
1221 return 0;
1224 static int mgcp_senddigit(struct ast_channel *ast, char digit)
1226 struct mgcp_subchannel *sub = ast->tech_pvt;
1227 char tmp[4];
1229 tmp[0] = 'D';
1230 tmp[1] = '/';
1231 tmp[2] = digit;
1232 tmp[3] = '\0';
1233 ast_mutex_lock(&sub->lock);
1234 transmit_notify_request(sub, tmp);
1235 ast_mutex_unlock(&sub->lock);
1236 return -1;
1240 * \brief mgcp_devicestate: channel callback for device status monitoring
1241 * \param data tech/resource name of MGCP device to query
1243 * Callback for device state management in channel subsystem
1244 * to obtain device status (up/down) of a specific MGCP endpoint
1246 * \return device status result (from devicestate.h) AST_DEVICE_INVALID (not available) or AST_DEVICE_UNKNOWN (available but unknown state)
1248 static int mgcp_devicestate(void *data)
1250 struct mgcp_gateway *g;
1251 struct mgcp_endpoint *e = NULL;
1252 char *tmp, *endpt, *gw;
1253 int ret = AST_DEVICE_INVALID;
1255 endpt = ast_strdupa(data);
1256 if ((tmp = strchr(endpt, '@'))) {
1257 *tmp++ = '\0';
1258 gw = tmp;
1259 } else
1260 goto error;
1262 ast_mutex_lock(&gatelock);
1263 g = gateways;
1264 while (g) {
1265 if (strcasecmp(g->name, gw) == 0) {
1266 e = g->endpoints;
1267 break;
1269 g = g->next;
1272 if (!e)
1273 goto error;
1275 while (e) {
1276 if (strcasecmp(e->name, endpt) == 0)
1277 break;
1278 e = e->next;
1281 if (!e)
1282 goto error;
1285 * As long as the gateway/endpoint is valid, we'll
1286 * assume that the device is available and its state
1287 * can be tracked.
1289 ret = AST_DEVICE_UNKNOWN;
1291 error:
1292 ast_mutex_unlock(&gatelock);
1293 return ret;
1296 static char *control2str(int ind) {
1297 switch (ind) {
1298 case AST_CONTROL_HANGUP:
1299 return "Other end has hungup";
1300 case AST_CONTROL_RING:
1301 return "Local ring";
1302 case AST_CONTROL_RINGING:
1303 return "Remote end is ringing";
1304 case AST_CONTROL_ANSWER:
1305 return "Remote end has answered";
1306 case AST_CONTROL_BUSY:
1307 return "Remote end is busy";
1308 case AST_CONTROL_TAKEOFFHOOK:
1309 return "Make it go off hook";
1310 case AST_CONTROL_OFFHOOK:
1311 return "Line is off hook";
1312 case AST_CONTROL_CONGESTION:
1313 return "Congestion (circuits busy)";
1314 case AST_CONTROL_FLASH:
1315 return "Flash hook";
1316 case AST_CONTROL_WINK:
1317 return "Wink";
1318 case AST_CONTROL_OPTION:
1319 return "Set a low-level option";
1320 case AST_CONTROL_RADIO_KEY:
1321 return "Key Radio";
1322 case AST_CONTROL_RADIO_UNKEY:
1323 return "Un-Key Radio";
1325 return "UNKNOWN";
1328 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
1330 struct mgcp_subchannel *sub = ast->tech_pvt;
1331 int res = 0;
1333 if (mgcpdebug) {
1334 ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n",
1335 ind, control2str(ind), ast->name);
1337 ast_mutex_lock(&sub->lock);
1338 switch(ind) {
1339 case AST_CONTROL_RINGING:
1340 #ifdef DLINK_BUGGY_FIRMWARE
1341 transmit_notify_request(sub, "rt");
1342 #else
1343 transmit_notify_request(sub, "G/rt");
1344 #endif
1345 break;
1346 case AST_CONTROL_BUSY:
1347 transmit_notify_request(sub, "L/bz");
1348 break;
1349 case AST_CONTROL_CONGESTION:
1350 transmit_notify_request(sub, "G/cg");
1351 break;
1352 case AST_CONTROL_HOLD:
1353 ast_moh_start(ast, data, NULL);
1354 break;
1355 case AST_CONTROL_UNHOLD:
1356 ast_moh_stop(ast);
1357 break;
1358 case -1:
1359 transmit_notify_request(sub, "");
1360 break;
1361 default:
1362 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
1363 res = -1;
1365 ast_mutex_unlock(&sub->lock);
1366 return res;
1369 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
1371 struct ast_channel *tmp;
1372 struct mgcp_endpoint *i = sub->parent;
1373 int fmt;
1375 tmp = ast_channel_alloc(1);
1376 if (tmp) {
1377 tmp->tech = &mgcp_tech;
1378 tmp->nativeformats = i->capability;
1379 if (!tmp->nativeformats)
1380 tmp->nativeformats = capability;
1381 fmt = ast_best_codec(tmp->nativeformats);
1382 ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
1383 if (sub->rtp)
1384 tmp->fds[0] = ast_rtp_fd(sub->rtp);
1385 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
1386 i->dsp = ast_dsp_new();
1387 ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
1388 /* this is to prevent clipping of dtmf tones during dsp processing */
1389 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
1390 } else {
1391 i->dsp = NULL;
1393 ast_setstate(tmp, state);
1394 if (state == AST_STATE_RING)
1395 tmp->rings = 1;
1396 tmp->writeformat = fmt;
1397 tmp->rawwriteformat = fmt;
1398 tmp->readformat = fmt;
1399 tmp->rawreadformat = fmt;
1400 tmp->tech_pvt = sub;
1401 if (!ast_strlen_zero(i->language))
1402 ast_string_field_set(tmp, language, i->language);
1403 if (!ast_strlen_zero(i->accountcode))
1404 ast_string_field_set(tmp, accountcode, i->accountcode);
1405 if (i->amaflags)
1406 tmp->amaflags = i->amaflags;
1407 sub->owner = tmp;
1408 ast_module_ref(ast_module_info->self);
1409 tmp->callgroup = i->callgroup;
1410 tmp->pickupgroup = i->pickupgroup;
1411 ast_string_field_set(tmp, call_forward, i->call_forward);
1412 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
1413 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
1415 /* Don't use ast_set_callerid() here because it will
1416 * generate a NewCallerID event before the NewChannel event */
1417 tmp->cid.cid_num = ast_strdup(i->cid_num);
1418 tmp->cid.cid_ani = ast_strdup(i->cid_num);
1419 tmp->cid.cid_name = ast_strdup(i->cid_name);
1421 if (!i->adsi)
1422 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
1423 tmp->priority = 1;
1424 if (sub->rtp)
1425 ast_jb_configure(tmp, &global_jbconf);
1426 if (state != AST_STATE_DOWN) {
1427 if (ast_pbx_start(tmp)) {
1428 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
1429 ast_hangup(tmp);
1430 tmp = NULL;
1433 /* verbose level check */
1434 if (option_verbose > 2) {
1435 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
1436 tmp->name, ast_state2str(state));
1438 } else {
1439 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
1441 return tmp;
1444 static char* get_sdp_by_line(char* line, char *name, int nameLen)
1446 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
1447 char* r = line + nameLen + 1;
1448 while (*r && (*r < 33)) ++r;
1449 return r;
1451 return "";
1454 static char *get_sdp(struct mgcp_request *req, char *name)
1456 int x;
1457 int len = strlen(name);
1458 char *r;
1460 for (x=0; x<req->lines; x++) {
1461 r = get_sdp_by_line(req->line[x], name, len);
1462 if (r[0] != '\0') return r;
1464 return "";
1467 static void sdpLineNum_iterator_init(int* iterator)
1469 *iterator = 0;
1472 static char* get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
1474 int len = strlen(name);
1475 char *r;
1476 while (*iterator < req->lines) {
1477 r = get_sdp_by_line(req->line[(*iterator)++], name, len);
1478 if (r[0] != '\0') return r;
1480 return "";
1483 static char *__get_header(struct mgcp_request *req, char *name, int *start)
1485 int x;
1486 int len = strlen(name);
1487 char *r;
1488 for (x=*start;x<req->headers;x++) {
1489 if (!strncasecmp(req->header[x], name, len) &&
1490 (req->header[x][len] == ':')) {
1491 r = req->header[x] + len + 1;
1492 while(*r && (*r < 33))
1493 r++;
1494 *start = x+1;
1495 return r;
1498 /* Don't return NULL, so get_header is always a valid pointer */
1499 return "";
1502 static char *get_header(struct mgcp_request *req, char *name)
1504 int start = 0;
1505 return __get_header(req, name, &start);
1508 /*! \brief get_csv: (SC:) get comma separated value */
1509 static char *get_csv(char *c, int *len, char **next)
1511 char *s;
1513 *next = NULL, *len = 0;
1514 if (!c) return NULL;
1516 while (*c && (*c < 33 || *c == ','))
1517 c++;
1519 s = c;
1520 while (*c && (*c >= 33 && *c != ','))
1521 c++, (*len)++;
1522 *next = c;
1524 if (*len == 0)
1525 s = NULL, *next = NULL;
1527 return s;
1530 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
1532 struct mgcp_endpoint *p = NULL;
1533 struct mgcp_subchannel *sub = NULL;
1534 struct mgcp_gateway *g;
1535 char tmp[256] = "";
1536 char *at = NULL, *c;
1537 int found = 0;
1538 if (name) {
1539 ast_copy_string(tmp, name, sizeof(tmp));
1540 at = strchr(tmp, '@');
1541 if (!at) {
1542 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
1543 return NULL;
1545 *at++ = '\0';
1547 ast_mutex_lock(&gatelock);
1548 if (at && (at[0] == '[')) {
1549 at++;
1550 c = strrchr(at, ']');
1551 if (c)
1552 *c = '\0';
1554 g = gateways;
1555 while(g) {
1556 if ((!name || !strcasecmp(g->name, at)) &&
1557 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
1558 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */
1559 if (sin && g->dynamic && name) {
1560 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1561 (g->addr.sin_port != sin->sin_port)) {
1562 memcpy(&g->addr, sin, sizeof(g->addr));
1563 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
1564 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
1565 if (option_verbose > 2)
1566 ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
1569 /* not dynamic, check if the name matches */
1570 else if (name) {
1571 if (strcasecmp(g->name, at)) {
1572 g = g->next;
1573 continue;
1576 /* not dynamic, no name, check if the addr matches */
1577 else if (!name && sin) {
1578 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1579 (g->addr.sin_port != sin->sin_port)) {
1580 g = g->next;
1581 continue;
1583 } else {
1584 g = g->next;
1585 continue;
1587 /* SC */
1588 p = g->endpoints;
1589 while(p) {
1590 if (option_debug)
1591 ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n",
1592 p->name, g->name);
1593 if (msgid) {
1594 #if 0 /* new transport mech */
1595 sub = p->sub;
1596 do {
1597 if (option_debug)
1598 ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
1599 p->name, g->name, sub->id, msgid);
1600 if (sub->lastout == msgid) {
1601 if (option_debug)
1602 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
1603 sub->id, msgid, sub->lastout);
1604 found = 1;
1605 break;
1607 sub = sub->next;
1608 } while (sub != p->sub);
1609 if (found) {
1610 break;
1612 #endif
1613 /* SC */
1614 sub = p->sub;
1615 found = 1;
1616 /* SC */
1617 break;
1618 } else if (name && !strcasecmp(p->name, tmp)) {
1619 ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
1620 p->name, g->name, p->sub->id);
1621 sub = p->sub;
1622 found = 1;
1623 break;
1625 p = p->next;
1627 if (sub && found) {
1628 ast_mutex_lock(&sub->lock);
1629 break;
1632 g = g->next;
1634 ast_mutex_unlock(&gatelock);
1635 if (!sub) {
1636 if (name) {
1637 if (g)
1638 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
1639 else
1640 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
1643 return sub;
1646 static void parse(struct mgcp_request *req)
1648 /* Divide fields by NULL's */
1649 char *c;
1650 int f = 0;
1651 c = req->data;
1653 /* First header starts immediately */
1654 req->header[f] = c;
1655 while(*c) {
1656 if (*c == '\n') {
1657 /* We've got a new header */
1658 *c = 0;
1659 #if 0
1660 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
1661 #endif
1662 if (ast_strlen_zero(req->header[f])) {
1663 /* Line by itself means we're now in content */
1664 c++;
1665 break;
1667 if (f >= MGCP_MAX_HEADERS - 1) {
1668 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
1669 } else
1670 f++;
1671 req->header[f] = c + 1;
1672 } else if (*c == '\r') {
1673 /* Ignore but eliminate \r's */
1674 *c = 0;
1676 c++;
1678 /* Check for last header */
1679 if (!ast_strlen_zero(req->header[f]))
1680 f++;
1681 req->headers = f;
1682 /* Now we process any mime content */
1683 f = 0;
1684 req->line[f] = c;
1685 while(*c) {
1686 if (*c == '\n') {
1687 /* We've got a new line */
1688 *c = 0;
1689 #if 0
1690 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
1691 #endif
1692 if (f >= MGCP_MAX_LINES - 1) {
1693 ast_log(LOG_WARNING, "Too many SDP lines...\n");
1694 } else
1695 f++;
1696 req->line[f] = c + 1;
1697 } else if (*c == '\r') {
1698 /* Ignore and eliminate \r's */
1699 *c = 0;
1701 c++;
1703 /* Check for last line */
1704 if (!ast_strlen_zero(req->line[f]))
1705 f++;
1706 req->lines = f;
1707 /* Parse up the initial header */
1708 c = req->header[0];
1709 while(*c && *c < 33) c++;
1710 /* First the verb */
1711 req->verb = c;
1712 while(*c && (*c > 32)) c++;
1713 if (*c) {
1714 *c = '\0';
1715 c++;
1716 while(*c && (*c < 33)) c++;
1717 req->identifier = c;
1718 while(*c && (*c > 32)) c++;
1719 if (*c) {
1720 *c = '\0';
1721 c++;
1722 while(*c && (*c < 33)) c++;
1723 req->endpoint = c;
1724 while(*c && (*c > 32)) c++;
1725 if (*c) {
1726 *c = '\0';
1727 c++;
1728 while(*c && (*c < 33)) c++;
1729 req->version = c;
1730 while(*c && (*c > 32)) c++;
1731 while(*c && (*c < 33)) c++;
1732 while(*c && (*c > 32)) c++;
1733 *c = '\0';
1738 if (mgcpdebug) {
1739 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
1740 req->verb, req->identifier, req->endpoint, req->version);
1741 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
1743 if (*c)
1744 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
1747 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
1749 char *m;
1750 char *c;
1751 char *a;
1752 char host[258];
1753 int len;
1754 int portno;
1755 int peercapability, peerNonCodecCapability;
1756 struct sockaddr_in sin;
1757 char *codecs;
1758 struct ast_hostent ahp; struct hostent *hp;
1759 int codec, codec_count=0;
1760 int iterator;
1761 struct mgcp_endpoint *p = sub->parent;
1763 /* Get codec and RTP info from SDP */
1764 m = get_sdp(req, "m");
1765 c = get_sdp(req, "c");
1766 if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
1767 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
1768 return -1;
1770 if (sscanf(c, "IN IP4 %256s", host) != 1) {
1771 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
1772 return -1;
1774 /* XXX This could block for a long time, and block the main thread! XXX */
1775 hp = ast_gethostbyname(host, &ahp);
1776 if (!hp) {
1777 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
1778 return -1;
1780 if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
1781 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
1782 return -1;
1784 sin.sin_family = AF_INET;
1785 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
1786 sin.sin_port = htons(portno);
1787 ast_rtp_set_peer(sub->rtp, &sin);
1788 #if 0
1789 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
1790 #endif
1791 /* Scan through the RTP payload types specified in a "m=" line: */
1792 ast_rtp_pt_clear(sub->rtp);
1793 codecs = ast_strdupa(m + len);
1794 while (!ast_strlen_zero(codecs)) {
1795 if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
1796 if (codec_count)
1797 break;
1798 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
1799 return -1;
1801 ast_rtp_set_m_type(sub->rtp, codec);
1802 codec_count++;
1803 codecs += len;
1806 /* Next, scan through each "a=rtpmap:" line, noting each */
1807 /* specified RTP payload type (with corresponding MIME subtype): */
1808 sdpLineNum_iterator_init(&iterator);
1809 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
1810 char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
1811 if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
1812 continue;
1813 /* Note: should really look at the 'freq' and '#chans' params too */
1814 ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0);
1817 /* Now gather all of the codecs that were asked for: */
1818 ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
1819 p->capability = capability & peercapability;
1820 if (mgcpdebug) {
1821 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
1822 capability, peercapability, p->capability);
1823 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
1824 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
1826 if (!p->capability) {
1827 ast_log(LOG_WARNING, "No compatible codecs!\n");
1828 return -1;
1830 return 0;
1833 static int add_header(struct mgcp_request *req, char *var, char *value)
1835 if (req->len >= sizeof(req->data) - 4) {
1836 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1837 return -1;
1839 if (req->lines) {
1840 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
1841 return -1;
1843 req->header[req->headers] = req->data + req->len;
1844 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
1845 req->len += strlen(req->header[req->headers]);
1846 if (req->headers < MGCP_MAX_HEADERS)
1847 req->headers++;
1848 else {
1849 ast_log(LOG_WARNING, "Out of header space\n");
1850 return -1;
1852 return 0;
1855 static int add_line(struct mgcp_request *req, char *line)
1857 if (req->len >= sizeof(req->data) - 4) {
1858 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1859 return -1;
1861 if (!req->lines) {
1862 /* Add extra empty return */
1863 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
1864 req->len += strlen(req->data + req->len);
1866 req->line[req->lines] = req->data + req->len;
1867 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
1868 req->len += strlen(req->line[req->lines]);
1869 if (req->lines < MGCP_MAX_LINES)
1870 req->lines++;
1871 else {
1872 ast_log(LOG_WARNING, "Out of line space\n");
1873 return -1;
1875 return 0;
1878 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
1880 /* Initialize a response */
1881 if (req->headers || req->len) {
1882 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1883 return -1;
1885 req->header[req->headers] = req->data + req->len;
1886 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
1887 req->len += strlen(req->header[req->headers]);
1888 if (req->headers < MGCP_MAX_HEADERS)
1889 req->headers++;
1890 else
1891 ast_log(LOG_WARNING, "Out of header space\n");
1892 return 0;
1895 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
1897 /* Initialize a response */
1898 if (req->headers || req->len) {
1899 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1900 return -1;
1902 req->header[req->headers] = req->data + req->len;
1903 /* check if we need brackets around the gw name */
1904 if (p->parent->isnamedottedip)
1905 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
1906 else
1907 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
1908 req->len += strlen(req->header[req->headers]);
1909 if (req->headers < MGCP_MAX_HEADERS)
1910 req->headers++;
1911 else
1912 ast_log(LOG_WARNING, "Out of header space\n");
1913 return 0;
1917 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
1919 memset(resp, 0, sizeof(*resp));
1920 init_resp(resp, msg, req, msgrest);
1921 return 0;
1924 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
1926 memset(req, 0, sizeof(struct mgcp_request));
1927 oseq++;
1928 if (oseq > 999999999)
1929 oseq = 1;
1930 init_req(p, req, verb);
1931 return 0;
1934 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
1936 struct mgcp_request resp;
1937 struct mgcp_endpoint *p = sub->parent;
1938 struct mgcp_response *mgr;
1940 respprep(&resp, p, msg, req, msgrest);
1941 mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
1942 if (mgr) {
1943 /* Store MGCP response in case we have to retransmit */
1944 memset(mgr, 0, sizeof(struct mgcp_response));
1945 sscanf(req->identifier, "%d", &mgr->seqno);
1946 time(&mgr->whensent);
1947 mgr->len = resp.len;
1948 memcpy(mgr->buf, resp.data, resp.len);
1949 mgr->buf[resp.len] = '\0';
1950 mgr->next = p->parent->responses;
1951 p->parent->responses = mgr;
1953 return send_response(sub, &resp);
1957 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1959 int len;
1960 int codec;
1961 char costr[80];
1962 struct sockaddr_in sin;
1963 char v[256];
1964 char s[256];
1965 char o[256];
1966 char c[256];
1967 char t[256];
1968 char m[256] = "";
1969 char a[1024] = "";
1970 int x;
1971 struct sockaddr_in dest;
1972 struct mgcp_endpoint *p = sub->parent;
1973 /* XXX We break with the "recommendation" and send our IP, in order that our
1974 peer doesn't have to ast_gethostbyname() us XXX */
1975 len = 0;
1976 if (!sub->rtp) {
1977 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
1978 return -1;
1980 ast_rtp_get_us(sub->rtp, &sin);
1981 if (rtp) {
1982 ast_rtp_get_peer(rtp, &dest);
1983 } else {
1984 if (sub->tmpdest.sin_addr.s_addr) {
1985 dest.sin_addr = sub->tmpdest.sin_addr;
1986 dest.sin_port = sub->tmpdest.sin_port;
1987 /* Reset temporary destination */
1988 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
1989 } else {
1990 dest.sin_addr = p->parent->ourip;
1991 dest.sin_port = sin.sin_port;
1994 if (mgcpdebug) {
1995 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
1997 snprintf(v, sizeof(v), "v=0\r\n");
1998 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), ast_inet_ntoa(dest.sin_addr));
1999 snprintf(s, sizeof(s), "s=session\r\n");
2000 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
2001 snprintf(t, sizeof(t), "t=0 0\r\n");
2002 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
2003 for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
2004 if (p->capability & x) {
2005 if (mgcpdebug) {
2006 ast_verbose("Answering with capability %d\n", x);
2008 codec = ast_rtp_lookup_code(sub->rtp, 1, x);
2009 if (codec > -1) {
2010 snprintf(costr, sizeof(costr), " %d", codec);
2011 strncat(m, costr, sizeof(m) - strlen(m) - 1);
2012 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0));
2013 strncat(a, costr, sizeof(a) - strlen(a) - 1);
2017 for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
2018 if (p->nonCodecCapability & x) {
2019 if (mgcpdebug) {
2020 ast_verbose("Answering with non-codec capability %d\n", x);
2022 codec = ast_rtp_lookup_code(sub->rtp, 0, x);
2023 if (codec > -1) {
2024 snprintf(costr, sizeof(costr), " %d", codec);
2025 strncat(m, costr, sizeof(m) - strlen(m) - 1);
2026 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0));
2027 strncat(a, costr, sizeof(a) - strlen(a) - 1);
2028 if (x == AST_RTP_DTMF) {
2029 /* Indicate we support DTMF... Not sure about 16,
2030 but MSN supports it so dang it, we will too... */
2031 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
2032 strncat(a, costr, sizeof(a) - strlen(a) - 1);
2037 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
2038 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
2039 snprintf(costr, sizeof(costr), "%d", len);
2040 add_line(resp, v);
2041 add_line(resp, o);
2042 add_line(resp, s);
2043 add_line(resp, c);
2044 add_line(resp, t);
2045 add_line(resp, m);
2046 add_line(resp, a);
2047 return 0;
2050 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
2052 struct mgcp_request resp;
2053 char local[256];
2054 char tmp[80];
2055 int x;
2056 int capability;
2057 struct mgcp_endpoint *p = sub->parent;
2059 capability = p->capability;
2060 if (codecs)
2061 capability = codecs;
2062 if (ast_strlen_zero(sub->cxident) && rtp) {
2063 /* We don't have a CXident yet, store the destination and
2064 wait a bit */
2065 ast_rtp_get_peer(rtp, &sub->tmpdest);
2066 return 0;
2068 snprintf(local, sizeof(local), "p:20");
2069 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
2070 if (p->capability & x) {
2071 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
2072 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2075 reqprep(&resp, p, "MDCX");
2076 add_header(&resp, "C", sub->callid);
2077 add_header(&resp, "L", local);
2078 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2079 /* X header should not be sent. kept for compatibility */
2080 add_header(&resp, "X", sub->txident);
2081 add_header(&resp, "I", sub->cxident);
2082 /*add_header(&resp, "S", "");*/
2083 add_sdp(&resp, sub, rtp);
2084 /* fill in new fields */
2085 resp.cmd = MGCP_CMD_MDCX;
2086 resp.trid = oseq;
2087 return send_request(p, sub, &resp, oseq); /* SC */
2090 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
2092 struct mgcp_request resp;
2093 char local[256];
2094 char tmp[80];
2095 int x;
2096 struct mgcp_endpoint *p = sub->parent;
2098 snprintf(local, sizeof(local), "p:20");
2099 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
2100 if (p->capability & x) {
2101 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
2102 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2105 if (mgcpdebug) {
2106 ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
2107 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2109 reqprep(&resp, p, "CRCX");
2110 add_header(&resp, "C", sub->callid);
2111 add_header(&resp, "L", local);
2112 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2113 /* X header should not be sent. kept for compatibility */
2114 add_header(&resp, "X", sub->txident);
2115 /*add_header(&resp, "S", "");*/
2116 add_sdp(&resp, sub, rtp);
2117 /* fill in new fields */
2118 resp.cmd = MGCP_CMD_CRCX;
2119 resp.trid = oseq;
2120 return send_request(p, sub, &resp, oseq); /* SC */
2123 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
2125 struct mgcp_request resp;
2126 struct mgcp_endpoint *p = sub->parent;
2128 if (mgcpdebug) {
2129 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2130 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2132 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
2133 reqprep(&resp, p, "RQNT");
2134 add_header(&resp, "X", p->rqnt_ident); /* SC */
2135 switch (p->hookstate) {
2136 case MGCP_ONHOOK:
2137 add_header(&resp, "R", "L/hd(N)");
2138 break;
2139 case MGCP_OFFHOOK:
2140 add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
2141 break;
2143 if (!ast_strlen_zero(tone)) {
2144 add_header(&resp, "S", tone);
2146 /* fill in new fields */
2147 resp.cmd = MGCP_CMD_RQNT;
2148 resp.trid = oseq;
2149 return send_request(p, NULL, &resp, oseq); /* SC */
2152 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
2154 struct mgcp_request resp;
2155 char tone2[256];
2156 char *l, *n;
2157 time_t t;
2158 struct tm tm;
2159 struct mgcp_endpoint *p = sub->parent;
2161 time(&t);
2162 localtime_r(&t,&tm);
2163 n = callername;
2164 l = callernum;
2165 if (!n)
2166 n = "";
2167 if (!l)
2168 l = "";
2170 /* Keep track of last callerid for blacklist and callreturn */
2171 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
2173 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
2174 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
2175 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
2176 reqprep(&resp, p, "RQNT");
2177 add_header(&resp, "X", p->rqnt_ident); /* SC */
2178 switch (p->hookstate) {
2179 case MGCP_ONHOOK:
2180 add_header(&resp, "R", "L/hd(N)");
2181 break;
2182 case MGCP_OFFHOOK:
2183 add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
2184 break;
2186 if (!ast_strlen_zero(tone2)) {
2187 add_header(&resp, "S", tone2);
2189 if (mgcpdebug) {
2190 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2191 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2193 /* fill in new fields */
2194 resp.cmd = MGCP_CMD_RQNT;
2195 resp.trid = oseq;
2196 return send_request(p, NULL, &resp, oseq); /* SC */
2199 static int transmit_modify_request(struct mgcp_subchannel *sub)
2201 struct mgcp_request resp;
2202 struct mgcp_endpoint *p = sub->parent;
2204 if (ast_strlen_zero(sub->cxident)) {
2205 /* We don't have a CXident yet, store the destination and
2206 wait a bit */
2207 return 0;
2209 if (mgcpdebug) {
2210 ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n",
2211 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2213 reqprep(&resp, p, "MDCX");
2214 add_header(&resp, "C", sub->callid);
2215 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2216 /* X header should not be sent. kept for compatibility */
2217 add_header(&resp, "X", sub->txident);
2218 add_header(&resp, "I", sub->cxident);
2219 switch (sub->parent->hookstate) {
2220 case MGCP_ONHOOK:
2221 add_header(&resp, "R", "L/hd(N)");
2222 break;
2223 case MGCP_OFFHOOK:
2224 add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N), L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
2225 break;
2227 /* fill in new fields */
2228 resp.cmd = MGCP_CMD_MDCX;
2229 resp.trid = oseq;
2230 return send_request(p, sub, &resp, oseq); /* SC */
2234 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
2236 struct mgcp_request resp;
2237 reqprep(&resp, p, "AUEP");
2238 /* removed unknown param VS */
2239 /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
2240 add_header(&resp, "F", "A");
2241 /* fill in new fields */
2242 resp.cmd = MGCP_CMD_AUEP;
2243 resp.trid = oseq;
2244 return send_request(p, NULL, &resp, oseq); /* SC */
2247 static int transmit_connection_del(struct mgcp_subchannel *sub)
2249 struct mgcp_endpoint *p = sub->parent;
2250 struct mgcp_request resp;
2252 if (mgcpdebug) {
2253 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
2254 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2256 reqprep(&resp, p, "DLCX");
2257 /* check if call id is avail */
2258 if (sub->callid[0])
2259 add_header(&resp, "C", sub->callid);
2260 /* X header should not be sent. kept for compatibility */
2261 add_header(&resp, "X", sub->txident);
2262 /* check if cxident is avail */
2263 if (sub->cxident[0])
2264 add_header(&resp, "I", sub->cxident);
2265 /* fill in new fields */
2266 resp.cmd = MGCP_CMD_DLCX;
2267 resp.trid = oseq;
2268 return send_request(p, sub, &resp, oseq); /* SC */
2271 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
2273 struct mgcp_request resp;
2275 if (mgcpdebug) {
2276 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n",
2277 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
2279 reqprep(&resp, p, "DLCX");
2280 /* check if call id is avail */
2281 if (callid && *callid)
2282 add_header(&resp, "C", callid);
2283 /* check if cxident is avail */
2284 if (cxident && *cxident)
2285 add_header(&resp, "I", cxident);
2286 /* fill in new fields */
2287 resp.cmd = MGCP_CMD_DLCX;
2288 resp.trid = oseq;
2289 return send_request(p, p->sub, &resp, oseq);
2292 /*! \brief dump_cmd_queues: (SC:) cleanup pending commands */
2293 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
2295 struct mgcp_request *t, *q;
2297 if (p) {
2298 ast_mutex_lock(&p->rqnt_queue_lock);
2299 for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
2300 p->rqnt_queue = NULL;
2301 ast_mutex_unlock(&p->rqnt_queue_lock);
2303 ast_mutex_lock(&p->cmd_queue_lock);
2304 for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
2305 p->cmd_queue = NULL;
2306 ast_mutex_unlock(&p->cmd_queue_lock);
2308 ast_mutex_lock(&p->sub->cx_queue_lock);
2309 for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
2310 p->sub->cx_queue = NULL;
2311 ast_mutex_unlock(&p->sub->cx_queue_lock);
2313 ast_mutex_lock(&p->sub->next->cx_queue_lock);
2314 for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
2315 p->sub->next->cx_queue = NULL;
2316 ast_mutex_unlock(&p->sub->next->cx_queue_lock);
2317 } else if (sub) {
2318 ast_mutex_lock(&sub->cx_queue_lock);
2319 for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
2320 sub->cx_queue = NULL;
2321 ast_mutex_unlock(&sub->cx_queue_lock);
2326 /*! \brief find_command: (SC:) remove command transaction from queue */
2327 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2328 struct mgcp_request **queue, ast_mutex_t *l, int ident)
2330 struct mgcp_request *prev, *req;
2332 ast_mutex_lock(l);
2333 for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
2334 if (req->trid == ident) {
2335 /* remove from queue */
2336 if (!prev)
2337 *queue = req->next;
2338 else
2339 prev->next = req->next;
2341 /* send next pending command */
2342 if (*queue) {
2343 if (mgcpdebug) {
2344 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
2345 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
2348 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
2350 break;
2353 ast_mutex_unlock(l);
2354 return req;
2357 /* modified for new transport mechanism */
2358 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2359 int result, unsigned int ident, struct mgcp_request *resp)
2361 char *c;
2362 struct mgcp_request *req;
2363 struct mgcp_gateway *gw = p->parent;
2365 if (result < 200) {
2366 /* provisional response */
2367 return;
2370 if (p->slowsequence)
2371 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2372 else if (sub)
2373 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
2374 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
2375 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2377 if (!req) {
2378 if (option_verbose > 2) {
2379 ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n",
2380 gw->name, ident);
2382 return;
2385 if (p && (result >= 400) && (result <= 599)) {
2386 switch (result) {
2387 case 401:
2388 p->hookstate = MGCP_OFFHOOK;
2389 break;
2390 case 402:
2391 p->hookstate = MGCP_ONHOOK;
2392 break;
2393 case 406:
2394 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
2395 break;
2396 case 407:
2397 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
2398 break;
2400 if (sub) {
2401 if (sub->owner) {
2402 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2403 result, p->name, p->parent->name, sub ? sub->id:-1);
2404 mgcp_queue_hangup(sub);
2406 } else {
2407 if (p->sub->next->owner) {
2408 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2409 result, p->name, p->parent->name, sub ? sub->id:-1);
2410 mgcp_queue_hangup(p->sub);
2413 if (p->sub->owner) {
2414 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2415 result, p->name, p->parent->name, sub ? sub->id:-1);
2416 mgcp_queue_hangup(p->sub);
2419 dump_cmd_queues(p, NULL);
2423 if (resp) {
2424 if (req->cmd == MGCP_CMD_CRCX) {
2425 if ((c = get_header(resp, "I"))) {
2426 if (!ast_strlen_zero(c) && sub) {
2427 /* if we are hanging up do not process this conn. */
2428 if (sub->owner) {
2429 if (!ast_strlen_zero(sub->cxident)) {
2430 if (strcasecmp(c, sub->cxident)) {
2431 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
2434 ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
2435 if (sub->tmpdest.sin_addr.s_addr) {
2436 transmit_modify_with_sdp(sub, NULL, 0);
2438 } else {
2439 /* XXX delete this one
2440 callid and conn id may already be lost.
2441 so the following del conn may have a side effect of
2442 cleaning up the next subchannel */
2443 transmit_connection_del(sub);
2449 if (req->cmd == MGCP_CMD_AUEP) {
2450 /* check stale connection ids */
2451 if ((c = get_header(resp, "I"))) {
2452 char *v, *n;
2453 int len;
2454 while ((v = get_csv(c, &len, &n))) {
2455 if (len) {
2456 if (strncasecmp(v, p->sub->cxident, len) &&
2457 strncasecmp(v, p->sub->next->cxident, len)) {
2458 /* connection id not found. delete it */
2459 char cxident[80] = "";
2461 if (len > (sizeof(cxident) - 1))
2462 len = sizeof(cxident) - 1;
2463 ast_copy_string(cxident, v, len);
2464 if (option_verbose > 2) {
2465 ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n",
2466 cxident, p->name, gw->name);
2468 transmit_connection_del_w_params(p, NULL, cxident);
2471 c = n;
2475 /* Try to determine the hookstate returned from an audit endpoint command */
2476 if ((c = get_header(resp, "ES"))) {
2477 if (!ast_strlen_zero(c)) {
2478 if (strstr(c, "hu")) {
2479 if (p->hookstate != MGCP_ONHOOK) {
2480 /* XXX cleanup if we think we are offhook XXX */
2481 if ((p->sub->owner || p->sub->next->owner ) &&
2482 p->hookstate == MGCP_OFFHOOK)
2483 mgcp_queue_hangup(sub);
2484 p->hookstate = MGCP_ONHOOK;
2486 /* update the requested events according to the new hookstate */
2487 transmit_notify_request(p->sub, "");
2489 /* verbose level check */
2490 if (option_verbose > 2) {
2491 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
2494 } else if (strstr(c, "hd")) {
2495 if (p->hookstate != MGCP_OFFHOOK) {
2496 p->hookstate = MGCP_OFFHOOK;
2498 /* update the requested events according to the new hookstate */
2499 transmit_notify_request(p->sub, "");
2501 /* verbose level check */
2502 if (option_verbose > 2) {
2503 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
2511 if (resp && resp->lines) {
2512 /* do not process sdp if we are hanging up. this may be a late response */
2513 if (sub && sub->owner) {
2514 if (!sub->rtp)
2515 start_rtp(sub);
2516 if (sub->rtp)
2517 process_sdp(sub, resp);
2522 free(req);
2525 static void start_rtp(struct mgcp_subchannel *sub)
2527 ast_mutex_lock(&sub->lock);
2528 /* check again to be on the safe side */
2529 if (sub->rtp) {
2530 ast_rtp_destroy(sub->rtp);
2531 sub->rtp = NULL;
2533 /* Allocate the RTP now */
2534 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
2535 if (sub->rtp && sub->owner)
2536 sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
2537 if (sub->rtp)
2538 ast_rtp_setnat(sub->rtp, sub->nat);
2539 #if 0
2540 ast_rtp_set_callback(p->rtp, rtpready);
2541 ast_rtp_set_data(p->rtp, p);
2542 #endif
2543 /* Make a call*ID */
2544 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
2545 /* Transmit the connection create */
2546 transmit_connect_with_sdp(sub, NULL);
2547 ast_mutex_unlock(&sub->lock);
2550 static void *mgcp_ss(void *data)
2552 struct ast_channel *chan = data;
2553 struct mgcp_subchannel *sub = chan->tech_pvt;
2554 struct mgcp_endpoint *p = sub->parent;
2555 char exten[AST_MAX_EXTENSION] = "";
2556 int len = 0;
2557 int timeout = firstdigittimeout;
2558 int res;
2559 int getforward = 0;
2561 while(len < AST_MAX_EXTENSION-1) {
2562 res = ast_waitfordigit(chan, timeout);
2563 timeout = 0;
2564 if (res < 0) {
2565 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
2566 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2567 ast_indicate(chan, -1);
2568 ast_hangup(chan);
2569 return NULL;
2570 } else if (res) {
2571 exten[len++]=res;
2572 exten[len] = '\0';
2574 if (!ast_ignore_pattern(chan->context, exten)) {
2575 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2576 ast_indicate(chan, -1);
2577 } else {
2578 /* XXX Redundant? We should already be playing dialtone */
2579 /*tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2580 transmit_notify_request(sub, "L/dl");
2582 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
2583 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
2584 if (getforward) {
2585 /* Record this as the forwarding extension */
2586 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
2587 if (option_verbose > 2) {
2588 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
2589 p->call_forward, chan->name);
2591 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2592 transmit_notify_request(sub, "L/sl");
2593 if (res)
2594 break;
2595 usleep(500000);
2596 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2597 ast_indicate(chan, -1);
2598 sleep(1);
2599 memset(exten, 0, sizeof(exten));
2600 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2601 transmit_notify_request(sub, "L/dl");
2602 len = 0;
2603 getforward = 0;
2604 } else {
2605 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2606 ast_indicate(chan, -1);
2607 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
2608 ast_set_callerid(chan,
2609 p->hidecallerid ? "" : p->cid_num,
2610 p->hidecallerid ? "" : p->cid_name,
2611 chan->cid.cid_ani ? NULL : p->cid_num);
2612 ast_setstate(chan, AST_STATE_RING);
2613 /*zt_enable_ec(p);*/
2614 if (p->dtmfmode & MGCP_DTMF_HYBRID) {
2615 p->dtmfmode |= MGCP_DTMF_INBAND;
2616 ast_indicate(chan, -1);
2618 res = ast_pbx_run(chan);
2619 if (res) {
2620 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2621 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2622 /*transmit_notify_request(p, "nbz", 1);*/
2623 transmit_notify_request(sub, "G/cg");
2625 return NULL;
2627 } else {
2628 /* It's a match, but they just typed a digit, and there is an ambiguous match,
2629 so just set the timeout to matchdigittimeout and wait some more */
2630 timeout = matchdigittimeout;
2632 } else if (res == 0) {
2633 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
2634 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2635 transmit_notify_request(sub, "G/cg");
2636 /*zt_wait_event(p->subs[index].zfd);*/
2637 ast_hangup(chan);
2638 return NULL;
2639 } else if (p->hascallwaiting && p->callwaiting && !strcmp(exten, "*70")) {
2640 if (option_verbose > 2) {
2641 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
2643 /* Disable call waiting if enabled */
2644 p->callwaiting = 0;
2645 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2646 transmit_notify_request(sub, "L/sl");
2647 len = 0;
2648 memset(exten, 0, sizeof(exten));
2649 timeout = firstdigittimeout;
2650 } else if (!strcmp(exten,ast_pickup_ext())) {
2651 /* Scan all channels and see if any there
2652 * ringing channqels with that have call groups
2653 * that equal this channels pickup group
2655 if (ast_pickup_call(chan)) {
2656 ast_log(LOG_WARNING, "No call pickup possible...\n");
2657 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2658 transmit_notify_request(sub, "G/cg");
2660 ast_hangup(chan);
2661 return NULL;
2662 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
2663 if (option_verbose > 2) {
2664 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
2666 /* Disable Caller*ID if enabled */
2667 p->hidecallerid = 1;
2668 ast_set_callerid(chan, "", "", NULL);
2669 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2670 transmit_notify_request(sub, "L/sl");
2671 len = 0;
2672 memset(exten, 0, sizeof(exten));
2673 timeout = firstdigittimeout;
2674 } else if (p->callreturn && !strcmp(exten, "*69")) {
2675 res = 0;
2676 if (!ast_strlen_zero(p->lastcallerid)) {
2677 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
2679 if (!res)
2680 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2681 transmit_notify_request(sub, "L/sl");
2682 break;
2683 } else if (!strcmp(exten, "*78")) {
2684 /* Do not disturb */
2685 if (option_verbose > 2) {
2686 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
2688 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2689 transmit_notify_request(sub, "L/sl");
2690 p->dnd = 1;
2691 getforward = 0;
2692 memset(exten, 0, sizeof(exten));
2693 len = 0;
2694 } else if (!strcmp(exten, "*79")) {
2695 /* Do not disturb */
2696 if (option_verbose > 2) {
2697 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
2699 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2700 transmit_notify_request(sub, "L/sl");
2701 p->dnd = 0;
2702 getforward = 0;
2703 memset(exten, 0, sizeof(exten));
2704 len = 0;
2705 } else if (p->cancallforward && !strcmp(exten, "*72")) {
2706 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2707 transmit_notify_request(sub, "L/sl");
2708 getforward = 1;
2709 memset(exten, 0, sizeof(exten));
2710 len = 0;
2711 } else if (p->cancallforward && !strcmp(exten, "*73")) {
2712 if (option_verbose > 2) {
2713 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
2715 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2716 transmit_notify_request(sub, "L/sl");
2717 memset(p->call_forward, 0, sizeof(p->call_forward));
2718 getforward = 0;
2719 memset(exten, 0, sizeof(exten));
2720 len = 0;
2721 } else if (!strcmp(exten, ast_parking_ext()) &&
2722 sub->next->owner && ast_bridged_channel(sub->next->owner)) {
2723 /* This is a three way call, the main call being a real channel,
2724 and we're parking the first call. */
2725 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
2726 if (option_verbose > 2) {
2727 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
2729 break;
2730 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(exten, "*60")) {
2731 if (option_verbose > 2) {
2732 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
2734 res = ast_db_put("blacklist", p->lastcallerid, "1");
2735 if (!res) {
2736 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2737 transmit_notify_request(sub, "L/sl");
2738 memset(exten, 0, sizeof(exten));
2739 len = 0;
2741 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
2742 if (option_verbose > 2) {
2743 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
2745 /* Enable Caller*ID if enabled */
2746 p->hidecallerid = 0;
2747 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
2748 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2749 transmit_notify_request(sub, "L/sl");
2750 len = 0;
2751 memset(exten, 0, sizeof(exten));
2752 timeout = firstdigittimeout;
2753 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
2754 ((exten[0] != '*') || (strlen(exten) > 2))) {
2755 if (option_debug)
2756 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
2757 break;
2759 if (!timeout)
2760 timeout = gendigittimeout;
2761 if (len && !ast_ignore_pattern(chan->context, exten))
2762 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
2763 ast_indicate(chan, -1);
2765 #if 0
2766 for (;;) {
2767 res = ast_waitfordigit(chan, to);
2768 if (!res) {
2769 ast_log(LOG_DEBUG, "Timeout...\n");
2770 break;
2772 if (res < 0) {
2773 ast_log(LOG_DEBUG, "Got hangup...\n");
2774 ast_hangup(chan);
2775 break;
2777 exten[pos++] = res;
2778 if (!ast_ignore_pattern(chan->context, exten))
2779 ast_indicate(chan, -1);
2780 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
2781 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
2782 to = 3000;
2783 else
2784 to = 8000;
2785 } else
2786 break;
2788 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
2789 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1);
2790 if (!p->rtp) {
2791 start_rtp(p);
2793 ast_setstate(chan, AST_STATE_RING);
2794 chan->rings = 1;
2795 if (ast_pbx_run(chan)) {
2796 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
2797 } else
2798 return NULL;
2800 #endif
2801 ast_hangup(chan);
2802 return NULL;
2805 static int attempt_transfer(struct mgcp_endpoint *p)
2807 /* *************************
2808 * I hope this works.
2809 * Copied out of chan_zap
2810 * Cross your fingers
2811 * *************************/
2813 /* In order to transfer, we need at least one of the channels to
2814 actually be in a call bridge. We can't conference two applications
2815 together (but then, why would we want to?) */
2816 if (ast_bridged_channel(p->sub->owner)) {
2817 /* The three-way person we're about to transfer to could still be in MOH, so
2818 stop if now if appropriate */
2819 if (ast_bridged_channel(p->sub->next->owner))
2820 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
2821 if (p->sub->owner->_state == AST_STATE_RINGING) {
2822 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
2824 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
2825 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2826 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
2827 return -1;
2829 /* Orphan the channel */
2830 unalloc_sub(p->sub->next);
2831 } else if (ast_bridged_channel(p->sub->next->owner)) {
2832 if (p->sub->owner->_state == AST_STATE_RINGING) {
2833 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
2835 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
2836 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
2837 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2838 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
2839 return -1;
2841 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
2842 if (option_verbose > 2) {
2843 ast_verbose(VERBOSE_PREFIX_3 "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
2845 p->sub = p->sub->next;
2846 unalloc_sub(p->sub->next);
2847 /* Tell the caller not to hangup */
2848 return 1;
2849 } else {
2850 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
2851 p->sub->owner->name, p->sub->next->owner->name);
2852 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
2853 if (p->sub->next->owner) {
2854 p->sub->next->alreadygone = 1;
2855 mgcp_queue_hangup(p->sub->next);
2858 return 0;
2861 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
2863 struct mgcp_endpoint *p = sub->parent;
2864 struct ast_channel *c;
2865 pthread_t t;
2866 pthread_attr_t attr;
2867 pthread_attr_init(&attr);
2868 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2870 /* Off hook / answer */
2871 if (sub->outgoing) {
2872 /* Answered */
2873 if (sub->owner) {
2874 if (ast_bridged_channel(sub->owner))
2875 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
2876 sub->cxmode = MGCP_CX_SENDRECV;
2877 if (!sub->rtp) {
2878 start_rtp(sub);
2879 } else {
2880 transmit_modify_request(sub);
2882 /*transmit_notify_request(sub, "aw");*/
2883 transmit_notify_request(sub, "");
2884 mgcp_queue_control(sub, AST_CONTROL_ANSWER);
2886 } else {
2887 /* Start switch */
2888 /*sub->cxmode = MGCP_CX_SENDRECV;*/
2889 if (!sub->owner) {
2890 if (!sub->rtp) {
2891 start_rtp(sub);
2892 } else {
2893 transmit_modify_request(sub);
2895 if (p->immediate) {
2896 /* The channel is immediately up. Start right away */
2897 #ifdef DLINK_BUGGY_FIRMWARE
2898 transmit_notify_request(sub, "rt");
2899 #else
2900 transmit_notify_request(sub, "G/rt");
2901 #endif
2902 c = mgcp_new(sub, AST_STATE_RING);
2903 if (!c) {
2904 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
2905 transmit_notify_request(sub, "G/cg");
2906 ast_hangup(c);
2908 } else {
2909 if (has_voicemail(p)) {
2910 transmit_notify_request(sub, "L/sl");
2911 } else {
2912 transmit_notify_request(sub, "L/dl");
2914 c = mgcp_new(sub, AST_STATE_DOWN);
2915 if (c) {
2916 if (ast_pthread_create(&t, &attr, mgcp_ss, c)) {
2917 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
2918 ast_hangup(c);
2920 } else {
2921 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
2924 } else {
2925 if (p->hookstate == MGCP_OFFHOOK) {
2926 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
2927 } else {
2928 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
2929 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
2931 if (ast_bridged_channel(sub->owner))
2932 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
2933 sub->cxmode = MGCP_CX_SENDRECV;
2934 if (!sub->rtp) {
2935 start_rtp(sub);
2936 } else {
2937 transmit_modify_request(sub);
2939 /*transmit_notify_request(sub, "aw");*/
2940 transmit_notify_request(sub, "");
2941 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
2946 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
2948 char *ev, *s;
2949 struct ast_frame f = { 0, };
2950 struct mgcp_endpoint *p = sub->parent;
2951 struct mgcp_gateway *g = NULL;
2952 int res;
2954 if (mgcpdebug) {
2955 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
2957 /* Clear out potential response */
2958 if (!strcasecmp(req->verb, "RSIP")) {
2959 /* Test if this RSIP request is just a keepalive */
2960 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
2961 if (option_verbose > 2)
2962 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
2963 transmit_response(sub, "200", req, "OK");
2964 } else {
2965 dump_queue(p->parent, p);
2966 dump_cmd_queues(p, NULL);
2968 if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) {
2969 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
2971 /* For RSIP on wildcard we reset all endpoints */
2972 if (!strcmp(p->name, p->parent->wcardep)) {
2973 /* Reset all endpoints */
2974 struct mgcp_endpoint *tmp_ep;
2976 g = p->parent;
2977 tmp_ep = g->endpoints;
2978 while (tmp_ep) {
2979 /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/
2980 if (strcmp(tmp_ep->name, g->wcardep) != 0) {
2981 struct mgcp_subchannel *tmp_sub, *first_sub;
2982 if (option_verbose > 2) {
2983 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
2986 first_sub = tmp_ep->sub;
2987 tmp_sub = tmp_ep->sub;
2988 while (tmp_sub) {
2989 mgcp_queue_hangup(tmp_sub);
2990 tmp_sub = tmp_sub->next;
2991 if (tmp_sub == first_sub)
2992 break;
2995 tmp_ep = tmp_ep->next;
2997 } else if (sub->owner) {
2998 mgcp_queue_hangup(sub);
3000 transmit_response(sub, "200", req, "OK");
3001 /* We dont send NTFY or AUEP to wildcard ep */
3002 if (strcmp(p->name, p->parent->wcardep) != 0) {
3003 transmit_notify_request(sub, "");
3004 /* Audit endpoint.
3005 Idea is to prevent lost lines due to race conditions
3007 transmit_audit_endpoint(p);
3010 } else if (!strcasecmp(req->verb, "NTFY")) {
3011 /* Acknowledge and be sure we keep looking for the same things */
3012 transmit_response(sub, "200", req, "OK");
3013 /* Notified of an event */
3014 ev = get_header(req, "O");
3015 s = strchr(ev, '/');
3016 if (s) ev = s + 1;
3017 ast_log(LOG_DEBUG, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
3018 /* Keep looking for events unless this was a hangup */
3019 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
3020 transmit_notify_request(sub, p->curtone);
3022 if (!strcasecmp(ev, "hd")) {
3023 p->hookstate = MGCP_OFFHOOK;
3024 sub->cxmode = MGCP_CX_SENDRECV;
3025 handle_hd_hf(sub, ev);
3026 } else if (!strcasecmp(ev, "hf")) {
3027 /* We can assume we are offhook if we received a hookflash */
3028 /* First let's just do call wait and ignore threeway */
3029 /* We're currently in charge */
3030 if (p->hookstate != MGCP_OFFHOOK) {
3031 /* Cisco c7940 sends hf even if the phone is onhook */
3032 /* Thanks to point on IRC for pointing this out */
3033 return -1;
3035 /* do not let * conference two down channels */
3036 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
3037 return -1;
3039 if (p->callwaiting || p->transfer || p->threewaycalling) {
3040 if (option_verbose > 2) {
3041 ast_verbose(VERBOSE_PREFIX_3 "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
3043 p->sub = p->sub->next;
3045 /* transfer control to our next subchannel */
3046 if (!sub->next->owner) {
3047 /* plave the first call on hold and start up a new call */
3048 sub->cxmode = MGCP_CX_MUTE;
3049 if (option_verbose > 2) {
3050 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3052 transmit_modify_request(sub);
3053 if (sub->owner && ast_bridged_channel(sub->owner))
3054 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
3055 sub->next->cxmode = MGCP_CX_RECVONLY;
3056 handle_hd_hf(sub->next, ev);
3057 } else if (sub->owner && sub->next->owner) {
3058 /* We've got two active calls lets decide whether or not to conference or just flip flop */
3059 if ((!sub->outgoing) && (!sub->next->outgoing)) {
3060 /* We made both calls lets conferenct */
3061 if (option_verbose > 2) {
3062 ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n",
3063 sub->id, sub->next->id, p->name, p->parent->name);
3065 sub->cxmode = MGCP_CX_CONF;
3066 sub->next->cxmode = MGCP_CX_CONF;
3067 if (ast_bridged_channel(sub->next->owner))
3068 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD);
3069 transmit_modify_request(sub);
3070 transmit_modify_request(sub->next);
3071 } else {
3072 /* Let's flipflop between calls */
3073 /* XXX Need to check for state up ??? */
3074 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
3075 if (option_verbose > 2) {
3076 ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
3077 sub->id, sub->next->id, p->name, p->parent->name);
3079 sub->cxmode = MGCP_CX_MUTE;
3080 if (option_verbose > 2) {
3081 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3083 transmit_modify_request(sub);
3084 if (ast_bridged_channel(sub->owner))
3085 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
3087 if (ast_bridged_channel(sub->next->owner))
3088 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD);
3090 handle_hd_hf(sub->next, ev);
3092 } else {
3093 /* We've most likely lost one of our calls find an active call and bring it up */
3094 if (sub->owner) {
3095 p->sub = sub;
3096 } else if (sub->next->owner) {
3097 p->sub = sub->next;
3098 } else {
3099 /* We seem to have lost both our calls */
3100 /* XXX - What do we do now? */
3101 return -1;
3103 if (ast_bridged_channel(p->sub->owner))
3104 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD);
3105 p->sub->cxmode = MGCP_CX_SENDRECV;
3106 transmit_modify_request(p->sub);
3108 } else {
3109 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
3110 p->name, p->parent->name);
3112 } else if (!strcasecmp(ev, "hu")) {
3113 p->hookstate = MGCP_ONHOOK;
3114 sub->cxmode = MGCP_CX_RECVONLY;
3115 ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
3116 /* Do we need to send MDCX before a DLCX ?
3117 if (sub->rtp) {
3118 transmit_modify_request(sub);
3121 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
3122 /* We're allowed to transfer, we have two avtive calls and */
3123 /* we made at least one of the calls. Let's try and transfer */
3124 ast_mutex_lock(&p->sub->next->lock);
3125 res = attempt_transfer(p);
3126 if (res < 0) {
3127 if (p->sub->next->owner) {
3128 sub->next->alreadygone = 1;
3129 mgcp_queue_hangup(sub->next);
3131 } else if (res) {
3132 ast_log(LOG_WARNING, "Transfer attempt failed\n");
3133 ast_mutex_unlock(&p->sub->next->lock);
3134 return -1;
3136 ast_mutex_unlock(&p->sub->next->lock);
3137 } else {
3138 /* Hangup the current call */
3139 /* If there is another active call, mgcp_hangup will ring the phone with the other call */
3140 if (sub->owner) {
3141 sub->alreadygone = 1;
3142 mgcp_queue_hangup(sub);
3143 } else {
3144 /* verbose level check */
3145 if (option_verbose > 2) {
3146 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
3147 p->name, p->parent->name, sub->id);
3149 /* Instruct the other side to remove the connection since it apparently *
3150 * still thinks the channel is active. *
3151 * For Cisco IAD2421 /BAK/ */
3152 transmit_connection_del(sub);
3155 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
3156 p->hidecallerid = 0;
3157 if (p->hascallwaiting && !p->callwaiting) {
3158 if (option_verbose > 2)
3159 ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
3160 p->callwaiting = -1;
3162 if (has_voicemail(p)) {
3163 if (option_verbose > 2) {
3164 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
3166 transmit_notify_request(sub, "L/vmwi(+)");
3167 } else {
3168 if (option_verbose > 2) {
3169 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
3171 transmit_notify_request(sub, "L/vmwi(-)");
3174 } else if ((strlen(ev) == 1) &&
3175 (((ev[0] >= '0') && (ev[0] <= '9')) ||
3176 ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
3177 (ev[0] == '*') || (ev[0] == '#'))) {
3178 f.frametype = AST_FRAME_DTMF;
3179 f.subclass = ev[0];
3180 f.src = "mgcp";
3181 if (sub->owner) {
3182 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
3183 mgcp_queue_frame(sub, &f);
3184 ast_mutex_lock(&sub->next->lock);
3185 if (sub->next->owner) {
3186 mgcp_queue_frame(sub->next, &f);
3188 ast_mutex_unlock(&sub->next->lock);
3190 if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
3191 memset(p->curtone, 0, sizeof(p->curtone));
3193 } else if (!strcasecmp(ev, "T")) {
3194 /* Digit timeout -- unimportant */
3195 } else if (!strcasecmp(ev, "ping")) {
3196 /* ping -- unimportant */
3197 } else {
3198 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
3200 } else {
3201 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
3202 transmit_response(sub, "510", req, "Unknown verb");
3204 return 0;
3207 static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
3209 int seqno=0;
3210 time_t now;
3211 struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
3212 time(&now);
3213 if (sscanf(req->identifier, "%d", &seqno) != 1)
3214 seqno = 0;
3215 cur = sub->parent->parent->responses;
3216 while(cur) {
3217 next = cur->next;
3218 if (now - cur->whensent > RESPONSE_TIMEOUT) {
3219 /* Delete this entry */
3220 if (prev)
3221 prev->next = next;
3222 else
3223 sub->parent->parent->responses = next;
3224 free(cur);
3225 } else {
3226 if (seqno == cur->seqno)
3227 answer = cur;
3228 prev = cur;
3230 cur = next;
3232 if (answer) {
3233 resend_response(sub, answer);
3234 return 1;
3236 return 0;
3239 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
3241 struct mgcp_request req;
3242 struct sockaddr_in sin;
3243 struct mgcp_subchannel *sub;
3244 int res;
3245 socklen_t len;
3246 int result;
3247 int ident;
3248 len = sizeof(sin);
3249 memset(&req, 0, sizeof(req));
3250 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
3251 if (res < 0) {
3252 if (errno != ECONNREFUSED)
3253 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
3254 return 1;
3256 req.data[res] = '\0';
3257 req.len = res;
3258 if (mgcpdebug) {
3259 ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
3261 parse(&req);
3262 if (req.headers < 1) {
3263 /* Must have at least one header */
3264 return 1;
3266 if (ast_strlen_zero(req.identifier)) {
3267 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
3268 return 1;
3271 if (sscanf(req.verb, "%d", &result) && sscanf(req.identifier, "%d", &ident)) {
3272 /* Try to find who this message is for, if it's important */
3273 sub = find_subchannel_and_lock(NULL, ident, &sin);
3274 if (sub) {
3275 struct mgcp_gateway *gw = sub->parent->parent;
3276 struct mgcp_message *cur, *prev;
3278 ast_mutex_unlock(&sub->lock);
3279 ast_mutex_lock(&gw->msgs_lock);
3280 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
3281 if (cur->seqno == ident) {
3282 ast_log(LOG_DEBUG, "Got response back on transaction %d\n", ident);
3283 if (prev)
3284 prev->next = cur->next;
3285 else
3286 gw->msgs = cur->next;
3287 break;
3291 /* stop retrans timer if the queue is empty */
3292 if (!gw->msgs && (gw->retransid != -1)) {
3293 ast_sched_del(sched, gw->retransid);
3294 gw->retransid = -1;
3297 ast_mutex_unlock(&gw->msgs_lock);
3298 if (cur) {
3299 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
3300 free(cur);
3301 return 1;
3304 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
3305 gw->name, ident);
3307 } else {
3308 if (ast_strlen_zero(req.endpoint) ||
3309 ast_strlen_zero(req.version) ||
3310 ast_strlen_zero(req.verb)) {
3311 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
3312 return 1;
3314 /* Process request, with iflock held */
3315 sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
3316 if (sub) {
3317 /* look first to find a matching response in the queue */
3318 if (!find_and_retrans(sub, &req))
3319 /* pass the request off to the currently mastering subchannel */
3320 handle_request(sub, &req, &sin);
3321 ast_mutex_unlock(&sub->lock);
3324 return 1;
3327 static int *mgcpsock_read_id = NULL;
3329 static void *do_monitor(void *data)
3331 int res;
3332 int reloading;
3333 /*struct mgcp_gateway *g;*/
3334 /*struct mgcp_endpoint *e;*/
3335 /*time_t thispass = 0, lastpass = 0;*/
3337 /* Add an I/O event to our UDP socket */
3338 if (mgcpsock > -1)
3339 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
3341 /* This thread monitors all the frame relay interfaces which are not yet in use
3342 (and thus do not have a separate thread) indefinitely */
3343 /* From here on out, we die whenever asked */
3344 for(;;) {
3345 /* Check for a reload request */
3346 ast_mutex_lock(&mgcp_reload_lock);
3347 reloading = mgcp_reloading;
3348 mgcp_reloading = 0;
3349 ast_mutex_unlock(&mgcp_reload_lock);
3350 if (reloading) {
3351 if (option_verbose > 0)
3352 ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n");
3353 mgcp_do_reload();
3354 /* Add an I/O event to our UDP socket */
3355 if (mgcpsock > -1)
3356 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
3359 /* Check for interfaces needing to be killed */
3360 /* Don't let anybody kill us right away. Nobody should lock the interface list
3361 and wait for the monitor list, but the other way around is okay. */
3362 ast_mutex_lock(&monlock);
3363 /* Lock the network interface */
3364 ast_mutex_lock(&netlock);
3366 #if 0
3367 /* XXX THIS IS COMPLETELY HOSED */
3368 /* The gateway goes into a state of panic */
3369 /* If the vmwi indicator is sent while it is reseting interfaces */
3370 lastpass = thispass;
3371 thispass = time(NULL);
3372 g = gateways;
3373 while(g) {
3374 if (thispass != lastpass) {
3375 e = g->endpoints;
3376 while(e) {
3377 if (e->type == TYPE_LINE) {
3378 res = has_voicemail(e);
3379 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
3380 if (res) {
3381 transmit_notify_request(e, "L/vmwi(+)");
3382 } else {
3383 transmit_notify_request(e, "L/vmwi(-)");
3385 e->msgstate = res;
3386 e->onhooktime = thispass;
3389 e = e->next;
3392 g = g->next;
3394 #endif
3395 /* Okay, now that we know what to do, release the network lock */
3396 ast_mutex_unlock(&netlock);
3397 /* And from now on, we're okay to be killed, so release the monitor lock as well */
3398 ast_mutex_unlock(&monlock);
3399 pthread_testcancel();
3400 /* Wait for sched or io */
3401 res = ast_sched_wait(sched);
3402 /* copied from chan_sip.c */
3403 if ((res < 0) || (res > 1000))
3404 res = 1000;
3405 res = ast_io_wait(io, res);
3406 ast_mutex_lock(&monlock);
3407 if (res >= 0)
3408 ast_sched_runq(sched);
3409 ast_mutex_unlock(&monlock);
3411 /* Never reached */
3412 return NULL;
3415 static int restart_monitor(void)
3417 /* If we're supposed to be stopped -- stay stopped */
3418 if (monitor_thread == AST_PTHREADT_STOP)
3419 return 0;
3420 if (ast_mutex_lock(&monlock)) {
3421 ast_log(LOG_WARNING, "Unable to lock monitor\n");
3422 return -1;
3424 if (monitor_thread == pthread_self()) {
3425 ast_mutex_unlock(&monlock);
3426 ast_log(LOG_WARNING, "Cannot kill myself\n");
3427 return -1;
3429 if (monitor_thread != AST_PTHREADT_NULL) {
3430 /* Wake up the thread */
3431 pthread_kill(monitor_thread, SIGURG);
3432 } else {
3433 /* Start a new monitor */
3434 if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
3435 ast_mutex_unlock(&monlock);
3436 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
3437 return -1;
3440 ast_mutex_unlock(&monlock);
3441 return 0;
3444 static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause)
3446 int oldformat;
3447 struct mgcp_subchannel *sub;
3448 struct ast_channel *tmpc = NULL;
3449 char tmp[256];
3450 char *dest = data;
3452 oldformat = format;
3453 format &= capability;
3454 if (!format) {
3455 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
3456 return NULL;
3458 ast_copy_string(tmp, dest, sizeof(tmp));
3459 if (ast_strlen_zero(tmp)) {
3460 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
3461 return NULL;
3463 sub = find_subchannel_and_lock(tmp, 0, NULL);
3464 if (!sub) {
3465 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
3466 *cause = AST_CAUSE_UNREGISTERED;
3467 return NULL;
3470 if (option_verbose > 2) {
3471 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
3472 ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
3473 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
3475 /* Must be busy */
3476 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
3477 ((!sub->parent->callwaiting) && (sub->owner)) ||
3478 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
3479 if (sub->parent->hookstate == MGCP_ONHOOK) {
3480 if (has_voicemail(sub->parent)) {
3481 transmit_notify_request(sub,"L/vmwi(+)");
3482 } else {
3483 transmit_notify_request(sub,"L/vmwi(-)");
3486 *cause = AST_CAUSE_BUSY;
3487 ast_mutex_unlock(&sub->lock);
3488 return NULL;
3490 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
3491 ast_mutex_unlock(&sub->lock);
3492 if (!tmpc)
3493 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
3494 restart_monitor();
3495 return tmpc;
3498 /* modified for reload support */
3499 /*! \brief build_gateway: parse mgcp.conf and create gateway/endpoint structures */
3500 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
3502 struct mgcp_gateway *gw;
3503 struct mgcp_endpoint *e;
3504 struct mgcp_subchannel *sub;
3505 /*char txident[80];*/
3506 int i=0, y=0;
3507 int gw_reload = 0;
3508 int ep_reload = 0;
3509 canreinvite = CANREINVITE;
3511 /* locate existing gateway */
3512 gw = gateways;
3513 while (gw) {
3514 if (!strcasecmp(cat, gw->name)) {
3515 /* gateway already exists */
3516 gw->delme = 0;
3517 gw_reload = 1;
3518 break;
3520 gw = gw->next;
3523 if (!gw)
3524 gw = malloc(sizeof(struct mgcp_gateway));
3526 if (gw) {
3527 if (!gw_reload) {
3528 memset(gw, 0, sizeof(struct mgcp_gateway));
3529 gw->expire = -1;
3530 gw->retransid = -1; /* SC */
3531 ast_mutex_init(&gw->msgs_lock);
3532 ast_copy_string(gw->name, cat, sizeof(gw->name));
3533 /* check if the name is numeric ip */
3534 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
3535 gw->isnamedottedip = 1;
3537 while(v) {
3538 if (!strcasecmp(v->name, "host")) {
3539 if (!strcasecmp(v->value, "dynamic")) {
3540 /* They'll register with us */
3541 gw->dynamic = 1;
3542 memset(&gw->addr.sin_addr, 0, 4);
3543 if (gw->addr.sin_port) {
3544 /* If we've already got a port, make it the default rather than absolute */
3545 gw->defaddr.sin_port = gw->addr.sin_port;
3546 gw->addr.sin_port = 0;
3548 } else {
3549 /* Non-dynamic. Make sure we become that way if we're not */
3550 if (gw->expire > -1)
3551 ast_sched_del(sched, gw->expire);
3552 gw->expire = -1;
3553 gw->dynamic = 0;
3554 if (ast_get_ip(&gw->addr, v->value)) {
3555 if (!gw_reload) {
3556 ast_mutex_destroy(&gw->msgs_lock);
3557 free(gw);
3559 return NULL;
3562 } else if (!strcasecmp(v->name, "defaultip")) {
3563 if (ast_get_ip(&gw->defaddr, v->value)) {
3564 if (!gw_reload) {
3565 ast_mutex_destroy(&gw->msgs_lock);
3566 free(gw);
3568 return NULL;
3570 } else if (!strcasecmp(v->name, "permit") ||
3571 !strcasecmp(v->name, "deny")) {
3572 gw->ha = ast_append_ha(v->name, v->value, gw->ha);
3573 } else if (!strcasecmp(v->name, "port")) {
3574 gw->addr.sin_port = htons(atoi(v->value));
3575 } else if (!strcasecmp(v->name, "context")) {
3576 strncpy(context, v->value, sizeof(context) - 1);
3577 } else if (!strcasecmp(v->name, "dtmfmode")) {
3578 if (!strcasecmp(v->value, "inband"))
3579 dtmfmode = MGCP_DTMF_INBAND;
3580 else if (!strcasecmp(v->value, "rfc2833"))
3581 dtmfmode = MGCP_DTMF_RFC2833;
3582 else if (!strcasecmp(v->value, "hybrid"))
3583 dtmfmode = MGCP_DTMF_HYBRID;
3584 else if (!strcasecmp(v->value, "none"))
3585 dtmfmode = 0;
3586 else
3587 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
3588 } else if (!strcasecmp(v->name, "nat")) {
3589 nat = ast_true(v->value);
3590 } else if (!strcasecmp(v->name, "callerid")) {
3591 if (!strcasecmp(v->value, "asreceived")) {
3592 cid_num[0] = '\0';
3593 cid_name[0] = '\0';
3594 } else {
3595 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
3597 } else if (!strcasecmp(v->name, "language")) {
3598 strncpy(language, v->value, sizeof(language)-1);
3599 } else if (!strcasecmp(v->name, "accountcode")) {
3600 strncpy(accountcode, v->value, sizeof(accountcode)-1);
3601 } else if (!strcasecmp(v->name, "amaflags")) {
3602 y = ast_cdr_amaflags2int(v->value);
3603 if (y < 0) {
3604 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
3605 } else {
3606 amaflags = y;
3608 } else if (!strcasecmp(v->name, "musiconhold")) {
3609 strncpy(musicclass, v->value, sizeof(musicclass)-1);
3610 } else if (!strcasecmp(v->name, "callgroup")) {
3611 cur_callergroup = ast_get_group(v->value);
3612 } else if (!strcasecmp(v->name, "pickupgroup")) {
3613 cur_pickupgroup = ast_get_group(v->value);
3614 } else if (!strcasecmp(v->name, "immediate")) {
3615 immediate = ast_true(v->value);
3616 } else if (!strcasecmp(v->name, "cancallforward")) {
3617 cancallforward = ast_true(v->value);
3618 } else if (!strcasecmp(v->name, "singlepath")) {
3619 singlepath = ast_true(v->value);
3620 } else if (!strcasecmp(v->name, "canreinvite")) {
3621 canreinvite = ast_true(v->value);
3622 } else if (!strcasecmp(v->name, "mailbox")) {
3623 strncpy(mailbox, v->value, sizeof(mailbox) -1);
3624 } else if (!strcasecmp(v->name, "adsi")) {
3625 adsi = ast_true(v->value);
3626 } else if (!strcasecmp(v->name, "callreturn")) {
3627 callreturn = ast_true(v->value);
3628 } else if (!strcasecmp(v->name, "callwaiting")) {
3629 callwaiting = ast_true(v->value);
3630 } else if (!strcasecmp(v->name, "slowsequence")) {
3631 slowsequence = ast_true(v->value);
3632 } else if (!strcasecmp(v->name, "transfer")) {
3633 transfer = ast_true(v->value);
3634 } else if (!strcasecmp(v->name, "threewaycalling")) {
3635 threewaycalling = ast_true(v->value);
3636 } else if (!strcasecmp(v->name, "wcardep")) {
3637 /* locate existing endpoint */
3638 e = gw->endpoints;
3639 while (e) {
3640 if (!strcasecmp(v->value, e->name)) {
3641 /* endpoint already exists */
3642 e->delme = 0;
3643 ep_reload = 1;
3644 break;
3646 e = e->next;
3649 if (!e) {
3650 /* Allocate wildcard endpoint */
3651 e = malloc(sizeof(struct mgcp_endpoint));
3652 ep_reload = 0;
3655 if (e) {
3656 if (!ep_reload) {
3657 memset(e, 0, sizeof(struct mgcp_endpoint));
3658 ast_mutex_init(&e->lock);
3659 ast_mutex_init(&e->rqnt_queue_lock);
3660 ast_mutex_init(&e->cmd_queue_lock);
3661 strncpy(e->name, v->value, sizeof(e->name) - 1);
3662 e->needaudit = 1;
3664 strncpy(gw->wcardep, v->value, sizeof(gw->wcardep) - 1);
3665 /*strncpy(e->name, "aaln/" "*", sizeof(e->name) - 1);*/
3666 /* XXX Should we really check for uniqueness?? XXX */
3667 strncpy(e->accountcode, accountcode, sizeof(e->accountcode) - 1);
3668 strncpy(e->context, context, sizeof(e->context) - 1);
3669 strncpy(e->cid_num, cid_num, sizeof(e->cid_num) - 1);
3670 strncpy(e->cid_name, cid_name, sizeof(e->cid_name) - 1);
3671 strncpy(e->language, language, sizeof(e->language) - 1);
3672 strncpy(e->musicclass, musicclass, sizeof(e->musicclass) - 1);
3673 strncpy(e->mailbox, mailbox, sizeof(e->mailbox) - 1);
3674 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
3675 e->msgstate = -1;
3676 e->amaflags = amaflags;
3677 e->capability = capability;
3678 e->parent = gw;
3679 e->dtmfmode = dtmfmode;
3680 if (!ep_reload && e->sub && e->sub->rtp)
3681 e->dtmfmode |= MGCP_DTMF_INBAND;
3682 e->adsi = adsi;
3683 e->type = TYPE_LINE;
3684 e->immediate = immediate;
3685 e->callgroup=cur_callergroup;
3686 e->pickupgroup=cur_pickupgroup;
3687 e->callreturn = callreturn;
3688 e->cancallforward = cancallforward;
3689 e->singlepath = singlepath;
3690 e->canreinvite = canreinvite;
3691 e->callwaiting = callwaiting;
3692 e->hascallwaiting = callwaiting;
3693 e->slowsequence = slowsequence;
3694 e->transfer = transfer;
3695 e->threewaycalling = threewaycalling;
3696 e->onhooktime = time(NULL);
3697 /* ASSUME we're onhook */
3698 e->hookstate = MGCP_ONHOOK;
3699 if (!ep_reload) {
3700 /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/
3701 for (i = 0; i < MAX_SUBS; i++) {
3702 sub = malloc(sizeof(struct mgcp_subchannel));
3703 if (sub) {
3704 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
3705 memset(sub, 0, sizeof(struct mgcp_subchannel));
3706 ast_mutex_init(&sub->lock);
3707 ast_mutex_init(&sub->cx_queue_lock);
3708 sub->parent = e;
3709 sub->id = i;
3710 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
3711 /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/
3712 sub->cxmode = MGCP_CX_INACTIVE;
3713 sub->nat = nat;
3714 sub->next = e->sub;
3715 e->sub = sub;
3716 } else {
3717 /* XXX Should find a way to clean up our memory */
3718 ast_log(LOG_WARNING, "Out of memory allocating subchannel");
3719 return NULL;
3722 /* Make out subs a circular linked list so we can always sping through the whole bunch */
3723 sub = e->sub;
3724 /* find the end of the list */
3725 while(sub->next){
3726 sub = sub->next;
3728 /* set the last sub->next to the first sub */
3729 sub->next = e->sub;
3731 e->next = gw->endpoints;
3732 gw->endpoints = e;
3735 } else if (!strcasecmp(v->name, "trunk") ||
3736 !strcasecmp(v->name, "line")) {
3738 /* locate existing endpoint */
3739 e = gw->endpoints;
3740 while (e) {
3741 if (!strcasecmp(v->value, e->name)) {
3742 /* endpoint already exists */
3743 e->delme = 0;
3744 ep_reload = 1;
3745 break;
3747 e = e->next;
3750 if (!e) {
3751 e = malloc(sizeof(struct mgcp_endpoint));
3752 ep_reload = 0;
3755 if (e) {
3756 if (!ep_reload) {
3757 memset(e, 0, sizeof(struct mgcp_endpoint));
3758 ast_mutex_init(&e->lock);
3759 ast_mutex_init(&e->rqnt_queue_lock);
3760 ast_mutex_init(&e->cmd_queue_lock);
3761 strncpy(e->name, v->value, sizeof(e->name) - 1);
3762 e->needaudit = 1;
3764 /* XXX Should we really check for uniqueness?? XXX */
3765 strncpy(e->accountcode, accountcode, sizeof(e->accountcode) - 1);
3766 strncpy(e->context, context, sizeof(e->context) - 1);
3767 strncpy(e->cid_num, cid_num, sizeof(e->cid_num) - 1);
3768 strncpy(e->cid_name, cid_name, sizeof(e->cid_name) - 1);
3769 strncpy(e->language, language, sizeof(e->language) - 1);
3770 strncpy(e->musicclass, musicclass, sizeof(e->musicclass) - 1);
3771 strncpy(e->mailbox, mailbox, sizeof(e->mailbox)-1);
3772 if (!ast_strlen_zero(mailbox)) {
3773 ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
3775 if (!ep_reload) {
3776 /* XXX potential issue due to reload */
3777 e->msgstate = -1;
3778 e->parent = gw;
3780 e->amaflags = amaflags;
3781 e->capability = capability;
3782 e->dtmfmode = dtmfmode;
3783 e->adsi = adsi;
3784 if (!strcasecmp(v->name, "trunk"))
3785 e->type = TYPE_TRUNK;
3786 else
3787 e->type = TYPE_LINE;
3789 e->immediate = immediate;
3790 e->callgroup=cur_callergroup;
3791 e->pickupgroup=cur_pickupgroup;
3792 e->callreturn = callreturn;
3793 e->cancallforward = cancallforward;
3794 e->canreinvite = canreinvite;
3795 e->singlepath = singlepath;
3796 e->callwaiting = callwaiting;
3797 e->hascallwaiting = callwaiting;
3798 e->slowsequence = slowsequence;
3799 e->transfer = transfer;
3800 e->threewaycalling = threewaycalling;
3801 if (!ep_reload) {
3802 e->onhooktime = time(NULL);
3803 /* ASSUME we're onhook */
3804 e->hookstate = MGCP_ONHOOK;
3805 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
3808 for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
3809 if (!ep_reload) {
3810 sub = malloc(sizeof(struct mgcp_subchannel));
3811 } else {
3812 if (!sub)
3813 sub = e->sub;
3814 else
3815 sub = sub->next;
3818 if (sub) {
3819 if (!ep_reload) {
3820 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
3821 memset(sub, 0, sizeof(struct mgcp_subchannel));
3822 ast_mutex_init(&sub->lock);
3823 ast_mutex_init(&sub->cx_queue_lock);
3824 strncpy(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic) - 1);
3825 sub->parent = e;
3826 sub->id = i;
3827 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
3828 sub->cxmode = MGCP_CX_INACTIVE;
3829 sub->next = e->sub;
3830 e->sub = sub;
3832 sub->nat = nat;
3833 } else {
3834 /* XXX Should find a way to clean up our memory */
3835 ast_log(LOG_WARNING, "Out of memory allocating subchannel");
3836 return NULL;
3839 if (!ep_reload) {
3840 /* Make out subs a circular linked list so we can always sping through the whole bunch */
3841 sub = e->sub;
3842 /* find the end of the list */
3843 while (sub->next) {
3844 sub = sub->next;
3846 /* set the last sub->next to the first sub */
3847 sub->next = e->sub;
3849 e->next = gw->endpoints;
3850 gw->endpoints = e;
3853 } else
3854 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
3855 v = v->next;
3858 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
3859 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
3860 if (!gw_reload) {
3861 ast_mutex_destroy(&gw->msgs_lock);
3862 free(gw);
3864 return NULL;
3866 gw->defaddr.sin_family = AF_INET;
3867 gw->addr.sin_family = AF_INET;
3868 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port))
3869 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
3870 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
3871 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
3872 if (gw->addr.sin_addr.s_addr)
3873 if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip))
3874 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
3876 return (gw_reload ? NULL : gw);
3879 static struct ast_rtp *mgcp_get_rtp_peer(struct ast_channel *chan)
3881 struct mgcp_subchannel *sub;
3882 sub = chan->tech_pvt;
3883 if (sub && sub->rtp && sub->parent->canreinvite)
3884 return sub->rtp;
3885 return NULL;
3888 static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
3890 /* XXX Is there such thing as video support with MGCP? XXX */
3891 struct mgcp_subchannel *sub;
3892 sub = chan->tech_pvt;
3893 if (sub && !sub->alreadygone) {
3894 transmit_modify_with_sdp(sub, rtp, codecs);
3895 return 0;
3897 return -1;
3900 static struct ast_rtp_protocol mgcp_rtp = {
3901 .type = "MGCP",
3902 .get_rtp_info = mgcp_get_rtp_peer,
3903 .set_rtp_peer = mgcp_set_rtp_peer,
3906 static int mgcp_do_debug(int fd, int argc, char *argv[])
3908 if (argc != 2)
3909 return RESULT_SHOWUSAGE;
3910 mgcpdebug = 1;
3911 ast_cli(fd, "MGCP Debugging Enabled\n");
3912 return RESULT_SUCCESS;
3915 static int mgcp_no_debug(int fd, int argc, char *argv[])
3917 if (argc != 3)
3918 return RESULT_SHOWUSAGE;
3919 mgcpdebug = 0;
3920 ast_cli(fd, "MGCP Debugging Disabled\n");
3921 return RESULT_SUCCESS;
3924 static char debug_usage[] =
3925 "Usage: mgcp debug\n"
3926 " Enables dumping of MGCP packets for debugging purposes\n";
3928 static char no_debug_usage[] =
3929 "Usage: mgcp no debug\n"
3930 " Disables dumping of MGCP packets for debugging purposes\n";
3932 static char mgcp_reload_usage[] =
3933 "Usage: mgcp reload\n"
3934 " Reloads MGCP configuration from mgcp.conf\n";
3936 static struct ast_cli_entry cli_debug =
3937 { { "mgcp", "debug", NULL }, mgcp_do_debug, "Enable MGCP debugging", debug_usage };
3938 static struct ast_cli_entry cli_no_debug =
3939 { { "mgcp", "no", "debug", NULL }, mgcp_no_debug, "Disable MGCP debugging", no_debug_usage };
3940 static struct ast_cli_entry cli_mgcp_reload =
3941 { { "mgcp", "reload", NULL }, mgcp_reload, "Reload MGCP configuration", mgcp_reload_usage };
3944 static void destroy_endpoint(struct mgcp_endpoint *e)
3946 struct mgcp_subchannel *sub = e->sub->next, *s;
3947 int i;
3949 for (i = 0; i < MAX_SUBS; i++) {
3950 ast_mutex_lock(&sub->lock);
3951 if (!ast_strlen_zero(sub->cxident)) {
3952 transmit_connection_del(sub);
3954 if (sub->rtp) {
3955 ast_rtp_destroy(sub->rtp);
3956 sub->rtp = NULL;
3958 memset(sub->magic, 0, sizeof(sub->magic));
3959 mgcp_queue_hangup(sub);
3960 dump_cmd_queues(NULL, sub);
3961 ast_mutex_unlock(&sub->lock);
3962 sub = sub->next;
3965 if (e->dsp) {
3966 ast_dsp_free(e->dsp);
3969 dump_queue(e->parent, e);
3970 dump_cmd_queues(e, NULL);
3972 sub = e->sub;
3973 for (i = 0; (i < MAX_SUBS) && sub; i++) {
3974 s = sub;
3975 sub = sub->next;
3976 ast_mutex_destroy(&s->lock);
3977 ast_mutex_destroy(&s->cx_queue_lock);
3978 free(s);
3980 ast_mutex_destroy(&e->lock);
3981 ast_mutex_destroy(&e->rqnt_queue_lock);
3982 ast_mutex_destroy(&e->cmd_queue_lock);
3983 free(e);
3986 static void destroy_gateway(struct mgcp_gateway *g)
3988 if (g->ha)
3989 ast_free_ha(g->ha);
3991 dump_queue(g, NULL);
3993 free (g);
3996 static void prune_gateways(void)
3998 struct mgcp_gateway *g, *z, *r;
3999 struct mgcp_endpoint *e, *p, *t;
4001 ast_mutex_lock(&gatelock);
4003 /* prune gateways */
4004 for (z = NULL, g = gateways; g;) {
4005 /* prune endpoints */
4006 for (p = NULL, e = g->endpoints; e; ) {
4007 if (e->delme || g->delme) {
4008 t = e;
4009 e = e->next;
4010 if (!p)
4011 g->endpoints = e;
4012 else
4013 p->next = e;
4014 destroy_endpoint(t);
4015 } else {
4016 p = e;
4017 e = e->next;
4021 if (g->delme) {
4022 r = g;
4023 g = g->next;
4024 if (!z)
4025 gateways = g;
4026 else
4027 z->next = g;
4029 destroy_gateway(r);
4030 } else {
4031 z = g;
4032 g = g->next;
4036 ast_mutex_unlock(&gatelock);
4039 static int reload_config(void)
4041 struct ast_config *cfg;
4042 struct ast_variable *v;
4043 struct mgcp_gateway *g;
4044 struct mgcp_endpoint *e;
4045 char *cat;
4046 struct ast_hostent ahp;
4047 struct hostent *hp;
4048 int format;
4050 if (gethostname(ourhost, sizeof(ourhost)-1)) {
4051 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
4052 return 0;
4054 cfg = ast_config_load(config);
4056 /* We *must* have a config file otherwise stop immediately */
4057 if (!cfg) {
4058 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
4059 return 0;
4061 memset(&bindaddr, 0, sizeof(bindaddr));
4062 dtmfmode = 0;
4064 /* Copy the default jb config over global_jbconf */
4065 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
4067 v = ast_variable_browse(cfg, "general");
4068 while (v) {
4069 /* handle jb conf */
4070 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
4071 v = v->next;
4072 continue;
4075 /* Create the interface list */
4076 if (!strcasecmp(v->name, "bindaddr")) {
4077 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
4078 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
4079 } else {
4080 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
4082 } else if (!strcasecmp(v->name, "allow")) {
4083 format = ast_getformatbyname(v->value);
4084 if (format < 1)
4085 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
4086 else
4087 capability |= format;
4088 } else if (!strcasecmp(v->name, "disallow")) {
4089 format = ast_getformatbyname(v->value);
4090 if (format < 1)
4091 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
4092 else
4093 capability &= ~format;
4094 } else if (!strcasecmp(v->name, "tos")) {
4095 if (sscanf(v->value, "%d", &format) == 1)
4096 tos = format & 0xff;
4097 else if (!strcasecmp(v->value, "lowdelay"))
4098 tos = IPTOS_LOWDELAY;
4099 else if (!strcasecmp(v->value, "throughput"))
4100 tos = IPTOS_THROUGHPUT;
4101 else if (!strcasecmp(v->value, "reliability"))
4102 tos = IPTOS_RELIABILITY;
4103 else if (!strcasecmp(v->value, "mincost"))
4104 tos = IPTOS_MINCOST;
4105 else if (!strcasecmp(v->value, "none"))
4106 tos = 0;
4107 else
4108 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
4109 } else if (!strcasecmp(v->name, "port")) {
4110 if (sscanf(v->value, "%d", &ourport) == 1) {
4111 bindaddr.sin_port = htons(ourport);
4112 } else {
4113 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
4116 v = v->next;
4119 /* mark existing entries for deletion */
4120 ast_mutex_lock(&gatelock);
4121 g = gateways;
4122 while (g) {
4123 g->delme = 1;
4124 e = g->endpoints;
4125 while (e) {
4126 e->delme = 1;
4127 e = e->next;
4129 g = g->next;
4131 ast_mutex_unlock(&gatelock);
4133 cat = ast_category_browse(cfg, NULL);
4134 while(cat) {
4135 if (strcasecmp(cat, "general")) {
4136 ast_mutex_lock(&gatelock);
4137 g = build_gateway(cat, ast_variable_browse(cfg, cat));
4138 if (g) {
4139 if (option_verbose > 2) {
4140 ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
4142 g->next = gateways;
4143 gateways = g;
4145 ast_mutex_unlock(&gatelock);
4147 /* FS: process queue and IO */
4148 if (monitor_thread == pthread_self()) {
4149 if (sched) ast_sched_runq(sched);
4150 if (io) ast_io_wait(io, 10);
4153 cat = ast_category_browse(cfg, cat);
4156 /* prune deleted entries etc. */
4157 prune_gateways();
4159 if (ntohl(bindaddr.sin_addr.s_addr)) {
4160 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
4161 } else {
4162 hp = ast_gethostbyname(ourhost, &ahp);
4163 if (!hp) {
4164 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
4165 ast_config_destroy(cfg);
4166 return 0;
4168 memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
4170 if (!ntohs(bindaddr.sin_port))
4171 bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
4172 bindaddr.sin_family = AF_INET;
4173 ast_mutex_lock(&netlock);
4174 if (mgcpsock > -1)
4175 close(mgcpsock);
4177 if (mgcpsock_read_id != NULL)
4178 ast_io_remove(io, mgcpsock_read_id);
4179 mgcpsock_read_id = NULL;
4181 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
4182 if (mgcpsock < 0) {
4183 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
4184 } else {
4185 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
4186 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
4187 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
4188 strerror(errno));
4189 close(mgcpsock);
4190 mgcpsock = -1;
4191 } else {
4192 if (option_verbose > 1) {
4193 ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n",
4194 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
4195 ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
4197 if (setsockopt(mgcpsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))
4198 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
4201 ast_mutex_unlock(&netlock);
4202 ast_config_destroy(cfg);
4204 /* send audit only to the new endpoints */
4205 g = gateways;
4206 while (g) {
4207 e = g->endpoints;
4208 while (e && e->needaudit) {
4209 e->needaudit = 0;
4210 transmit_audit_endpoint(e);
4211 ast_verbose(VERBOSE_PREFIX_3 "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
4212 e = e->next;
4214 g = g->next;
4217 return 0;
4220 /*! \brief load_module: PBX load module - initialization ---*/
4221 static int load_module(void)
4223 int res;
4225 sched = sched_context_create();
4226 if (!sched) {
4227 ast_log(LOG_WARNING, "Unable to create schedule context\n");
4228 return -1;
4230 io = io_context_create();
4231 if (!io) {
4232 ast_log(LOG_WARNING, "Unable to create I/O context\n");
4233 return -1;
4236 if (!(res = reload_config())) {
4237 /* Make sure we can register our mgcp channel type */
4238 if (ast_channel_register(&mgcp_tech)) {
4239 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
4240 return -1;
4242 ast_rtp_proto_register(&mgcp_rtp);
4243 ast_cli_register(&cli_show_endpoints);
4244 ast_cli_register(&cli_audit_endpoint);
4245 ast_cli_register(&cli_debug);
4246 ast_cli_register(&cli_no_debug);
4247 ast_cli_register(&cli_mgcp_reload);
4249 /* And start the monitor for the first time */
4250 restart_monitor();
4253 return res;
4256 /*! \brief mgcp_do_reload: Reload module */
4257 static int mgcp_do_reload(void)
4259 reload_config();
4260 return 0;
4263 static int mgcp_reload(int fd, int argc, char *argv[])
4265 ast_mutex_lock(&mgcp_reload_lock);
4266 if (mgcp_reloading) {
4267 ast_verbose("Previous mgcp reload not yet done\n");
4268 } else
4269 mgcp_reloading = 1;
4270 ast_mutex_unlock(&mgcp_reload_lock);
4271 restart_monitor();
4272 return 0;
4275 static int reload(void)
4277 mgcp_reload(0, 0, NULL);
4278 return 0;
4281 static int unload_module(void)
4283 struct mgcp_endpoint *e;
4284 struct mgcp_gateway *g;
4286 /* Check to see if we're reloading */
4287 if (ast_mutex_trylock(&mgcp_reload_lock)) {
4288 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n");
4289 return -1;
4290 } else {
4291 mgcp_reloading = 1;
4292 ast_mutex_unlock(&mgcp_reload_lock);
4295 /* First, take us out of the channel loop */
4296 ast_channel_unregister(&mgcp_tech);
4298 /* Shut down the monitoring thread */
4299 if (!ast_mutex_lock(&monlock)) {
4300 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
4301 pthread_cancel(monitor_thread);
4302 pthread_kill(monitor_thread, SIGURG);
4303 pthread_join(monitor_thread, NULL);
4305 monitor_thread = AST_PTHREADT_STOP;
4306 ast_mutex_unlock(&monlock);
4307 } else {
4308 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
4309 /* We always want to leave this in a consistent state */
4310 ast_channel_register(&mgcp_tech);
4311 mgcp_reloading = 0;
4312 mgcp_reload(0, 0, NULL);
4313 return -1;
4316 if (!ast_mutex_lock(&gatelock)) {
4317 for (g = gateways; g; g = g->next) {
4318 g->delme = 1;
4319 for (e = g->endpoints; e; e = e->next)
4320 e->delme = 1;
4323 prune_gateways();
4324 ast_mutex_unlock(&gatelock);
4325 } else {
4326 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
4327 /* We always want to leave this in a consistent state */
4328 ast_channel_register(&mgcp_tech);
4329 /* Allow the monitor to restart */
4330 monitor_thread = AST_PTHREADT_NULL;
4331 mgcp_reloading = 0;
4332 mgcp_reload(0, 0, NULL);
4333 return -1;
4336 close(mgcpsock);
4337 ast_rtp_proto_unregister(&mgcp_rtp);
4338 ast_cli_unregister(&cli_show_endpoints);
4339 ast_cli_unregister(&cli_audit_endpoint);
4340 ast_cli_unregister(&cli_debug);
4341 ast_cli_unregister(&cli_no_debug);
4342 ast_cli_unregister(&cli_mgcp_reload);
4343 sched_context_destroy(sched);
4345 return 0;
4348 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Media Gateway Control Protocol (MGCP)",
4349 .load = load_module,
4350 .unload = unload_module,
4351 .reload = reload,