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.
21 * \brief Implementation of Media Gateway Control Protocol
23 * \author Mark Spencer <markster@digium.com>
26 * \arg \ref Config_mgcp
28 * \ingroup channel_drivers
33 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
38 #include <sys/socket.h>
39 #include <sys/ioctl.h>
45 #include <sys/signal.h>
47 #include <netinet/in.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/ip.h>
50 #include <arpa/inet.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"
81 #define IPTOS_MINCOST 0x02
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 */
91 #define DEFAULT_EXPIRY 120
92 #define MAX_EXPIRY 3600
96 #define INADDR_NONE (in_addr_t)(-1)
99 /*! Global jitterbuffer configuration - by default, jb is disabled */
100 static struct ast_jb_conf default_jbconf
=
104 .resync_threshold
= -1,
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
132 static char *mgcp_cxmodes
[] = {
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;
162 static ast_group_t cur_callergroup
= 0;
163 static ast_group_t cur_pickupgroup
= 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;
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
;
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
{
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
;
255 unsigned long expire
;
258 struct mgcp_message
*next
;
262 #define RESPONSE_TIMEOUT 30 /*!< in seconds */
264 struct mgcp_response
{
268 struct mgcp_response
*next
;
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!"
287 struct ast_channel
*owner
;
288 struct mgcp_endpoint
*parent
;
290 struct sockaddr_in tmpdest
;
291 char txident
[80]; /*! \todo FIXME txident is replaced by rqnt_ident in endpoint.
292 This should be obsoleted */
296 struct mgcp_request
*cx_queue
; /*!< pending CX commands */
297 ast_mutex_t cx_queue_lock
; /*!< CX queue lock */
299 int iseq
; /*!< Not used? RTP? */
302 struct mgcp_subchannel
*next
; /*!< for out circular linked list */
305 #define MGCP_ONHOOK 1
306 #define MGCP_OFFHOOK 2
311 struct mgcp_endpoint
{
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
;
336 int dnd
; /* How does this affect callwait? Do we just deny a mgcp_request if we're dnd? */
342 int slowsequence
; /*!< MS: Sequence the endpoint as a whole */
344 int iseq
; /*!< Not used? */
345 int lastout
; /*!< tracking this on the subchannels. Is it needed here? */
346 int needdestroy
; /*!< Not used? */
348 int nonCodecCapability
;
350 int msgstate
; /*!< voicemail message state */
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 */
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
;
379 int expire
; /*!< XXX Should we ever expire dynamic registrations? XXX */
380 struct mgcp_endpoint
*endpoints
;
387 /* Wildcard endpoint name */
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
;
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
= {
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
,
441 .hangup
= mgcp_hangup
,
442 .answer
= mgcp_answer
,
445 .indicate
= mgcp_indicate
,
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
;
460 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %s@%s?!?\n", p
->name
, p
->parent
->name
);
463 ast_log(LOG_DEBUG
, "Released sub %d of channel %s@%s\n", sub
->id
, p
->name
, p
->parent
->name
);
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
;
473 sub
->alreadygone
= 0;
474 memset(&sub
->tmpdest
, 0, sizeof(sub
->tmpdest
));
476 ast_rtp_destroy(sub
->rtp
);
479 dump_cmd_queues(NULL
, sub
); /* SC */
483 /* modified for new transport mechanism */
484 static int __mgcp_xmit(struct mgcp_gateway
*gw
, char *data
, int len
)
487 if (gw
->addr
.sin_addr
.s_addr
)
488 res
=sendto(mgcpsock
, data
, len
, 0, (struct sockaddr
*)&gw
->addr
, sizeof(struct sockaddr_in
));
490 res
=sendto(mgcpsock
, data
, len
, 0, (struct sockaddr
*)&gw
->defaddr
, sizeof(struct sockaddr_in
));
492 ast_log(LOG_WARNING
, "mgcp_xmit returned %d: %s\n", res
, strerror(errno
));
497 static int resend_response(struct mgcp_subchannel
*sub
, struct mgcp_response
*resp
)
499 struct mgcp_endpoint
*p
= sub
->parent
;
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
);
510 static int send_response(struct mgcp_subchannel
*sub
, struct mgcp_request
*req
)
512 struct mgcp_endpoint
*p
= sub
->parent
;
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
);
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
;
531 if (!p
|| cur
->owner_ep
== p
) {
533 prev
->next
= cur
->next
;
535 gw
->msgs
= cur
->next
;
537 ast_log(LOG_NOTICE
, "Removing message from %s transaction %u\n",
538 gw
->name
, cur
->seqno
);
549 prev
= cur
, cur
=cur
->next
;
552 ast_mutex_unlock(&gw
->msgs_lock
);
561 static void mgcp_queue_frame(struct mgcp_subchannel
*sub
, struct ast_frame
*f
)
565 if (!ast_mutex_trylock(&sub
->owner
->lock
)) {
566 ast_queue_frame(sub
->owner
, f
);
567 ast_mutex_unlock(&sub
->owner
->lock
);
570 ast_mutex_unlock(&sub
->lock
);
572 ast_mutex_lock(&sub
->lock
);
579 static void mgcp_queue_hangup(struct mgcp_subchannel
*sub
)
583 if (!ast_mutex_trylock(&sub
->owner
->lock
)) {
584 ast_queue_hangup(sub
->owner
);
585 ast_mutex_unlock(&sub
->owner
->lock
);
588 ast_mutex_unlock(&sub
->lock
);
590 ast_mutex_lock(&sub
->lock
);
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
;
610 /* find out expired msgs */
611 ast_mutex_lock(&gw
->msgs_lock
);
613 prev
= NULL
, cur
= gw
->msgs
;
615 if (cur
->retrans
< MAX_RETRANS
) {
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
);
627 prev
->next
= cur
->next
;
629 gw
->msgs
= cur
->next
;
631 ast_log(LOG_WARNING
, "Maximum retries exceeded for transaction %u on [%s]\n",
632 cur
->seqno
, gw
->name
);
652 ast_mutex_unlock(&gw
->msgs_lock
);
656 /* time-out transaction */
657 handle_response(cur
->owner_ep
, cur
->owner_sub
, 406, cur
->seqno
, NULL
);
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
);
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
;
694 memcpy(msg
->buf
, data
, msg
->len
);
696 ast_mutex_lock(&gw
->msgs_lock
);
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");
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
);
717 if (!gw->messagepending) {
718 gw->messagepending = 1;
722 __mgcp_xmit(gw
, msg
->buf
, msg
->len
);
723 /* XXX Should schedule retransmission XXX */
726 ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
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
)
736 struct mgcp_request
**queue
, *q
, *r
, *t
;
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
;
747 queue
= &sub
->cx_queue
;
748 l
= &sub
->cx_queue_lock
;
751 /* delete pending cx cmds */
762 queue
= &sub
->cx_queue
;
763 l
= &sub
->cx_queue_lock
;
768 queue
= &p
->rqnt_queue
;
769 l
= &p
->rqnt_queue_lock
;
774 queue
= &p
->cmd_queue
;
775 l
= &p
->cmd_queue_lock
;
781 r
= (struct mgcp_request
*) malloc (sizeof(struct mgcp_request
));
783 ast_log(LOG_WARNING
, "Cannot post MGCP request: insufficient memory\n");
787 memcpy(r
, req
, sizeof(struct mgcp_request
));
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
);
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
);
817 static int mgcp_call(struct ast_channel
*ast
, char *dest
, int timeout
)
820 struct mgcp_endpoint
*p
;
821 struct mgcp_subchannel
*sub
;
823 const char *distinctive_ring
= NULL
;
824 struct varshead
*headp
;
825 struct ast_var_t
*current
;
828 ast_verbose(VERBOSE_PREFIX_3
"MGCP mgcp_call(%s)\n", ast
->name
);
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
) {
843 if (!ast_strlen_zero(distinctive_ring
)) {
844 snprintf(tone
, sizeof(tone
), "L/wt%s", distinctive_ring
);
846 ast_verbose(VERBOSE_PREFIX_3
"MGCP distinctive callwait %s\n", tone
);
849 snprintf(tone
, sizeof(tone
), "L/wt");
851 ast_verbose(VERBOSE_PREFIX_3
"MGCP normal callwait %s\n", tone
);
857 if (!ast_strlen_zero(distinctive_ring
)) {
858 snprintf(tone
, sizeof(tone
), "L/r%s", distinctive_ring
);
860 ast_verbose(VERBOSE_PREFIX_3
"MGCP distinctive ring %s\n", tone
);
863 snprintf(tone
, sizeof(tone
), "L/rg");
865 ast_verbose(VERBOSE_PREFIX_3
"MGCP default ring\n");
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
);
879 sub
->cxmode
= MGCP_CX_RECVONLY
;
880 if (p
->type
== TYPE_LINE
) {
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
);
902 ast_log(LOG_NOTICE
, "Don't know how to dial on trunks yet\n");
905 ast_mutex_unlock(&sub
->lock
);
906 ast_queue_control(ast
, AST_CONTROL_RINGING
);
910 static int mgcp_hangup(struct ast_channel
*ast
)
912 struct mgcp_subchannel
*sub
= ast
->tech_pvt
;
913 struct mgcp_endpoint
*p
= sub
->parent
;
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");
922 if (strcmp(sub
->magic
, MGCP_SUBCHANNEL_MAGIC
)) {
923 ast_log(LOG_DEBUG
, "Invalid magic. MGCP subchannel freed up already.\n");
926 ast_mutex_lock(&sub
->lock
);
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
;
937 ast_verbose(VERBOSE_PREFIX_2
"MGCP free dsp on %s@%s\n", p
->name
, p
->parent
->name
);
939 ast_dsp_free(p
->dsp
);
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
);
955 /* set our other connection as the primary and swith over to it */
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");
969 transmit_notify_request(sub
, "");
972 ast
->tech_pvt
= NULL
;
973 sub
->alreadygone
= 0;
975 sub
->cxmode
= MGCP_CX_INACTIVE
;
976 sub
->callid
[0] = '\0';
977 /* Reset temporary destination */
978 memset(&sub
->tmpdest
, 0, sizeof(sub
->tmpdest
));
980 ast_rtp_destroy(sub
->rtp
);
984 ast_module_unref(ast_module_info
->self
);
986 if ((p
->hookstate
== MGCP_ONHOOK
) && (!sub
->next
->rtp
)) {
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
);
993 if (has_voicemail(p
)) {
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(+)");
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
);
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;
1018 return RESULT_SHOWUSAGE
;
1019 ast_mutex_lock(&gatelock
);
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");
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");
1031 if (!hasendpoints
) {
1032 ast_cli(fd
, " << No Endpoints Defined >> ");
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
;
1052 char *ename
,*gname
, *c
;
1055 return RESULT_SHOWUSAGE
;
1058 return RESULT_SHOWUSAGE
;
1059 /* split the name into parts by null */
1063 if (*gname
== '@') {
1070 if (gname
[0] == '[')
1072 if ((c
= strrchr(gname
, ']')))
1074 ast_mutex_lock(&gatelock
);
1077 if (!strcasecmp(g
->name
, gname
)) {
1080 if (!strcasecmp(e
->name
, ename
)) {
1082 transmit_audit_endpoint(e
);
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
)
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
;
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
);
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
);
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
;
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
)) {
1158 ast_log(LOG_NOTICE
, "MGCP ast_dsp_process\n");
1160 f
= ast_dsp_process(sub
->owner
, sub
->parent
->dsp
, 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
);
1178 static int mgcp_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
1180 struct mgcp_subchannel
*sub
= ast
->tech_pvt
;
1182 if (frame
->frametype
!= AST_FRAME_VOICE
) {
1183 if (frame
->frametype
== AST_FRAME_IMAGE
)
1186 ast_log(LOG_WARNING
, "Can't send %d type frames with MGCP write\n", frame
->frametype
);
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
);
1197 ast_mutex_lock(&sub
->lock
);
1198 if ((sub
->parent
->sub
== sub
) || !sub
->parent
->singlepath
) {
1200 res
= ast_rtp_write(sub
->rtp
, frame
);
1203 ast_mutex_unlock(&sub
->lock
);
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
);
1219 sub
->owner
= newchan
;
1220 ast_mutex_unlock(&sub
->lock
);
1224 static int mgcp_senddigit(struct ast_channel
*ast
, char digit
)
1226 struct mgcp_subchannel
*sub
= ast
->tech_pvt
;
1233 ast_mutex_lock(&sub
->lock
);
1234 transmit_notify_request(sub
, tmp
);
1235 ast_mutex_unlock(&sub
->lock
);
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
, '@'))) {
1262 ast_mutex_lock(&gatelock
);
1265 if (strcasecmp(g
->name
, gw
) == 0) {
1276 if (strcasecmp(e
->name
, endpt
) == 0)
1285 * As long as the gateway/endpoint is valid, we'll
1286 * assume that the device is available and its state
1289 ret
= AST_DEVICE_UNKNOWN
;
1292 ast_mutex_unlock(&gatelock
);
1296 static char *control2str(int 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
:
1318 case AST_CONTROL_OPTION
:
1319 return "Set a low-level option";
1320 case AST_CONTROL_RADIO_KEY
:
1322 case AST_CONTROL_RADIO_UNKEY
:
1323 return "Un-Key Radio";
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
;
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
);
1339 case AST_CONTROL_RINGING
:
1340 #ifdef DLINK_BUGGY_FIRMWARE
1341 transmit_notify_request(sub
, "rt");
1343 transmit_notify_request(sub
, "G/rt");
1346 case AST_CONTROL_BUSY
:
1347 transmit_notify_request(sub
, "L/bz");
1349 case AST_CONTROL_CONGESTION
:
1350 transmit_notify_request(sub
, "G/cg");
1352 case AST_CONTROL_HOLD
:
1353 ast_moh_start(ast
, data
, NULL
);
1355 case AST_CONTROL_UNHOLD
:
1359 transmit_notify_request(sub
, "");
1362 ast_log(LOG_WARNING
, "Don't know how to indicate condition %d\n", ind
);
1365 ast_mutex_unlock(&sub
->lock
);
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
;
1375 tmp
= ast_channel_alloc(1);
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
);
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
);
1393 ast_setstate(tmp
, state
);
1394 if (state
== AST_STATE_RING
)
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
);
1406 tmp
->amaflags
= i
->amaflags
;
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
);
1422 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
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
);
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
));
1439 ast_log(LOG_WARNING
, "Unable to allocate channel structure\n");
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
;
1454 static char *get_sdp(struct mgcp_request
*req
, char *name
)
1457 int len
= strlen(name
);
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
;
1467 static void sdpLineNum_iterator_init(int* iterator
)
1472 static char* get_sdp_iterate(int* iterator
, struct mgcp_request
*req
, char *name
)
1474 int len
= strlen(name
);
1476 while (*iterator
< req
->lines
) {
1477 r
= get_sdp_by_line(req
->line
[(*iterator
)++], name
, len
);
1478 if (r
[0] != '\0') return r
;
1483 static char *__get_header(struct mgcp_request
*req
, char *name
, int *start
)
1486 int len
= strlen(name
);
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))
1498 /* Don't return NULL, so get_header is always a valid pointer */
1502 static char *get_header(struct mgcp_request
*req
, char *name
)
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
)
1513 *next
= NULL
, *len
= 0;
1514 if (!c
) return NULL
;
1516 while (*c
&& (*c
< 33 || *c
== ','))
1520 while (*c
&& (*c
>= 33 && *c
!= ','))
1525 s
= NULL
, *next
= NULL
;
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
;
1536 char *at
= NULL
, *c
;
1539 ast_copy_string(tmp
, name
, sizeof(tmp
));
1540 at
= strchr(tmp
, '@');
1542 ast_log(LOG_NOTICE
, "Endpoint '%s' has no at sign!\n", name
);
1547 ast_mutex_lock(&gatelock
);
1548 if (at
&& (at
[0] == '[')) {
1550 c
= strrchr(at
, ']');
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 */
1571 if (strcasecmp(g
->name
, at
)) {
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
)) {
1591 ast_log(LOG_DEBUG
, "Searching on %s@%s for subchannel\n",
1594 #if 0 /* new transport mech */
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
) {
1602 ast_log(LOG_DEBUG
, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
1603 sub
->id
, msgid
, sub
->lastout
);
1608 } while (sub
!= p
->sub
);
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
);
1628 ast_mutex_lock(&sub
->lock
);
1634 ast_mutex_unlock(&gatelock
);
1638 ast_log(LOG_NOTICE
, "Endpoint '%s' not found on gateway '%s'\n", tmp
, at
);
1640 ast_log(LOG_NOTICE
, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at
, tmp
);
1646 static void parse(struct mgcp_request
*req
)
1648 /* Divide fields by NULL's */
1653 /* First header starts immediately */
1657 /* We've got a new header */
1660 printf("Header: %s (%d)\n", req
->header
[f
], strlen(req
->header
[f
]));
1662 if (ast_strlen_zero(req
->header
[f
])) {
1663 /* Line by itself means we're now in content */
1667 if (f
>= MGCP_MAX_HEADERS
- 1) {
1668 ast_log(LOG_WARNING
, "Too many MGCP headers...\n");
1671 req
->header
[f
] = c
+ 1;
1672 } else if (*c
== '\r') {
1673 /* Ignore but eliminate \r's */
1678 /* Check for last header */
1679 if (!ast_strlen_zero(req
->header
[f
]))
1682 /* Now we process any mime content */
1687 /* We've got a new line */
1690 printf("Line: %s (%d)\n", req
->line
[f
], strlen(req
->line
[f
]));
1692 if (f
>= MGCP_MAX_LINES
- 1) {
1693 ast_log(LOG_WARNING
, "Too many SDP lines...\n");
1696 req
->line
[f
] = c
+ 1;
1697 } else if (*c
== '\r') {
1698 /* Ignore and eliminate \r's */
1703 /* Check for last line */
1704 if (!ast_strlen_zero(req
->line
[f
]))
1707 /* Parse up the initial header */
1709 while(*c
&& *c
< 33) c
++;
1710 /* First the verb */
1712 while(*c
&& (*c
> 32)) c
++;
1716 while(*c
&& (*c
< 33)) c
++;
1717 req
->identifier
= c
;
1718 while(*c
&& (*c
> 32)) c
++;
1722 while(*c
&& (*c
< 33)) c
++;
1724 while(*c
&& (*c
> 32)) c
++;
1728 while(*c
&& (*c
< 33)) c
++;
1730 while(*c
&& (*c
> 32)) c
++;
1731 while(*c
&& (*c
< 33)) c
++;
1732 while(*c
&& (*c
> 32)) c
++;
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
);
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
)
1755 int peercapability
, peerNonCodecCapability
;
1756 struct sockaddr_in sin
;
1758 struct ast_hostent ahp
; struct hostent
*hp
;
1759 int codec
, codec_count
=0;
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
);
1770 if (sscanf(c
, "IN IP4 %256s", host
) != 1) {
1771 ast_log(LOG_WARNING
, "Invalid host in c= line, '%s'\n", c
);
1774 /* XXX This could block for a long time, and block the main thread! XXX */
1775 hp
= ast_gethostbyname(host
, &ahp
);
1777 ast_log(LOG_WARNING
, "Unable to lookup host in c= line, '%s'\n", c
);
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
);
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
);
1789 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin
.sin_addr
), ntohs(sin
.sin_port
));
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) {
1798 ast_log(LOG_WARNING
, "Error in codec string '%s' at '%s'\n", m
, codecs
);
1801 ast_rtp_set_m_type(sub
->rtp
, codec
);
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)
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
;
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");
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");
1840 ast_log(LOG_WARNING
, "Can't add more headers when lines have been added\n");
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
)
1849 ast_log(LOG_WARNING
, "Out of header space\n");
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");
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
)
1872 ast_log(LOG_WARNING
, "Out of line space\n");
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");
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
)
1891 ast_log(LOG_WARNING
, "Out of header space\n");
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");
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
);
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
)
1912 ast_log(LOG_WARNING
, "Out of header space\n");
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
);
1924 static int reqprep(struct mgcp_request
*req
, struct mgcp_endpoint
*p
, char *verb
)
1926 memset(req
, 0, sizeof(struct mgcp_request
));
1928 if (oseq
> 999999999)
1930 init_req(p
, req
, verb
);
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);
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
)
1962 struct sockaddr_in sin
;
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 */
1977 ast_log(LOG_WARNING
, "No way to add SDP without an RTP structure\n");
1980 ast_rtp_get_us(sub
->rtp
, &sin
);
1982 ast_rtp_get_peer(rtp
, &dest
);
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
));
1990 dest
.sin_addr
= p
->parent
->ourip
;
1991 dest
.sin_port
= sin
.sin_port
;
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
) {
2006 ast_verbose("Answering with capability %d\n", x
);
2008 codec
= ast_rtp_lookup_code(sub
->rtp
, 1, x
);
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
) {
2020 ast_verbose("Answering with non-codec capability %d\n", x
);
2022 codec
= ast_rtp_lookup_code(sub
->rtp
, 0, x
);
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
);
2050 static int transmit_modify_with_sdp(struct mgcp_subchannel
*sub
, struct ast_rtp
*rtp
, int codecs
)
2052 struct mgcp_request resp
;
2057 struct mgcp_endpoint
*p
= sub
->parent
;
2059 capability
= p
->capability
;
2061 capability
= codecs
;
2062 if (ast_strlen_zero(sub
->cxident
) && rtp
) {
2063 /* We don't have a CXident yet, store the destination and
2065 ast_rtp_get_peer(rtp
, &sub
->tmpdest
);
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
;
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
;
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);
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
;
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
;
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
) {
2137 add_header(&resp
, "R", "L/hd(N)");
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)");
2143 if (!ast_strlen_zero(tone
)) {
2144 add_header(&resp
, "S", tone
);
2146 /* fill in new fields */
2147 resp
.cmd
= MGCP_CMD_RQNT
;
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
;
2159 struct mgcp_endpoint
*p
= sub
->parent
;
2162 localtime_r(&t
,&tm
);
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
) {
2180 add_header(&resp
, "R", "L/hd(N)");
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)");
2186 if (!ast_strlen_zero(tone2
)) {
2187 add_header(&resp
, "S", tone2
);
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
;
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
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
) {
2221 add_header(&resp
, "R", "L/hd(N)");
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)");
2227 /* fill in new fields */
2228 resp
.cmd
= MGCP_CMD_MDCX
;
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
;
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
;
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 */
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
;
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
;
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
;
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
;
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
);
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
;
2333 for (prev
= NULL
, req
= *queue
; req
; prev
= req
, req
= req
->next
) {
2334 if (req
->trid
== ident
) {
2335 /* remove from queue */
2339 prev
->next
= req
->next
;
2341 /* send next pending command */
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
);
2353 ast_mutex_unlock(l
);
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
)
2362 struct mgcp_request
*req
;
2363 struct mgcp_gateway
*gw
= p
->parent
;
2366 /* provisional response */
2370 if (p
->slowsequence
)
2371 req
= find_command(p
, sub
, &p
->cmd_queue
, &p
->cmd_queue_lock
, ident
);
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
);
2378 if (option_verbose
> 2) {
2379 ast_verbose(VERBOSE_PREFIX_3
"No command found on [%s] for transaction %d. Ignoring...\n",
2385 if (p
&& (result
>= 400) && (result
<= 599)) {
2388 p
->hookstate
= MGCP_OFFHOOK
;
2391 p
->hookstate
= MGCP_ONHOOK
;
2394 ast_log(LOG_NOTICE
, "Transaction %d timed out\n", ident
);
2397 ast_log(LOG_NOTICE
, "Transaction %d aborted\n", ident
);
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
);
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
);
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. */
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);
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"))) {
2454 while ((v
= get_csv(c
, &len
, &n
))) {
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
);
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
) {
2517 process_sdp(sub
, resp
);
2525 static void start_rtp(struct mgcp_subchannel
*sub
)
2527 ast_mutex_lock(&sub
->lock
);
2528 /* check again to be on the safe side */
2530 ast_rtp_destroy(sub
->rtp
);
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
);
2538 ast_rtp_setnat(sub
->rtp
, sub
->nat
);
2540 ast_rtp_set_callback(p
->rtp
, rtpready
);
2541 ast_rtp_set_data(p
->rtp
, p
);
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
] = "";
2557 int timeout
= firstdigittimeout
;
2561 while(len
< AST_MAX_EXTENSION
-1) {
2562 res
= ast_waitfordigit(chan
, timeout
);
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);
2574 if (!ast_ignore_pattern(chan
->context
, exten
)) {
2575 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2576 ast_indicate(chan
, -1);
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
)) {
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");
2596 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2597 ast_indicate(chan
, -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");
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
);
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");
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);*/
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 */
2645 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2646 transmit_notify_request(sub
, "L/sl");
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");
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");
2672 memset(exten
, 0, sizeof(exten
));
2673 timeout
= firstdigittimeout
;
2674 } else if (p
->callreturn
&& !strcmp(exten
, "*69")) {
2676 if (!ast_strlen_zero(p
->lastcallerid
)) {
2677 res
= ast_say_digit_str(chan
, p
->lastcallerid
, "", chan
->language
);
2680 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2681 transmit_notify_request(sub
, "L/sl");
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");
2692 memset(exten
, 0, sizeof(exten
));
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");
2703 memset(exten
, 0, sizeof(exten
));
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");
2709 memset(exten
, 0, sizeof(exten
));
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
));
2719 memset(exten
, 0, sizeof(exten
));
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
);
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");
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
));
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");
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))) {
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
);
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);
2767 res
= ast_waitfordigit(chan
, to
);
2769 ast_log(LOG_DEBUG
, "Timeout...\n");
2773 ast_log(LOG_DEBUG
, "Got hangup...\n");
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
))
2788 if (ast_exists_extension(chan
, chan
->context
, exten
, 1, chan
->callerid
)) {
2789 ast_copy_string(chan
->exten
, exten
, sizeof(chan
->exten
)1);
2793 ast_setstate(chan
, AST_STATE_RING
);
2795 if (ast_pbx_run(chan
)) {
2796 ast_log(LOG_WARNING
, "Unable to launch PBX on %s\n", chan
->name
);
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
);
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
);
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 */
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
);
2861 static void handle_hd_hf(struct mgcp_subchannel
*sub
, char *ev
)
2863 struct mgcp_endpoint
*p
= sub
->parent
;
2864 struct ast_channel
*c
;
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
) {
2874 if (ast_bridged_channel(sub
->owner
))
2875 ast_queue_control(sub
->owner
, AST_CONTROL_UNHOLD
);
2876 sub
->cxmode
= MGCP_CX_SENDRECV
;
2880 transmit_modify_request(sub
);
2882 /*transmit_notify_request(sub, "aw");*/
2883 transmit_notify_request(sub
, "");
2884 mgcp_queue_control(sub
, AST_CONTROL_ANSWER
);
2888 /*sub->cxmode = MGCP_CX_SENDRECV;*/
2893 transmit_modify_request(sub
);
2896 /* The channel is immediately up. Start right away */
2897 #ifdef DLINK_BUGGY_FIRMWARE
2898 transmit_notify_request(sub
, "rt");
2900 transmit_notify_request(sub
, "G/rt");
2902 c
= mgcp_new(sub
, AST_STATE_RING
);
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");
2909 if (has_voicemail(p
)) {
2910 transmit_notify_request(sub
, "L/sl");
2912 transmit_notify_request(sub
, "L/dl");
2914 c
= mgcp_new(sub
, AST_STATE_DOWN
);
2916 if (ast_pthread_create(&t
, &attr
, mgcp_ss
, c
)) {
2917 ast_log(LOG_WARNING
, "Unable to create switch thread: %s\n", strerror(errno
));
2921 ast_log(LOG_WARNING
, "Unable to create channel for %s@%s\n", p
->name
, p
->parent
->name
);
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
);
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
;
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
)
2949 struct ast_frame f
= { 0, };
2950 struct mgcp_endpoint
*p
= sub
->parent
;
2951 struct mgcp_gateway
*g
= NULL
;
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");
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
;
2977 tmp_ep
= g
->endpoints
;
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
;
2989 mgcp_queue_hangup(tmp_sub
);
2990 tmp_sub
= tmp_sub
->next
;
2991 if (tmp_sub
== first_sub
)
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
, "");
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
, '/');
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 */
3035 /* do not let * conference two down channels */
3036 if (sub
->owner
&& sub
->owner
->_state
== AST_STATE_DOWN
&& !sub
->next
->owner
)
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
);
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
);
3093 /* We've most likely lost one of our calls find an active call and bring it up */
3096 } else if (sub
->next
->owner
) {
3099 /* We seem to have lost both our calls */
3100 /* XXX - What do we do now? */
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
);
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 ?
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
);
3127 if (p
->sub
->next
->owner
) {
3128 sub
->next
->alreadygone
= 1;
3129 mgcp_queue_hangup(sub
->next
);
3132 ast_log(LOG_WARNING
, "Transfer attempt failed\n");
3133 ast_mutex_unlock(&p
->sub
->next
->lock
);
3136 ast_mutex_unlock(&p
->sub
->next
->lock
);
3138 /* Hangup the current call */
3139 /* If there is another active call, mgcp_hangup will ring the phone with the other call */
3141 sub
->alreadygone
= 1;
3142 mgcp_queue_hangup(sub
);
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(+)");
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
;
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 */
3198 ast_log(LOG_NOTICE
, "Received unknown event '%s' from %s@%s\n", ev
, p
->name
, p
->parent
->name
);
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");
3207 static int find_and_retrans(struct mgcp_subchannel
*sub
, struct mgcp_request
*req
)
3211 struct mgcp_response
*prev
= NULL
, *cur
, *next
, *answer
=NULL
;
3213 if (sscanf(req
->identifier
, "%d", &seqno
) != 1)
3215 cur
= sub
->parent
->parent
->responses
;
3218 if (now
- cur
->whensent
> RESPONSE_TIMEOUT
) {
3219 /* Delete this entry */
3223 sub
->parent
->parent
->responses
= next
;
3226 if (seqno
== cur
->seqno
)
3233 resend_response(sub
, answer
);
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
;
3249 memset(&req
, 0, sizeof(req
));
3250 res
= recvfrom(mgcpsock
, req
.data
, sizeof(req
.data
) - 1, 0, (struct sockaddr
*)&sin
, &len
);
3252 if (errno
!= ECONNREFUSED
)
3253 ast_log(LOG_WARNING
, "Recv error: %s\n", strerror(errno
));
3256 req
.data
[res
] = '\0';
3259 ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req
.data
, ast_inet_ntoa(sin
.sin_addr
), ntohs(sin
.sin_port
));
3262 if (req
.headers
< 1) {
3263 /* Must have at least one header */
3266 if (ast_strlen_zero(req
.identifier
)) {
3267 ast_log(LOG_NOTICE
, "Message from %s missing identifier\n", ast_inet_ntoa(sin
.sin_addr
));
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
);
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
);
3284 prev
->next
= cur
->next
;
3286 gw
->msgs
= cur
->next
;
3291 /* stop retrans timer if the queue is empty */
3292 if (!gw
->msgs
&& (gw
->retransid
!= -1)) {
3293 ast_sched_del(sched
, gw
->retransid
);
3297 ast_mutex_unlock(&gw
->msgs_lock
);
3299 handle_response(cur
->owner_ep
, cur
->owner_sub
, result
, ident
, &req
);
3304 ast_log(LOG_NOTICE
, "Got response back on [%s] for transaction %d we aren't sending?\n",
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");
3314 /* Process request, with iflock held */
3315 sub
= find_subchannel_and_lock(req
.endpoint
, 0, &sin
);
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
);
3327 static int *mgcpsock_read_id
= NULL
;
3329 static void *do_monitor(void *data
)
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 */
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 */
3345 /* Check for a reload request */
3346 ast_mutex_lock(&mgcp_reload_lock
);
3347 reloading
= mgcp_reloading
;
3349 ast_mutex_unlock(&mgcp_reload_lock
);
3351 if (option_verbose
> 0)
3352 ast_verbose(VERBOSE_PREFIX_1
"Reloading MGCP\n");
3354 /* Add an I/O event to our UDP socket */
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
);
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
);
3374 if (thispass
!= lastpass
) {
3377 if (e
->type
== TYPE_LINE
) {
3378 res
= has_voicemail(e
);
3379 if ((e
->msgstate
!= res
) && (e
->hookstate
== MGCP_ONHOOK
) && (!e
->rtp
)){
3381 transmit_notify_request(e
, "L/vmwi(+)");
3383 transmit_notify_request(e
, "L/vmwi(-)");
3386 e
->onhooktime
= thispass
;
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))
3405 res
= ast_io_wait(io
, res
);
3406 ast_mutex_lock(&monlock
);
3408 ast_sched_runq(sched
);
3409 ast_mutex_unlock(&monlock
);
3415 static int restart_monitor(void)
3417 /* If we're supposed to be stopped -- stay stopped */
3418 if (monitor_thread
== AST_PTHREADT_STOP
)
3420 if (ast_mutex_lock(&monlock
)) {
3421 ast_log(LOG_WARNING
, "Unable to lock monitor\n");
3424 if (monitor_thread
== pthread_self()) {
3425 ast_mutex_unlock(&monlock
);
3426 ast_log(LOG_WARNING
, "Cannot kill myself\n");
3429 if (monitor_thread
!= AST_PTHREADT_NULL
) {
3430 /* Wake up the thread */
3431 pthread_kill(monitor_thread
, SIGURG
);
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");
3440 ast_mutex_unlock(&monlock
);
3444 static struct ast_channel
*mgcp_request(const char *type
, int format
, void *data
, int *cause
)
3447 struct mgcp_subchannel
*sub
;
3448 struct ast_channel
*tmpc
= NULL
;
3453 format
&= capability
;
3455 ast_log(LOG_NOTICE
, "Asked to get a channel of unsupported format '%d'\n", format
);
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");
3463 sub
= find_subchannel_and_lock(tmp
, 0, NULL
);
3465 ast_log(LOG_WARNING
, "Unable to find MGCP endpoint '%s'\n", tmp
);
3466 *cause
= AST_CAUSE_UNREGISTERED
;
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);
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(+)");
3483 transmit_notify_request(sub
,"L/vmwi(-)");
3486 *cause
= AST_CAUSE_BUSY
;
3487 ast_mutex_unlock(&sub
->lock
);
3490 tmpc
= mgcp_new(sub
->owner
? sub
->next
: sub
, AST_STATE_DOWN
);
3491 ast_mutex_unlock(&sub
->lock
);
3493 ast_log(LOG_WARNING
, "Unable to make channel for '%s'\n", tmp
);
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];*/
3509 canreinvite
= CANREINVITE
;
3511 /* locate existing gateway */
3514 if (!strcasecmp(cat
, gw
->name
)) {
3515 /* gateway already exists */
3524 gw
= malloc(sizeof(struct mgcp_gateway
));
3528 memset(gw
, 0, sizeof(struct mgcp_gateway
));
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;
3538 if (!strcasecmp(v
->name
, "host")) {
3539 if (!strcasecmp(v
->value
, "dynamic")) {
3540 /* They'll register with us */
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;
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
);
3554 if (ast_get_ip(&gw
->addr
, v
->value
)) {
3556 ast_mutex_destroy(&gw
->msgs_lock
);
3562 } else if (!strcasecmp(v
->name
, "defaultip")) {
3563 if (ast_get_ip(&gw
->defaddr
, v
->value
)) {
3565 ast_mutex_destroy(&gw
->msgs_lock
);
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"))
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")) {
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
);
3604 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d\n", v
->value
, v
->lineno
);
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 */
3640 if (!strcasecmp(v
->value
, e
->name
)) {
3641 /* endpoint already exists */
3650 /* Allocate wildcard endpoint */
3651 e
= malloc(sizeof(struct mgcp_endpoint
));
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);
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());
3676 e
->amaflags
= amaflags
;
3677 e
->capability
= capability
;
3679 e
->dtmfmode
= dtmfmode
;
3680 if (!ep_reload
&& e
->sub
&& e
->sub
->rtp
)
3681 e
->dtmfmode
|= MGCP_DTMF_INBAND
;
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
;
3700 /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/
3701 for (i
= 0; i
< MAX_SUBS
; i
++) {
3702 sub
= malloc(sizeof(struct mgcp_subchannel
));
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
);
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
;
3717 /* XXX Should find a way to clean up our memory */
3718 ast_log(LOG_WARNING
, "Out of memory allocating subchannel");
3722 /* Make out subs a circular linked list so we can always sping through the whole bunch */
3724 /* find the end of the list */
3728 /* set the last sub->next to the first sub */
3731 e
->next
= gw
->endpoints
;
3735 } else if (!strcasecmp(v
->name
, "trunk") ||
3736 !strcasecmp(v
->name
, "line")) {
3738 /* locate existing endpoint */
3741 if (!strcasecmp(v
->value
, e
->name
)) {
3742 /* endpoint already exists */
3751 e
= malloc(sizeof(struct mgcp_endpoint
));
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);
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
);
3776 /* XXX potential issue due to reload */
3780 e
->amaflags
= amaflags
;
3781 e
->capability
= capability
;
3782 e
->dtmfmode
= dtmfmode
;
3784 if (!strcasecmp(v
->name
, "trunk"))
3785 e
->type
= TYPE_TRUNK
;
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
;
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
++) {
3810 sub
= malloc(sizeof(struct mgcp_subchannel
));
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);
3827 snprintf(sub
->txident
, sizeof(sub
->txident
), "%08lx", ast_random());
3828 sub
->cxmode
= MGCP_CX_INACTIVE
;
3834 /* XXX Should find a way to clean up our memory */
3835 ast_log(LOG_WARNING
, "Out of memory allocating subchannel");
3840 /* Make out subs a circular linked list so we can always sping through the whole bunch */
3842 /* find the end of the list */
3846 /* set the last sub->next to the first sub */
3849 e
->next
= gw
->endpoints
;
3854 ast_log(LOG_WARNING
, "Don't know keyword '%s' at line %d\n", v
->name
, v
->lineno
);
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
);
3861 ast_mutex_destroy(&gw
->msgs_lock
);
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
)
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
);
3900 static struct ast_rtp_protocol mgcp_rtp
= {
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
[])
3909 return RESULT_SHOWUSAGE
;
3911 ast_cli(fd
, "MGCP Debugging Enabled\n");
3912 return RESULT_SUCCESS
;
3915 static int mgcp_no_debug(int fd
, int argc
, char *argv
[])
3918 return RESULT_SHOWUSAGE
;
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
;
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
);
3955 ast_rtp_destroy(sub
->rtp
);
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
);
3966 ast_dsp_free(e
->dsp
);
3969 dump_queue(e
->parent
, e
);
3970 dump_cmd_queues(e
, NULL
);
3973 for (i
= 0; (i
< MAX_SUBS
) && sub
; i
++) {
3976 ast_mutex_destroy(&s
->lock
);
3977 ast_mutex_destroy(&s
->cx_queue_lock
);
3980 ast_mutex_destroy(&e
->lock
);
3981 ast_mutex_destroy(&e
->rqnt_queue_lock
);
3982 ast_mutex_destroy(&e
->cmd_queue_lock
);
3986 static void destroy_gateway(struct mgcp_gateway
*g
)
3991 dump_queue(g
, NULL
);
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
) {
4014 destroy_endpoint(t
);
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
;
4046 struct ast_hostent ahp
;
4050 if (gethostname(ourhost
, sizeof(ourhost
)-1)) {
4051 ast_log(LOG_WARNING
, "Unable to get hostname, MGCP disabled\n");
4054 cfg
= ast_config_load(config
);
4056 /* We *must* have a config file otherwise stop immediately */
4058 ast_log(LOG_NOTICE
, "Unable to load config %s, MGCP disabled\n", config
);
4061 memset(&bindaddr
, 0, sizeof(bindaddr
));
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");
4069 /* handle jb conf */
4070 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
)) {
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
);
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
);
4085 ast_log(LOG_WARNING
, "Cannot allow unknown format '%s'\n", v
->value
);
4087 capability
|= format
;
4088 } else if (!strcasecmp(v
->name
, "disallow")) {
4089 format
= ast_getformatbyname(v
->value
);
4091 ast_log(LOG_WARNING
, "Cannot disallow unknown format '%s'\n", v
->value
);
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"))
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
);
4113 ast_log(LOG_WARNING
, "Invalid port number '%s' at line %d of %s\n", v
->value
, v
->lineno
, config
);
4119 /* mark existing entries for deletion */
4120 ast_mutex_lock(&gatelock
);
4131 ast_mutex_unlock(&gatelock
);
4133 cat
= ast_category_browse(cfg
, NULL
);
4135 if (strcasecmp(cat
, "general")) {
4136 ast_mutex_lock(&gatelock
);
4137 g
= build_gateway(cat
, ast_variable_browse(cfg
, cat
));
4139 if (option_verbose
> 2) {
4140 ast_verbose(VERBOSE_PREFIX_3
"Added gateway '%s'\n", g
->name
);
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. */
4159 if (ntohl(bindaddr
.sin_addr
.s_addr
)) {
4160 memcpy(&__ourip
, &bindaddr
.sin_addr
, sizeof(__ourip
));
4162 hp
= ast_gethostbyname(ourhost
, &ahp
);
4164 ast_log(LOG_WARNING
, "Unable to get our IP address, MGCP disabled\n");
4165 ast_config_destroy(cfg
);
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
);
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);
4183 ast_log(LOG_WARNING
, "Unable to create MGCP socket: %s\n", strerror(errno
));
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
),
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 */
4208 while (e
&& e
->needaudit
) {
4210 transmit_audit_endpoint(e
);
4211 ast_verbose(VERBOSE_PREFIX_3
"MGCP Auditing endpoint %s@%s for hookstate\n", e
->name
, g
->name
);
4220 /*! \brief load_module: PBX load module - initialization ---*/
4221 static int load_module(void)
4225 sched
= sched_context_create();
4227 ast_log(LOG_WARNING
, "Unable to create schedule context\n");
4230 io
= io_context_create();
4232 ast_log(LOG_WARNING
, "Unable to create I/O context\n");
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");
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 */
4256 /*! \brief mgcp_do_reload: Reload module */
4257 static int mgcp_do_reload(void)
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");
4270 ast_mutex_unlock(&mgcp_reload_lock
);
4275 static int reload(void)
4277 mgcp_reload(0, 0, NULL
);
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");
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
);
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
);
4312 mgcp_reload(0, 0, NULL
);
4316 if (!ast_mutex_lock(&gatelock
)) {
4317 for (g
= gateways
; g
; g
= g
->next
) {
4319 for (e
= g
->endpoints
; e
; e
= e
->next
)
4324 ast_mutex_unlock(&gatelock
);
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
;
4332 mgcp_reload(0, 0, NULL
);
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
);
4348 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Media Gateway Control Protocol (MGCP)",
4349 .load
= load_module
,
4350 .unload
= unload_module
,