00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00037
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <unistd.h>
00041 #include <sys/socket.h>
00042 #include <sys/ioctl.h>
00043 #include <net/if.h>
00044 #include <errno.h>
00045 #include <stdlib.h>
00046 #include <fcntl.h>
00047 #include <netdb.h>
00048 #include <sys/signal.h>
00049 #include <signal.h>
00050 #include <netinet/in.h>
00051 #include <netinet/in_systm.h>
00052 #include <netinet/ip.h>
00053 #include <arpa/inet.h>
00054 #include <ctype.h>
00055
00056 #include "asterisk/lock.h"
00057 #include "asterisk/channel.h"
00058 #include "asterisk/config.h"
00059 #include "asterisk/logger.h"
00060 #include "asterisk/module.h"
00061 #include "asterisk/pbx.h"
00062 #include "asterisk/options.h"
00063 #include "asterisk/lock.h"
00064 #include "asterisk/sched.h"
00065 #include "asterisk/io.h"
00066 #include "asterisk/rtp.h"
00067 #include "asterisk/acl.h"
00068 #include "asterisk/callerid.h"
00069 #include "asterisk/cli.h"
00070 #include "asterisk/say.h"
00071 #include "asterisk/cdr.h"
00072 #include "asterisk/astdb.h"
00073 #include "asterisk/features.h"
00074 #include "asterisk/app.h"
00075 #include "asterisk/musiconhold.h"
00076 #include "asterisk/utils.h"
00077 #include "asterisk/causes.h"
00078 #include "asterisk/dsp.h"
00079 #include "asterisk/devicestate.h"
00080 #include "asterisk/stringfields.h"
00081 #include "asterisk/abstract_jb.h"
00082
00083 #ifndef IPTOS_MINCOST
00084 #define IPTOS_MINCOST 0x02
00085 #endif
00086
00087
00088
00089
00090
00091
00092
00093 #define MGCPDUMPER
00094 #define DEFAULT_EXPIRY 120
00095 #define MAX_EXPIRY 3600
00096 #define CANREINVITE 1
00097
00098 #ifndef INADDR_NONE
00099 #define INADDR_NONE (in_addr_t)(-1)
00100 #endif
00101
00102
00103 static struct ast_jb_conf default_jbconf =
00104 {
00105 .flags = 0,
00106 .max_size = -1,
00107 .resync_threshold = -1,
00108 .impl = ""
00109 };
00110 static struct ast_jb_conf global_jbconf;
00111
00112 static const char tdesc[] = "Media Gateway Control Protocol (MGCP)";
00113 static const char config[] = "mgcp.conf";
00114
00115 #define MGCP_DTMF_RFC2833 (1 << 0)
00116 #define MGCP_DTMF_INBAND (1 << 1)
00117 #define MGCP_DTMF_HYBRID (1 << 2)
00118
00119 #define DEFAULT_MGCP_GW_PORT 2427
00120 #define DEFAULT_MGCP_CA_PORT 2727
00121 #define MGCP_MAX_PACKET 1500
00122 #define DEFAULT_RETRANS 1000
00123 #define MAX_RETRANS 5
00124
00125
00126 #define MGCP_CX_SENDONLY 0
00127 #define MGCP_CX_RECVONLY 1
00128 #define MGCP_CX_SENDRECV 2
00129 #define MGCP_CX_CONF 3
00130 #define MGCP_CX_CONFERENCE 3
00131 #define MGCP_CX_MUTE 4
00132 #define MGCP_CX_INACTIVE 4
00133
00134
00135 static char *mgcp_cxmodes[] = {
00136 "sendonly",
00137 "recvonly",
00138 "sendrecv",
00139 "confrnce",
00140 "inactive"
00141 };
00142
00143 enum {
00144 MGCP_CMD_EPCF,
00145 MGCP_CMD_CRCX,
00146 MGCP_CMD_MDCX,
00147 MGCP_CMD_DLCX,
00148 MGCP_CMD_RQNT,
00149 MGCP_CMD_NTFY,
00150 MGCP_CMD_AUEP,
00151 MGCP_CMD_AUCX,
00152 MGCP_CMD_RSIP
00153 };
00154
00155 static char context[AST_MAX_EXTENSION] = "default";
00156
00157 static char language[MAX_LANGUAGE] = "";
00158 static char musicclass[MAX_MUSICCLASS] = "";
00159 static char cid_num[AST_MAX_EXTENSION] = "";
00160 static char cid_name[AST_MAX_EXTENSION] = "";
00161
00162 static int dtmfmode = 0;
00163 static int nat = 0;
00164
00165 static ast_group_t cur_callergroup = 0;
00166 static ast_group_t cur_pickupgroup = 0;
00167
00168 static int tos = 0;
00169
00170 static int immediate = 0;
00171
00172 static int callwaiting = 0;
00173
00174 static int callreturn = 0;
00175
00176 static int slowsequence = 0;
00177
00178 static int threewaycalling = 0;
00179
00180
00181 static int transfer = 0;
00182
00183 static int cancallforward = 0;
00184
00185 static int singlepath = 0;
00186
00187 static int canreinvite = CANREINVITE;
00188
00189 static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
00190
00191 static char mailbox[AST_MAX_EXTENSION];
00192
00193 static int amaflags = 0;
00194
00195 static int adsi = 0;
00196
00197 static unsigned int oseq;
00198
00199
00200 static int firstdigittimeout = 16000;
00201
00202
00203 static int gendigittimeout = 8000;
00204
00205
00206 static int matchdigittimeout = 3000;
00207
00208
00209
00210 AST_MUTEX_DEFINE_STATIC(netlock);
00211
00212 AST_MUTEX_DEFINE_STATIC(monlock);
00213
00214
00215
00216 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00217
00218 static int restart_monitor(void);
00219
00220 static int capability = AST_FORMAT_ULAW;
00221 static int nonCodecCapability = AST_RTP_DTMF;
00222
00223 static char ourhost[MAXHOSTNAMELEN];
00224 static struct in_addr __ourip;
00225 static int ourport;
00226
00227 static int mgcpdebug = 0;
00228
00229 static struct sched_context *sched;
00230 static struct io_context *io;
00231
00232
00233
00234 #define MGCP_MAX_HEADERS 64
00235 #define MGCP_MAX_LINES 64
00236
00237 struct mgcp_request {
00238 int len;
00239 char *verb;
00240 char *identifier;
00241 char *endpoint;
00242 char *version;
00243 int headers;
00244 char *header[MGCP_MAX_HEADERS];
00245 int lines;
00246 char *line[MGCP_MAX_LINES];
00247 char data[MGCP_MAX_PACKET];
00248 int cmd;
00249 unsigned int trid;
00250 struct mgcp_request *next;
00251 };
00252
00253
00254 struct mgcp_message {
00255 struct mgcp_endpoint *owner_ep;
00256 struct mgcp_subchannel *owner_sub;
00257 int retrans;
00258 unsigned long expire;
00259 unsigned int seqno;
00260 int len;
00261 struct mgcp_message *next;
00262 char buf[0];
00263 };
00264
00265 #define RESPONSE_TIMEOUT 30
00266
00267 struct mgcp_response {
00268 time_t whensent;
00269 int len;
00270 int seqno;
00271 struct mgcp_response *next;
00272 char buf[0];
00273 };
00274
00275 #define MAX_SUBS 2
00276
00277 #define SUB_REAL 0
00278 #define SUB_ALT 1
00279
00280 struct mgcp_subchannel {
00281
00282
00283
00284
00285
00286 #define MGCP_SUBCHANNEL_MAGIC "!978!"
00287 char magic[6];
00288 ast_mutex_t lock;
00289 int id;
00290 struct ast_channel *owner;
00291 struct mgcp_endpoint *parent;
00292 struct ast_rtp *rtp;
00293 struct sockaddr_in tmpdest;
00294 char txident[80];
00295
00296 char cxident[80];
00297 char callid[80];
00298 int cxmode;
00299 struct mgcp_request *cx_queue;
00300 ast_mutex_t cx_queue_lock;
00301 int nat;
00302 int iseq;
00303 int outgoing;
00304 int alreadygone;
00305 struct mgcp_subchannel *next;
00306 };
00307
00308 #define MGCP_ONHOOK 1
00309 #define MGCP_OFFHOOK 2
00310
00311 #define TYPE_TRUNK 1
00312 #define TYPE_LINE 2
00313
00314 struct mgcp_endpoint {
00315 ast_mutex_t lock;
00316 char name[80];
00317 struct mgcp_subchannel *sub;
00318 char accountcode[AST_MAX_ACCOUNT_CODE];
00319 char exten[AST_MAX_EXTENSION];
00320 char context[AST_MAX_EXTENSION];
00321 char language[MAX_LANGUAGE];
00322 char cid_num[AST_MAX_EXTENSION];
00323 char cid_name[AST_MAX_EXTENSION];
00324 char lastcallerid[AST_MAX_EXTENSION];
00325 char call_forward[AST_MAX_EXTENSION];
00326 char mailbox[AST_MAX_EXTENSION];
00327 char musicclass[MAX_MUSICCLASS];
00328 char curtone[80];
00329 char dtmf_buf[AST_MAX_EXTENSION];
00330 ast_group_t callgroup;
00331 ast_group_t pickupgroup;
00332 int callwaiting;
00333 int hascallwaiting;
00334 int transfer;
00335 int threewaycalling;
00336 int singlepath;
00337 int cancallforward;
00338 int canreinvite;
00339 int callreturn;
00340 int dnd;
00341 int hascallerid;
00342 int hidecallerid;
00343 int dtmfmode;
00344 int amaflags;
00345 int type;
00346 int slowsequence;
00347 int group;
00348 int iseq;
00349 int lastout;
00350 int needdestroy;
00351 int capability;
00352 int nonCodecCapability;
00353 int onhooktime;
00354 int msgstate;
00355 int immediate;
00356 int hookstate;
00357 int adsi;
00358 char rqnt_ident[80];
00359 struct mgcp_request *rqnt_queue;
00360 ast_mutex_t rqnt_queue_lock;
00361 struct mgcp_request *cmd_queue;
00362 ast_mutex_t cmd_queue_lock;
00363 int delme;
00364 int needaudit;
00365 struct ast_dsp *dsp;
00366
00367
00368
00369
00370
00371 struct mgcp_endpoint *next;
00372 struct mgcp_gateway *parent;
00373 };
00374
00375 static struct mgcp_gateway {
00376
00377 char name[80];
00378 int isnamedottedip;
00379 struct sockaddr_in addr;
00380 struct sockaddr_in defaddr;
00381 struct in_addr ourip;
00382 int dynamic;
00383 int expire;
00384 struct mgcp_endpoint *endpoints;
00385 struct ast_ha *ha;
00386
00387
00388
00389
00390
00391
00392 char wcardep[30];
00393 struct mgcp_message *msgs;
00394 ast_mutex_t msgs_lock;
00395 int retransid;
00396 int delme;
00397 struct mgcp_response *responses;
00398 struct mgcp_gateway *next;
00399 } *gateways;
00400
00401 AST_MUTEX_DEFINE_STATIC(mgcp_reload_lock);
00402 static int mgcp_reloading = 0;
00403
00404
00405 AST_MUTEX_DEFINE_STATIC(gatelock);
00406
00407 static int mgcpsock = -1;
00408
00409 static struct sockaddr_in bindaddr;
00410
00411 static struct ast_frame *mgcp_read(struct ast_channel *ast);
00412 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
00413 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
00414 static int transmit_modify_request(struct mgcp_subchannel *sub);
00415 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
00416 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs);
00417 static int transmit_connection_del(struct mgcp_subchannel *sub);
00418 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
00419 static void start_rtp(struct mgcp_subchannel *sub);
00420 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
00421 int result, unsigned int ident, struct mgcp_request *resp);
00422 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
00423 static int mgcp_do_reload(void);
00424 static int mgcp_reload(int fd, int argc, char *argv[]);
00425
00426 static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause);
00427 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout);
00428 static int mgcp_hangup(struct ast_channel *ast);
00429 static int mgcp_answer(struct ast_channel *ast);
00430 static struct ast_frame *mgcp_read(struct ast_channel *ast);
00431 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame);
00432 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
00433 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00434 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
00435 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
00436 static int mgcp_devicestate(void *data);
00437 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp);
00438
00439 static const struct ast_channel_tech mgcp_tech = {
00440 .type = "MGCP",
00441 .description = tdesc,
00442 .capabilities = AST_FORMAT_ULAW,
00443 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
00444 .requester = mgcp_request,
00445 .devicestate = mgcp_devicestate,
00446 .call = mgcp_call,
00447 .hangup = mgcp_hangup,
00448 .answer = mgcp_answer,
00449 .read = mgcp_read,
00450 .write = mgcp_write,
00451 .indicate = mgcp_indicate,
00452 .fixup = mgcp_fixup,
00453 .send_digit_begin = mgcp_senddigit_begin,
00454 .send_digit_end = mgcp_senddigit_end,
00455 .bridge = ast_rtp_bridge,
00456 };
00457
00458 static int has_voicemail(struct mgcp_endpoint *p)
00459 {
00460 return ast_app_has_voicemail(p->mailbox, NULL);
00461 }
00462
00463 static int unalloc_sub(struct mgcp_subchannel *sub)
00464 {
00465 struct mgcp_endpoint *p = sub->parent;
00466 if (p->sub == sub) {
00467 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
00468 return -1;
00469 }
00470 ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
00471
00472 sub->owner = NULL;
00473 if (!ast_strlen_zero(sub->cxident)) {
00474 transmit_connection_del(sub);
00475 }
00476 sub->cxident[0] = '\0';
00477 sub->callid[0] = '\0';
00478 sub->cxmode = MGCP_CX_INACTIVE;
00479 sub->outgoing = 0;
00480 sub->alreadygone = 0;
00481 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00482 if (sub->rtp) {
00483 ast_rtp_destroy(sub->rtp);
00484 sub->rtp = NULL;
00485 }
00486 dump_cmd_queues(NULL, sub);
00487 return 0;
00488 }
00489
00490
00491 static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
00492 {
00493 int res;
00494 if (gw->addr.sin_addr.s_addr)
00495 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
00496 else
00497 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
00498 if (res != len) {
00499 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
00500 }
00501 return res;
00502 }
00503
00504 static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
00505 {
00506 struct mgcp_endpoint *p = sub->parent;
00507 int res;
00508 if (mgcpdebug) {
00509 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));
00510 }
00511 res = __mgcp_xmit(p->parent, resp->buf, resp->len);
00512 if (res > 0)
00513 res = 0;
00514 return res;
00515 }
00516
00517 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
00518 {
00519 struct mgcp_endpoint *p = sub->parent;
00520 int res;
00521 if (mgcpdebug) {
00522 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));
00523 }
00524 res = __mgcp_xmit(p->parent, req->data, req->len);
00525 if (res > 0)
00526 res = 0;
00527 return res;
00528 }
00529
00530
00531 static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
00532 {
00533 struct mgcp_message *cur, *q = NULL, *w, *prev;
00534
00535 ast_mutex_lock(&gw->msgs_lock);
00536 prev = NULL, cur = gw->msgs;
00537 while (cur) {
00538 if (!p || cur->owner_ep == p) {
00539 if (prev)
00540 prev->next = cur->next;
00541 else
00542 gw->msgs = cur->next;
00543
00544 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
00545 gw->name, cur->seqno);
00546
00547 w = cur;
00548 cur = cur->next;
00549 if (q) {
00550 w->next = q;
00551 } else {
00552 w->next = NULL;
00553 }
00554 q = w;
00555 } else {
00556 prev = cur, cur=cur->next;
00557 }
00558 }
00559 ast_mutex_unlock(&gw->msgs_lock);
00560
00561 while (q) {
00562 cur = q;
00563 q = q->next;
00564 free(cur);
00565 }
00566 }
00567
00568 static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
00569 {
00570 for(;;) {
00571 if (sub->owner) {
00572 if (!ast_mutex_trylock(&sub->owner->lock)) {
00573 ast_queue_frame(sub->owner, f);
00574 ast_mutex_unlock(&sub->owner->lock);
00575 break;
00576 } else {
00577 ast_mutex_unlock(&sub->lock);
00578 usleep(1);
00579 ast_mutex_lock(&sub->lock);
00580 }
00581 } else
00582 break;
00583 }
00584 }
00585
00586 static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
00587 {
00588 for(;;) {
00589 if (sub->owner) {
00590 if (!ast_mutex_trylock(&sub->owner->lock)) {
00591 ast_queue_hangup(sub->owner);
00592 ast_mutex_unlock(&sub->owner->lock);
00593 break;
00594 } else {
00595 ast_mutex_unlock(&sub->lock);
00596 usleep(1);
00597 ast_mutex_lock(&sub->lock);
00598 }
00599 } else
00600 break;
00601 }
00602 }
00603
00604 static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
00605 {
00606 struct ast_frame f = { AST_FRAME_CONTROL, };
00607 f.subclass = control;
00608 return mgcp_queue_frame(sub, &f);
00609 }
00610
00611 static int retrans_pkt(const void *data)
00612 {
00613 struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
00614 struct mgcp_message *cur, *exq = NULL, *w, *prev;
00615 int res = 0;
00616
00617
00618 ast_mutex_lock(&gw->msgs_lock);
00619
00620 prev = NULL, cur = gw->msgs;
00621 while (cur) {
00622 if (cur->retrans < MAX_RETRANS) {
00623 cur->retrans++;
00624 if (mgcpdebug) {
00625 ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
00626 cur->retrans, cur->seqno, gw->name);
00627 }
00628 __mgcp_xmit(gw, cur->buf, cur->len);
00629
00630 prev = cur;
00631 cur = cur->next;
00632 } else {
00633 if (prev)
00634 prev->next = cur->next;
00635 else
00636 gw->msgs = cur->next;
00637
00638 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
00639 cur->seqno, gw->name);
00640
00641 w = cur;
00642 cur = cur->next;
00643
00644 if (exq) {
00645 w->next = exq;
00646 } else {
00647 w->next = NULL;
00648 }
00649 exq = w;
00650 }
00651 }
00652
00653 if (!gw->msgs) {
00654 gw->retransid = -1;
00655 res = 0;
00656 } else {
00657 res = 1;
00658 }
00659 ast_mutex_unlock(&gw->msgs_lock);
00660
00661 while (exq) {
00662 cur = exq;
00663
00664 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
00665 exq = exq->next;
00666 free(cur);
00667 }
00668
00669 return res;
00670 }
00671
00672
00673 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
00674 char *data, int len, unsigned int seqno)
00675 {
00676 struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
00677 struct mgcp_message *cur;
00678 struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
00679 struct timeval tv;
00680
00681 if (!msg) {
00682 return -1;
00683 }
00684 if (!gw) {
00685 return -1;
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695 msg->owner_sub = sub;
00696 msg->owner_ep = p;
00697 msg->seqno = seqno;
00698 msg->next = NULL;
00699 msg->len = len;
00700 msg->retrans = 0;
00701 memcpy(msg->buf, data, msg->len);
00702
00703 ast_mutex_lock(&gw->msgs_lock);
00704 cur = gw->msgs;
00705 if (cur) {
00706 while(cur->next)
00707 cur = cur->next;
00708 cur->next = msg;
00709 } else {
00710 gw->msgs = msg;
00711 }
00712
00713 if (gettimeofday(&tv, NULL) < 0) {
00714
00715 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
00716 } else {
00717 msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
00718
00719 if (gw->retransid == -1)
00720 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
00721 }
00722 ast_mutex_unlock(&gw->msgs_lock);
00723
00724
00725
00726
00727
00728
00729 __mgcp_xmit(gw, msg->buf, msg->len);
00730
00731
00732
00733
00734
00735 return 0;
00736 }
00737
00738
00739 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
00740 struct mgcp_request *req, unsigned int seqno)
00741 {
00742 int res = 0;
00743 struct mgcp_request **queue, *q, *r, *t;
00744 ast_mutex_t *l;
00745
00746 ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);
00747 if (p->slowsequence) {
00748 queue = &p->cmd_queue;
00749 l = &p->cmd_queue_lock;
00750 ast_mutex_lock(l);
00751 } else {
00752 switch (req->cmd) {
00753 case MGCP_CMD_DLCX:
00754 queue = &sub->cx_queue;
00755 l = &sub->cx_queue_lock;
00756 ast_mutex_lock(l);
00757 q = sub->cx_queue;
00758
00759 while (q) {
00760 r = q->next;
00761 free(q);
00762 q = r;
00763 }
00764 *queue = NULL;
00765 break;
00766
00767 case MGCP_CMD_CRCX:
00768 case MGCP_CMD_MDCX:
00769 queue = &sub->cx_queue;
00770 l = &sub->cx_queue_lock;
00771 ast_mutex_lock(l);
00772 break;
00773
00774 case MGCP_CMD_RQNT:
00775 queue = &p->rqnt_queue;
00776 l = &p->rqnt_queue_lock;
00777 ast_mutex_lock(l);
00778 break;
00779
00780 default:
00781 queue = &p->cmd_queue;
00782 l = &p->cmd_queue_lock;
00783 ast_mutex_lock(l);
00784 break;
00785 }
00786 }
00787
00788 r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
00789 if (!r) {
00790 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
00791 ast_mutex_unlock(l);
00792 return -1;
00793 }
00794 memcpy(r, req, sizeof(struct mgcp_request));
00795
00796 if (!(*queue)) {
00797 if (mgcpdebug) {
00798 ast_verbose("Posting Request:\n%s to %s:%d\n", req->data,
00799 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00800 }
00801
00802 res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
00803 } else {
00804 if (mgcpdebug) {
00805 ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data,
00806 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00807 }
00808 }
00809
00810
00811 for (t = *queue; t && t->next; t = t->next);
00812
00813 r->next = NULL;
00814 if (t)
00815 t->next = r;
00816 else
00817 *queue = r;
00818
00819 ast_mutex_unlock(l);
00820
00821 return res;
00822 }
00823
00824 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
00825 {
00826 int res;
00827 struct mgcp_endpoint *p;
00828 struct mgcp_subchannel *sub;
00829 char tone[50] = "";
00830 const char *distinctive_ring = NULL;
00831 struct varshead *headp;
00832 struct ast_var_t *current;
00833
00834 if (mgcpdebug) {
00835 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);
00836 }
00837 sub = ast->tech_pvt;
00838 p = sub->parent;
00839 headp = &ast->varshead;
00840 AST_LIST_TRAVERSE(headp,current,entries) {
00841
00842 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {
00843 distinctive_ring = ast_var_value(current);
00844 }
00845 }
00846
00847 ast_mutex_lock(&sub->lock);
00848 switch (p->hookstate) {
00849 case MGCP_OFFHOOK:
00850 if (!ast_strlen_zero(distinctive_ring)) {
00851 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
00852 if (mgcpdebug) {
00853 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive callwait %s\n", tone);
00854 }
00855 } else {
00856 snprintf(tone, sizeof(tone), "L/wt");
00857 if (mgcpdebug) {
00858 ast_verbose(VERBOSE_PREFIX_3 "MGCP normal callwait %s\n", tone);
00859 }
00860 }
00861 break;
00862 case MGCP_ONHOOK:
00863 default:
00864 if (!ast_strlen_zero(distinctive_ring)) {
00865 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
00866 if (mgcpdebug) {
00867 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive ring %s\n", tone);
00868 }
00869 } else {
00870 snprintf(tone, sizeof(tone), "L/rg");
00871 if (mgcpdebug) {
00872 ast_verbose(VERBOSE_PREFIX_3 "MGCP default ring\n");
00873 }
00874 }
00875 break;
00876 }
00877
00878 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00879 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
00880 ast_mutex_unlock(&sub->lock);
00881 return -1;
00882 }
00883
00884 res = 0;
00885 sub->outgoing = 1;
00886 sub->cxmode = MGCP_CX_RECVONLY;
00887 if (p->type == TYPE_LINE) {
00888 if (!sub->rtp) {
00889 start_rtp(sub);
00890 } else {
00891 transmit_modify_request(sub);
00892 }
00893
00894 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00895
00896 sub->next->cxmode = MGCP_CX_RECVONLY;
00897 transmit_modify_request(sub->next);
00898 }
00899
00900 transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
00901 ast_setstate(ast, AST_STATE_RINGING);
00902
00903 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00904
00905 sub->next->cxmode = MGCP_CX_SENDRECV;
00906 transmit_modify_request(sub->next);
00907 }
00908 } else {
00909 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
00910 res = -1;
00911 }
00912 ast_mutex_unlock(&sub->lock);
00913 ast_queue_control(ast, AST_CONTROL_RINGING);
00914 return res;
00915 }
00916
00917 static int mgcp_hangup(struct ast_channel *ast)
00918 {
00919 struct mgcp_subchannel *sub = ast->tech_pvt;
00920 struct mgcp_endpoint *p = sub->parent;
00921
00922 if (option_debug) {
00923 ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
00924 }
00925 if (!ast->tech_pvt) {
00926 ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
00927 return 0;
00928 }
00929 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
00930 ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
00931 return 0;
00932 }
00933 ast_mutex_lock(&sub->lock);
00934 if (mgcpdebug) {
00935 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
00936 }
00937
00938 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
00939
00940 if (!sub->next->owner) {
00941 if (p->dtmfmode & MGCP_DTMF_HYBRID)
00942 p->dtmfmode &= ~MGCP_DTMF_INBAND;
00943 if (mgcpdebug) {
00944 ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
00945 }
00946 ast_dsp_free(p->dsp);
00947 p->dsp = NULL;
00948 }
00949 }
00950
00951 sub->owner = NULL;
00952 if (!ast_strlen_zero(sub->cxident)) {
00953 transmit_connection_del(sub);
00954 }
00955 sub->cxident[0] = '\0';
00956 if ((sub == p->sub) && sub->next->owner) {
00957 if (p->hookstate == MGCP_OFFHOOK) {
00958 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00959 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);
00960 }
00961 } else {
00962
00963 p->sub = sub->next;
00964 p->sub->cxmode = MGCP_CX_RECVONLY;
00965 transmit_modify_request(p->sub);
00966 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00967 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);
00968 }
00969 }
00970
00971 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
00972 transmit_notify_request(sub, "L/v");
00973 } else if (p->hookstate == MGCP_OFFHOOK) {
00974 transmit_notify_request(sub, "L/ro");
00975 } else {
00976 transmit_notify_request(sub, "");
00977 }
00978
00979 ast->tech_pvt = NULL;
00980 sub->alreadygone = 0;
00981 sub->outgoing = 0;
00982 sub->cxmode = MGCP_CX_INACTIVE;
00983 sub->callid[0] = '\0';
00984 if (p) {
00985 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
00986 }
00987
00988 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00989 if (sub->rtp) {
00990 ast_rtp_destroy(sub->rtp);
00991 sub->rtp = NULL;
00992 }
00993
00994 ast_module_unref(ast_module_info->self);
00995
00996 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
00997 p->hidecallerid = 0;
00998 if (p->hascallwaiting && !p->callwaiting) {
00999 if (option_verbose > 2)
01000 ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on %s\n", ast->name);
01001 p->callwaiting = -1;
01002 }
01003 if (has_voicemail(p)) {
01004 if (mgcpdebug) {
01005 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
01006 ast->name, p->name, p->parent->name);
01007 }
01008 transmit_notify_request(sub, "L/vmwi(+)");
01009 } else {
01010 if (mgcpdebug) {
01011 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
01012 ast->name, p->name, p->parent->name);
01013 }
01014 transmit_notify_request(sub, "L/vmwi(-)");
01015 }
01016 }
01017 ast_mutex_unlock(&sub->lock);
01018 return 0;
01019 }
01020
01021 static int mgcp_show_endpoints(int fd, int argc, char *argv[])
01022 {
01023 struct mgcp_gateway *g;
01024 struct mgcp_endpoint *e;
01025 int hasendpoints = 0;
01026
01027 if (argc != 3)
01028 return RESULT_SHOWUSAGE;
01029 ast_mutex_lock(&gatelock);
01030 g = gateways;
01031 while(g) {
01032 e = g->endpoints;
01033 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");
01034 while(e) {
01035
01036 if (strcmp(e->name, g->wcardep) !=0)
01037 ast_cli(fd, " -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
01038 hasendpoints = 1;
01039 e = e->next;
01040 }
01041 if (!hasendpoints) {
01042 ast_cli(fd, " << No Endpoints Defined >> ");
01043 }
01044 g = g->next;
01045 }
01046 ast_mutex_unlock(&gatelock);
01047 return RESULT_SUCCESS;
01048 }
01049
01050 static char show_endpoints_usage[] =
01051 "Usage: mgcp show endpoints\n"
01052 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
01053
01054 static char audit_endpoint_usage[] =
01055 "Usage: mgcp audit endpoint <endpointid>\n"
01056 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
01057 " mgcp debug MUST be on to see the results of this command.\n";
01058
01059 static char debug_usage[] =
01060 "Usage: mgcp set debug\n"
01061 " Enables dumping of MGCP packets for debugging purposes\n";
01062
01063 static char no_debug_usage[] =
01064 "Usage: mgcp set debug off\n"
01065 " Disables dumping of MGCP packets for debugging purposes\n";
01066
01067 static char mgcp_reload_usage[] =
01068 "Usage: mgcp reload\n"
01069 " Reloads MGCP configuration from mgcp.conf\n"
01070 " Deprecated: please use 'reload chan_mgcp.so' instead.\n";
01071
01072 static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
01073 {
01074 struct mgcp_gateway *g;
01075 struct mgcp_endpoint *e;
01076 int found = 0;
01077 char *ename,*gname, *c;
01078
01079 if (!mgcpdebug) {
01080 return RESULT_SHOWUSAGE;
01081 }
01082 if (argc != 4)
01083 return RESULT_SHOWUSAGE;
01084
01085 ename = argv[3];
01086 gname = ename;
01087 while (*gname) {
01088 if (*gname == '@') {
01089 *gname = 0;
01090 gname++;
01091 break;
01092 }
01093 gname++;
01094 }
01095 if (gname[0] == '[')
01096 gname++;
01097 if ((c = strrchr(gname, ']')))
01098 *c = '\0';
01099 ast_mutex_lock(&gatelock);
01100 g = gateways;
01101 while(g) {
01102 if (!strcasecmp(g->name, gname)) {
01103 e = g->endpoints;
01104 while(e) {
01105 if (!strcasecmp(e->name, ename)) {
01106 found = 1;
01107 transmit_audit_endpoint(e);
01108 break;
01109 }
01110 e = e->next;
01111 }
01112 if (found) {
01113 break;
01114 }
01115 }
01116 g = g->next;
01117 }
01118 if (!found) {
01119 ast_cli(fd, " << Could not find endpoint >> ");
01120 }
01121 ast_mutex_unlock(&gatelock);
01122 return RESULT_SUCCESS;
01123 }
01124
01125 static int mgcp_do_debug(int fd, int argc, char *argv[])
01126 {
01127 if (argc != 3)
01128 return RESULT_SHOWUSAGE;
01129 mgcpdebug = 1;
01130 ast_cli(fd, "MGCP Debugging Enabled\n");
01131 return RESULT_SUCCESS;
01132 }
01133
01134 static int mgcp_no_debug(int fd, int argc, char *argv[])
01135 {
01136 if (argc != 4)
01137 return RESULT_SHOWUSAGE;
01138 mgcpdebug = 0;
01139 ast_cli(fd, "MGCP Debugging Disabled\n");
01140 return RESULT_SUCCESS;
01141 }
01142
01143 static struct ast_cli_entry cli_mgcp[] = {
01144 { { "mgcp", "audit", "endpoint", NULL },
01145 mgcp_audit_endpoint, "Audit specified MGCP endpoint",
01146 audit_endpoint_usage },
01147
01148 { { "mgcp", "show", "endpoints", NULL },
01149 mgcp_show_endpoints, "List defined MGCP endpoints",
01150 show_endpoints_usage },
01151
01152 { { "mgcp", "set", "debug", NULL },
01153 mgcp_do_debug, "Enable MGCP debugging",
01154 debug_usage },
01155
01156 { { "mgcp", "set", "debug", "off", NULL },
01157 mgcp_no_debug, "Disable MGCP debugging",
01158 no_debug_usage },
01159
01160 { { "mgcp", "reload", NULL },
01161 mgcp_reload, "Reload MGCP configuration",
01162 mgcp_reload_usage },
01163 };
01164
01165 static int mgcp_answer(struct ast_channel *ast)
01166 {
01167 int res = 0;
01168 struct mgcp_subchannel *sub = ast->tech_pvt;
01169 struct mgcp_endpoint *p = sub->parent;
01170
01171 ast_mutex_lock(&sub->lock);
01172 sub->cxmode = MGCP_CX_SENDRECV;
01173 if (!sub->rtp) {
01174 start_rtp(sub);
01175 } else {
01176 transmit_modify_request(sub);
01177 }
01178
01179 if (option_verbose > 2) {
01180 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n",
01181 ast->name, p->name, p->parent->name, sub->id);
01182 }
01183 if (ast->_state != AST_STATE_UP) {
01184 ast_setstate(ast, AST_STATE_UP);
01185 if (option_debug)
01186 ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
01187 transmit_notify_request(sub, "");
01188 transmit_modify_request(sub);
01189 }
01190 ast_mutex_unlock(&sub->lock);
01191 return res;
01192 }
01193
01194 static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
01195 {
01196
01197 struct ast_frame *f;
01198
01199 f = ast_rtp_read(sub->rtp);
01200
01201 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
01202 return &ast_null_frame;
01203 if (sub->owner) {
01204
01205 if (f->frametype == AST_FRAME_VOICE) {
01206 if (f->subclass != sub->owner->nativeformats) {
01207 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
01208 sub->owner->nativeformats = f->subclass;
01209 ast_set_read_format(sub->owner, sub->owner->readformat);
01210 ast_set_write_format(sub->owner, sub->owner->writeformat);
01211 }
01212
01213 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
01214 #if 0
01215 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
01216 #endif
01217 f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
01218 }
01219 }
01220 }
01221 return f;
01222 }
01223
01224
01225 static struct ast_frame *mgcp_read(struct ast_channel *ast)
01226 {
01227 struct ast_frame *f;
01228 struct mgcp_subchannel *sub = ast->tech_pvt;
01229 ast_mutex_lock(&sub->lock);
01230 f = mgcp_rtp_read(sub);
01231 ast_mutex_unlock(&sub->lock);
01232 return f;
01233 }
01234
01235 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
01236 {
01237 struct mgcp_subchannel *sub = ast->tech_pvt;
01238 int res = 0;
01239 if (frame->frametype != AST_FRAME_VOICE) {
01240 if (frame->frametype == AST_FRAME_IMAGE)
01241 return 0;
01242 else {
01243 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
01244 return 0;
01245 }
01246 } else {
01247 if (!(frame->subclass & ast->nativeformats)) {
01248 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01249 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
01250 return -1;
01251 }
01252 }
01253 if (sub) {
01254 ast_mutex_lock(&sub->lock);
01255 if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
01256 if (sub->rtp) {
01257 res = ast_rtp_write(sub->rtp, frame);
01258 }
01259 }
01260 ast_mutex_unlock(&sub->lock);
01261 }
01262 return res;
01263 }
01264
01265 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
01266 {
01267 struct mgcp_subchannel *sub = newchan->tech_pvt;
01268
01269 ast_mutex_lock(&sub->lock);
01270 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
01271 if (sub->owner != oldchan) {
01272 ast_mutex_unlock(&sub->lock);
01273 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
01274 return -1;
01275 }
01276 sub->owner = newchan;
01277 ast_mutex_unlock(&sub->lock);
01278 return 0;
01279 }
01280
01281 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit)
01282 {
01283 struct mgcp_subchannel *sub = ast->tech_pvt;
01284 struct mgcp_endpoint *p = sub->parent;
01285 int res = 0;
01286
01287 ast_mutex_lock(&sub->lock);
01288 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01289 ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n");
01290 res = -1;
01291 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01292 ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
01293 ast_rtp_senddigit_begin(sub->rtp, digit);
01294 } else {
01295 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01296 }
01297 ast_mutex_unlock(&sub->lock);
01298
01299 return res;
01300 }
01301
01302 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
01303 {
01304 struct mgcp_subchannel *sub = ast->tech_pvt;
01305 struct mgcp_endpoint *p = sub->parent;
01306 int res = 0;
01307 char tmp[4];
01308
01309 ast_mutex_lock(&sub->lock);
01310 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01311 ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n");
01312 res = -1;
01313 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01314 ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n");
01315 tmp[0] = 'D';
01316 tmp[1] = '/';
01317 tmp[2] = digit;
01318 tmp[3] = '\0';
01319 transmit_notify_request(sub, tmp);
01320 ast_rtp_senddigit_end(sub->rtp, digit);
01321 } else {
01322 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01323 }
01324 ast_mutex_unlock(&sub->lock);
01325
01326 return res;
01327 }
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338 static int mgcp_devicestate(void *data)
01339 {
01340 struct mgcp_gateway *g;
01341 struct mgcp_endpoint *e = NULL;
01342 char *tmp, *endpt, *gw;
01343 int ret = AST_DEVICE_INVALID;
01344
01345 endpt = ast_strdupa(data);
01346 if ((tmp = strchr(endpt, '@'))) {
01347 *tmp++ = '\0';
01348 gw = tmp;
01349 } else
01350 goto error;
01351
01352 ast_mutex_lock(&gatelock);
01353 g = gateways;
01354 while (g) {
01355 if (strcasecmp(g->name, gw) == 0) {
01356 e = g->endpoints;
01357 break;
01358 }
01359 g = g->next;
01360 }
01361
01362 if (!e)
01363 goto error;
01364
01365 while (e) {
01366 if (strcasecmp(e->name, endpt) == 0)
01367 break;
01368 e = e->next;
01369 }
01370
01371 if (!e)
01372 goto error;
01373
01374
01375
01376
01377
01378
01379 ret = AST_DEVICE_UNKNOWN;
01380
01381 error:
01382 ast_mutex_unlock(&gatelock);
01383 return ret;
01384 }
01385
01386 static char *control2str(int ind) {
01387 switch (ind) {
01388 case AST_CONTROL_HANGUP:
01389 return "Other end has hungup";
01390 case AST_CONTROL_RING:
01391 return "Local ring";
01392 case AST_CONTROL_RINGING:
01393 return "Remote end is ringing";
01394 case AST_CONTROL_ANSWER:
01395 return "Remote end has answered";
01396 case AST_CONTROL_BUSY:
01397 return "Remote end is busy";
01398 case AST_CONTROL_TAKEOFFHOOK:
01399 return "Make it go off hook";
01400 case AST_CONTROL_OFFHOOK:
01401 return "Line is off hook";
01402 case AST_CONTROL_CONGESTION:
01403 return "Congestion (circuits busy)";
01404 case AST_CONTROL_FLASH:
01405 return "Flash hook";
01406 case AST_CONTROL_WINK:
01407 return "Wink";
01408 case AST_CONTROL_OPTION:
01409 return "Set a low-level option";
01410 case AST_CONTROL_RADIO_KEY:
01411 return "Key Radio";
01412 case AST_CONTROL_RADIO_UNKEY:
01413 return "Un-Key Radio";
01414 }
01415 return "UNKNOWN";
01416 }
01417
01418 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
01419 {
01420 struct mgcp_subchannel *sub = ast->tech_pvt;
01421 int res = 0;
01422
01423 if (mgcpdebug) {
01424 ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n",
01425 ind, control2str(ind), ast->name);
01426 }
01427 ast_mutex_lock(&sub->lock);
01428 switch(ind) {
01429 case AST_CONTROL_RINGING:
01430 #ifdef DLINK_BUGGY_FIRMWARE
01431 transmit_notify_request(sub, "rt");
01432 #else
01433 transmit_notify_request(sub, "G/rt");
01434 #endif
01435 break;
01436 case AST_CONTROL_BUSY:
01437 transmit_notify_request(sub, "L/bz");
01438 break;
01439 case AST_CONTROL_CONGESTION:
01440 transmit_notify_request(sub, "G/cg");
01441 break;
01442 case AST_CONTROL_HOLD:
01443 ast_moh_start(ast, data, NULL);
01444 break;
01445 case AST_CONTROL_UNHOLD:
01446 ast_moh_stop(ast);
01447 break;
01448 case AST_CONTROL_SRCUPDATE:
01449 ast_rtp_new_source(sub->rtp);
01450 break;
01451 case -1:
01452 transmit_notify_request(sub, "");
01453 break;
01454 default:
01455 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01456 res = -1;
01457 }
01458 ast_mutex_unlock(&sub->lock);
01459 return res;
01460 }
01461
01462 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
01463 {
01464 struct ast_channel *tmp;
01465 struct mgcp_endpoint *i = sub->parent;
01466 int fmt;
01467
01468 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01469 if (tmp) {
01470 tmp->tech = &mgcp_tech;
01471 tmp->nativeformats = i->capability;
01472 if (!tmp->nativeformats)
01473 tmp->nativeformats = capability;
01474 fmt = ast_best_codec(tmp->nativeformats);
01475 ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01476 if (sub->rtp)
01477 tmp->fds[0] = ast_rtp_fd(sub->rtp);
01478 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
01479 i->dsp = ast_dsp_new();
01480 ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
01481
01482 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
01483 } else {
01484 i->dsp = NULL;
01485 }
01486 if (state == AST_STATE_RING)
01487 tmp->rings = 1;
01488 tmp->writeformat = fmt;
01489 tmp->rawwriteformat = fmt;
01490 tmp->readformat = fmt;
01491 tmp->rawreadformat = fmt;
01492 tmp->tech_pvt = sub;
01493 if (!ast_strlen_zero(i->language))
01494 ast_string_field_set(tmp, language, i->language);
01495 if (!ast_strlen_zero(i->accountcode))
01496 ast_string_field_set(tmp, accountcode, i->accountcode);
01497 if (i->amaflags)
01498 tmp->amaflags = i->amaflags;
01499 sub->owner = tmp;
01500 ast_module_ref(ast_module_info->self);
01501 tmp->callgroup = i->callgroup;
01502 tmp->pickupgroup = i->pickupgroup;
01503 ast_string_field_set(tmp, call_forward, i->call_forward);
01504 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
01505 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
01506
01507
01508
01509 tmp->cid.cid_ani = ast_strdup(i->cid_num);
01510
01511 if (!i->adsi)
01512 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01513 tmp->priority = 1;
01514 if (sub->rtp)
01515 ast_jb_configure(tmp, &global_jbconf);
01516 if (state != AST_STATE_DOWN) {
01517 if (ast_pbx_start(tmp)) {
01518 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01519 ast_hangup(tmp);
01520 tmp = NULL;
01521 }
01522 }
01523
01524 if (option_verbose > 2) {
01525 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
01526 tmp->name, ast_state2str(state));
01527 }
01528 } else {
01529 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01530 }
01531 return tmp;
01532 }
01533
01534 static char* get_sdp_by_line(char* line, char *name, int nameLen)
01535 {
01536 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01537 char* r = line + nameLen + 1;
01538 while (*r && (*r < 33)) ++r;
01539 return r;
01540 }
01541 return "";
01542 }
01543
01544 static char *get_sdp(struct mgcp_request *req, char *name)
01545 {
01546 int x;
01547 int len = strlen(name);
01548 char *r;
01549
01550 for (x=0; x<req->lines; x++) {
01551 r = get_sdp_by_line(req->line[x], name, len);
01552 if (r[0] != '\0') return r;
01553 }
01554 return "";
01555 }
01556
01557 static void sdpLineNum_iterator_init(int* iterator)
01558 {
01559 *iterator = 0;
01560 }
01561
01562 static char* get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
01563 {
01564 int len = strlen(name);
01565 char *r;
01566 while (*iterator < req->lines) {
01567 r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01568 if (r[0] != '\0') return r;
01569 }
01570 return "";
01571 }
01572
01573 static char *__get_header(struct mgcp_request *req, char *name, int *start)
01574 {
01575 int x;
01576 int len = strlen(name);
01577 char *r;
01578 for (x=*start;x<req->headers;x++) {
01579 if (!strncasecmp(req->header[x], name, len) &&
01580 (req->header[x][len] == ':')) {
01581 r = req->header[x] + len + 1;
01582 while(*r && (*r < 33))
01583 r++;
01584 *start = x+1;
01585 return r;
01586 }
01587 }
01588
01589 return "";
01590 }
01591
01592 static char *get_header(struct mgcp_request *req, char *name)
01593 {
01594 int start = 0;
01595 return __get_header(req, name, &start);
01596 }
01597
01598
01599 static char *get_csv(char *c, int *len, char **next)
01600 {
01601 char *s;
01602
01603 *next = NULL, *len = 0;
01604 if (!c) return NULL;
01605
01606 while (*c && (*c < 33 || *c == ','))
01607 c++;
01608
01609 s = c;
01610 while (*c && (*c >= 33 && *c != ','))
01611 c++, (*len)++;
01612 *next = c;
01613
01614 if (*len == 0)
01615 s = NULL, *next = NULL;
01616
01617 return s;
01618 }
01619
01620 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
01621 {
01622 struct mgcp_endpoint *p = NULL;
01623 struct mgcp_subchannel *sub = NULL;
01624 struct mgcp_gateway *g;
01625 char tmp[256] = "";
01626 char *at = NULL, *c;
01627 int found = 0;
01628 if (name) {
01629 ast_copy_string(tmp, name, sizeof(tmp));
01630 at = strchr(tmp, '@');
01631 if (!at) {
01632 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01633 return NULL;
01634 }
01635 *at++ = '\0';
01636 }
01637 ast_mutex_lock(&gatelock);
01638 if (at && (at[0] == '[')) {
01639 at++;
01640 c = strrchr(at, ']');
01641 if (c)
01642 *c = '\0';
01643 }
01644 g = gateways;
01645 while(g) {
01646 if ((!name || !strcasecmp(g->name, at)) &&
01647 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01648
01649 if (sin && g->dynamic && name) {
01650 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01651 (g->addr.sin_port != sin->sin_port)) {
01652 memcpy(&g->addr, sin, sizeof(g->addr));
01653 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
01654 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01655 if (option_verbose > 2)
01656 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));
01657 }
01658 }
01659
01660 else if (name) {
01661 if (strcasecmp(g->name, at)) {
01662 g = g->next;
01663 continue;
01664 }
01665 }
01666
01667 else if (!name && sin) {
01668 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01669 (g->addr.sin_port != sin->sin_port)) {
01670 g = g->next;
01671 continue;
01672 }
01673 } else {
01674 g = g->next;
01675 continue;
01676 }
01677
01678 p = g->endpoints;
01679 while(p) {
01680 if (option_debug)
01681 ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n",
01682 p->name, g->name);
01683 if (msgid) {
01684 #if 0
01685 sub = p->sub;
01686 do {
01687 if (option_debug)
01688 ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
01689 p->name, g->name, sub->id, msgid);
01690 if (sub->lastout == msgid) {
01691 if (option_debug)
01692 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
01693 sub->id, msgid, sub->lastout);
01694 found = 1;
01695 break;
01696 }
01697 sub = sub->next;
01698 } while (sub != p->sub);
01699 if (found) {
01700 break;
01701 }
01702 #endif
01703
01704 sub = p->sub;
01705 found = 1;
01706
01707 break;
01708 } else if (name && !strcasecmp(p->name, tmp)) {
01709 ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
01710 p->name, g->name, p->sub->id);
01711 sub = p->sub;
01712 found = 1;
01713 break;
01714 }
01715 p = p->next;
01716 }
01717 if (sub && found) {
01718 ast_mutex_lock(&sub->lock);
01719 break;
01720 }
01721 }
01722 g = g->next;
01723 }
01724 ast_mutex_unlock(&gatelock);
01725 if (!sub) {
01726 if (name) {
01727 if (g)
01728 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01729 else
01730 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01731 }
01732 }
01733 return sub;
01734 }
01735
01736 static void parse(struct mgcp_request *req)
01737 {
01738
01739 char *c;
01740 int f = 0;
01741 c = req->data;
01742
01743
01744 req->header[f] = c;
01745 while(*c) {
01746 if (*c == '\n') {
01747
01748 *c = 0;
01749 #if 0
01750 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
01751 #endif
01752 if (ast_strlen_zero(req->header[f])) {
01753
01754 c++;
01755 break;
01756 }
01757 if (f >= MGCP_MAX_HEADERS - 1) {
01758 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01759 } else
01760 f++;
01761 req->header[f] = c + 1;
01762 } else if (*c == '\r') {
01763
01764 *c = 0;
01765 }
01766 c++;
01767 }
01768
01769 if (!ast_strlen_zero(req->header[f]))
01770 f++;
01771 req->headers = f;
01772
01773 f = 0;
01774 req->line[f] = c;
01775 while(*c) {
01776 if (*c == '\n') {
01777
01778 *c = 0;
01779 #if 0
01780 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
01781 #endif
01782 if (f >= MGCP_MAX_LINES - 1) {
01783 ast_log(LOG_WARNING, "Too many SDP lines...\n");
01784 } else
01785 f++;
01786 req->line[f] = c + 1;
01787 } else if (*c == '\r') {
01788
01789 *c = 0;
01790 }
01791 c++;
01792 }
01793
01794 if (!ast_strlen_zero(req->line[f]))
01795 f++;
01796 req->lines = f;
01797
01798 c = req->header[0];
01799 while(*c && *c < 33) c++;
01800
01801 req->verb = c;
01802 while(*c && (*c > 32)) c++;
01803 if (*c) {
01804 *c = '\0';
01805 c++;
01806 while(*c && (*c < 33)) c++;
01807 req->identifier = c;
01808 while(*c && (*c > 32)) c++;
01809 if (*c) {
01810 *c = '\0';
01811 c++;
01812 while(*c && (*c < 33)) c++;
01813 req->endpoint = c;
01814 while(*c && (*c > 32)) c++;
01815 if (*c) {
01816 *c = '\0';
01817 c++;
01818 while(*c && (*c < 33)) c++;
01819 req->version = c;
01820 while(*c && (*c > 32)) c++;
01821 while(*c && (*c < 33)) c++;
01822 while(*c && (*c > 32)) c++;
01823 *c = '\0';
01824 }
01825 }
01826 }
01827
01828 if (mgcpdebug) {
01829 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01830 req->verb, req->identifier, req->endpoint, req->version);
01831 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
01832 }
01833 if (*c)
01834 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01835 }
01836
01837 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
01838 {
01839 char *m;
01840 char *c;
01841 char *a;
01842 char host[258];
01843 int len;
01844 int portno;
01845 int peercapability, peerNonCodecCapability;
01846 struct sockaddr_in sin;
01847 char *codecs;
01848 struct ast_hostent ahp; struct hostent *hp;
01849 int codec, codec_count=0;
01850 int iterator;
01851 struct mgcp_endpoint *p = sub->parent;
01852
01853
01854 m = get_sdp(req, "m");
01855 c = get_sdp(req, "c");
01856 if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
01857 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
01858 return -1;
01859 }
01860 if (sscanf(c, "IN IP4 %256s", host) != 1) {
01861 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
01862 return -1;
01863 }
01864
01865 hp = ast_gethostbyname(host, &ahp);
01866 if (!hp) {
01867 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
01868 return -1;
01869 }
01870 if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
01871 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
01872 return -1;
01873 }
01874 sin.sin_family = AF_INET;
01875 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01876 sin.sin_port = htons(portno);
01877 ast_rtp_set_peer(sub->rtp, &sin);
01878 #if 0
01879 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
01880 #endif
01881
01882 ast_rtp_pt_clear(sub->rtp);
01883 codecs = ast_strdupa(m + len);
01884 while (!ast_strlen_zero(codecs)) {
01885 if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
01886 if (codec_count)
01887 break;
01888 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
01889 return -1;
01890 }
01891 ast_rtp_set_m_type(sub->rtp, codec);
01892 codec_count++;
01893 codecs += len;
01894 }
01895
01896
01897
01898 sdpLineNum_iterator_init(&iterator);
01899 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
01900 char* mimeSubtype = ast_strdupa(a);
01901 if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
01902 continue;
01903
01904 ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0);
01905 }
01906
01907
01908 ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
01909 p->capability = capability & peercapability;
01910 if (mgcpdebug) {
01911 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
01912 capability, peercapability, p->capability);
01913 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
01914 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
01915 }
01916 if (!p->capability) {
01917 ast_log(LOG_WARNING, "No compatible codecs!\n");
01918 return -1;
01919 }
01920 return 0;
01921 }
01922
01923 static int add_header(struct mgcp_request *req, char *var, char *value)
01924 {
01925 if (req->len >= sizeof(req->data) - 4) {
01926 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01927 return -1;
01928 }
01929 if (req->lines) {
01930 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
01931 return -1;
01932 }
01933 req->header[req->headers] = req->data + req->len;
01934 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
01935 req->len += strlen(req->header[req->headers]);
01936 if (req->headers < MGCP_MAX_HEADERS)
01937 req->headers++;
01938 else {
01939 ast_log(LOG_WARNING, "Out of header space\n");
01940 return -1;
01941 }
01942 return 0;
01943 }
01944
01945 static int add_line(struct mgcp_request *req, char *line)
01946 {
01947 if (req->len >= sizeof(req->data) - 4) {
01948 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01949 return -1;
01950 }
01951 if (!req->lines) {
01952
01953 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
01954 req->len += strlen(req->data + req->len);
01955 }
01956 req->line[req->lines] = req->data + req->len;
01957 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
01958 req->len += strlen(req->line[req->lines]);
01959 if (req->lines < MGCP_MAX_LINES)
01960 req->lines++;
01961 else {
01962 ast_log(LOG_WARNING, "Out of line space\n");
01963 return -1;
01964 }
01965 return 0;
01966 }
01967
01968 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
01969 {
01970
01971 if (req->headers || req->len) {
01972 ast_log(LOG_WARNING, "Request already initialized?!?\n");
01973 return -1;
01974 }
01975 req->header[req->headers] = req->data + req->len;
01976 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
01977 req->len += strlen(req->header[req->headers]);
01978 if (req->headers < MGCP_MAX_HEADERS)
01979 req->headers++;
01980 else
01981 ast_log(LOG_WARNING, "Out of header space\n");
01982 return 0;
01983 }
01984
01985 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
01986 {
01987
01988 if (req->headers || req->len) {
01989 ast_log(LOG_WARNING, "Request already initialized?!?\n");
01990 return -1;
01991 }
01992 req->header[req->headers] = req->data + req->len;
01993
01994 if (p->parent->isnamedottedip)
01995 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);
01996 else
01997 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);
01998 req->len += strlen(req->header[req->headers]);
01999 if (req->headers < MGCP_MAX_HEADERS)
02000 req->headers++;
02001 else
02002 ast_log(LOG_WARNING, "Out of header space\n");
02003 return 0;
02004 }
02005
02006
02007 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
02008 {
02009 memset(resp, 0, sizeof(*resp));
02010 init_resp(resp, msg, req, msgrest);
02011 return 0;
02012 }
02013
02014 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
02015 {
02016 memset(req, 0, sizeof(struct mgcp_request));
02017 oseq++;
02018 if (oseq > 999999999)
02019 oseq = 1;
02020 init_req(p, req, verb);
02021 return 0;
02022 }
02023
02024 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
02025 {
02026 struct mgcp_request resp;
02027 struct mgcp_endpoint *p = sub->parent;
02028 struct mgcp_response *mgr;
02029
02030 respprep(&resp, p, msg, req, msgrest);
02031 mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
02032 if (mgr) {
02033
02034 memset(mgr, 0, sizeof(struct mgcp_response));
02035 sscanf(req->identifier, "%d", &mgr->seqno);
02036 time(&mgr->whensent);
02037 mgr->len = resp.len;
02038 memcpy(mgr->buf, resp.data, resp.len);
02039 mgr->buf[resp.len] = '\0';
02040 mgr->next = p->parent->responses;
02041 p->parent->responses = mgr;
02042 }
02043 return send_response(sub, &resp);
02044 }
02045
02046
02047 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
02048 {
02049 int len;
02050 int codec;
02051 char costr[80];
02052 struct sockaddr_in sin;
02053 char v[256];
02054 char s[256];
02055 char o[256];
02056 char c[256];
02057 char t[256];
02058 char m[256] = "";
02059 char a[1024] = "";
02060 int x;
02061 struct sockaddr_in dest;
02062 struct mgcp_endpoint *p = sub->parent;
02063
02064
02065 len = 0;
02066 if (!sub->rtp) {
02067 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
02068 return -1;
02069 }
02070 ast_rtp_get_us(sub->rtp, &sin);
02071 if (rtp) {
02072 ast_rtp_get_peer(rtp, &dest);
02073 } else {
02074 if (sub->tmpdest.sin_addr.s_addr) {
02075 dest.sin_addr = sub->tmpdest.sin_addr;
02076 dest.sin_port = sub->tmpdest.sin_port;
02077
02078 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
02079 } else {
02080 dest.sin_addr = p->parent->ourip;
02081 dest.sin_port = sin.sin_port;
02082 }
02083 }
02084 if (mgcpdebug) {
02085 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
02086 }
02087 snprintf(v, sizeof(v), "v=0\r\n");
02088 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
02089 snprintf(s, sizeof(s), "s=session\r\n");
02090 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
02091 snprintf(t, sizeof(t), "t=0 0\r\n");
02092 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
02093 for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02094 if (p->capability & x) {
02095 if (mgcpdebug) {
02096 ast_verbose("Answering with capability %d\n", x);
02097 }
02098 codec = ast_rtp_lookup_code(sub->rtp, 1, x);
02099 if (codec > -1) {
02100 snprintf(costr, sizeof(costr), " %d", codec);
02101 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02102 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0));
02103 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02104 }
02105 }
02106 }
02107 for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
02108 if (p->nonCodecCapability & x) {
02109 if (mgcpdebug) {
02110 ast_verbose("Answering with non-codec capability %d\n", x);
02111 }
02112 codec = ast_rtp_lookup_code(sub->rtp, 0, x);
02113 if (codec > -1) {
02114 snprintf(costr, sizeof(costr), " %d", codec);
02115 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02116 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0));
02117 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02118 if (x == AST_RTP_DTMF) {
02119
02120
02121 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
02122 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02123 }
02124 }
02125 }
02126 }
02127 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
02128 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
02129 snprintf(costr, sizeof(costr), "%d", len);
02130 add_line(resp, v);
02131 add_line(resp, o);
02132 add_line(resp, s);
02133 add_line(resp, c);
02134 add_line(resp, t);
02135 add_line(resp, m);
02136 add_line(resp, a);
02137 return 0;
02138 }
02139
02140 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
02141 {
02142 struct mgcp_request resp;
02143 char local[256];
02144 char tmp[80];
02145 int x;
02146 int capability;
02147 struct mgcp_endpoint *p = sub->parent;
02148
02149 capability = p->capability;
02150 if (codecs)
02151 capability = codecs;
02152 if (ast_strlen_zero(sub->cxident) && rtp) {
02153
02154
02155 ast_rtp_get_peer(rtp, &sub->tmpdest);
02156 return 0;
02157 }
02158 snprintf(local, sizeof(local), "p:20");
02159 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02160 if (p->capability & x) {
02161 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02162 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02163 }
02164 }
02165 reqprep(&resp, p, "MDCX");
02166 add_header(&resp, "C", sub->callid);
02167 add_header(&resp, "L", local);
02168 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02169
02170 add_header(&resp, "X", sub->txident);
02171 add_header(&resp, "I", sub->cxident);
02172
02173 add_sdp(&resp, sub, rtp);
02174
02175 resp.cmd = MGCP_CMD_MDCX;
02176 resp.trid = oseq;
02177 return send_request(p, sub, &resp, oseq);
02178 }
02179
02180 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
02181 {
02182 struct mgcp_request resp;
02183 char local[256];
02184 char tmp[80];
02185 int x;
02186 struct mgcp_endpoint *p = sub->parent;
02187
02188 snprintf(local, sizeof(local), "p:20");
02189 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02190 if (p->capability & x) {
02191 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02192 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02193 }
02194 }
02195 if (mgcpdebug) {
02196 ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02197 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02198 }
02199 reqprep(&resp, p, "CRCX");
02200 add_header(&resp, "C", sub->callid);
02201 add_header(&resp, "L", local);
02202 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02203
02204 add_header(&resp, "X", sub->txident);
02205
02206 add_sdp(&resp, sub, rtp);
02207
02208 resp.cmd = MGCP_CMD_CRCX;
02209 resp.trid = oseq;
02210 return send_request(p, sub, &resp, oseq);
02211 }
02212
02213 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
02214 {
02215 struct mgcp_request resp;
02216 struct mgcp_endpoint *p = sub->parent;
02217
02218 if (mgcpdebug) {
02219 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02220 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02221 }
02222 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02223 reqprep(&resp, p, "RQNT");
02224 add_header(&resp, "X", p->rqnt_ident);
02225 switch (p->hookstate) {
02226 case MGCP_ONHOOK:
02227 add_header(&resp, "R", "L/hd(N)");
02228 break;
02229 case MGCP_OFFHOOK:
02230 add_header_offhook(sub, &resp);
02231 break;
02232 }
02233 if (!ast_strlen_zero(tone)) {
02234 add_header(&resp, "S", tone);
02235 }
02236
02237 resp.cmd = MGCP_CMD_RQNT;
02238 resp.trid = oseq;
02239 return send_request(p, NULL, &resp, oseq);
02240 }
02241
02242 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
02243 {
02244 struct mgcp_request resp;
02245 char tone2[256];
02246 char *l, *n;
02247 time_t t;
02248 struct tm tm;
02249 struct mgcp_endpoint *p = sub->parent;
02250
02251 time(&t);
02252 ast_localtime(&t, &tm, NULL);
02253 n = callername;
02254 l = callernum;
02255 if (!n)
02256 n = "";
02257 if (!l)
02258 l = "";
02259
02260
02261 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
02262
02263 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
02264 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02265 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02266 reqprep(&resp, p, "RQNT");
02267 add_header(&resp, "X", p->rqnt_ident);
02268 switch (p->hookstate) {
02269 case MGCP_ONHOOK:
02270 add_header(&resp, "R", "L/hd(N)");
02271 break;
02272 case MGCP_OFFHOOK:
02273 add_header_offhook(sub, &resp);
02274 break;
02275 }
02276 if (!ast_strlen_zero(tone2)) {
02277 add_header(&resp, "S", tone2);
02278 }
02279 if (mgcpdebug) {
02280 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02281 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02282 }
02283
02284 resp.cmd = MGCP_CMD_RQNT;
02285 resp.trid = oseq;
02286 return send_request(p, NULL, &resp, oseq);
02287 }
02288
02289 static int transmit_modify_request(struct mgcp_subchannel *sub)
02290 {
02291 struct mgcp_request resp;
02292 struct mgcp_endpoint *p = sub->parent;
02293
02294 if (ast_strlen_zero(sub->cxident)) {
02295
02296
02297 return 0;
02298 }
02299 if (mgcpdebug) {
02300 ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n",
02301 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02302 }
02303 reqprep(&resp, p, "MDCX");
02304 add_header(&resp, "C", sub->callid);
02305 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02306
02307 add_header(&resp, "X", sub->txident);
02308 add_header(&resp, "I", sub->cxident);
02309 switch (sub->parent->hookstate) {
02310 case MGCP_ONHOOK:
02311 add_header(&resp, "R", "L/hd(N)");
02312 break;
02313 case MGCP_OFFHOOK:
02314 add_header_offhook(sub, &resp);
02315 break;
02316 }
02317
02318 resp.cmd = MGCP_CMD_MDCX;
02319 resp.trid = oseq;
02320 return send_request(p, sub, &resp, oseq);
02321 }
02322
02323
02324 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp)
02325 {
02326 struct mgcp_endpoint *p = sub->parent;
02327
02328 if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)))
02329 add_header(resp, "R", "L/hu(N),L/hf(N)");
02330 else
02331 add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
02332 }
02333
02334 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
02335 {
02336 struct mgcp_request resp;
02337 reqprep(&resp, p, "AUEP");
02338
02339
02340 add_header(&resp, "F", "A");
02341
02342 resp.cmd = MGCP_CMD_AUEP;
02343 resp.trid = oseq;
02344 return send_request(p, NULL, &resp, oseq);
02345 }
02346
02347 static int transmit_connection_del(struct mgcp_subchannel *sub)
02348 {
02349 struct mgcp_endpoint *p = sub->parent;
02350 struct mgcp_request resp;
02351
02352 if (mgcpdebug) {
02353 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
02354 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02355 }
02356 reqprep(&resp, p, "DLCX");
02357
02358 if (sub->callid[0])
02359 add_header(&resp, "C", sub->callid);
02360
02361 add_header(&resp, "X", sub->txident);
02362
02363 if (sub->cxident[0])
02364 add_header(&resp, "I", sub->cxident);
02365
02366 resp.cmd = MGCP_CMD_DLCX;
02367 resp.trid = oseq;
02368 return send_request(p, sub, &resp, oseq);
02369 }
02370
02371 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
02372 {
02373 struct mgcp_request resp;
02374
02375 if (mgcpdebug) {
02376 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n",
02377 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02378 }
02379 reqprep(&resp, p, "DLCX");
02380
02381 if (callid && *callid)
02382 add_header(&resp, "C", callid);
02383
02384 if (cxident && *cxident)
02385 add_header(&resp, "I", cxident);
02386
02387 resp.cmd = MGCP_CMD_DLCX;
02388 resp.trid = oseq;
02389 return send_request(p, p->sub, &resp, oseq);
02390 }
02391
02392
02393 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
02394 {
02395 struct mgcp_request *t, *q;
02396
02397 if (p) {
02398 ast_mutex_lock(&p->rqnt_queue_lock);
02399 for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
02400 p->rqnt_queue = NULL;
02401 ast_mutex_unlock(&p->rqnt_queue_lock);
02402
02403 ast_mutex_lock(&p->cmd_queue_lock);
02404 for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
02405 p->cmd_queue = NULL;
02406 ast_mutex_unlock(&p->cmd_queue_lock);
02407
02408 ast_mutex_lock(&p->sub->cx_queue_lock);
02409 for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
02410 p->sub->cx_queue = NULL;
02411 ast_mutex_unlock(&p->sub->cx_queue_lock);
02412
02413 ast_mutex_lock(&p->sub->next->cx_queue_lock);
02414 for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
02415 p->sub->next->cx_queue = NULL;
02416 ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02417 } else if (sub) {
02418 ast_mutex_lock(&sub->cx_queue_lock);
02419 for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
02420 sub->cx_queue = NULL;
02421 ast_mutex_unlock(&sub->cx_queue_lock);
02422 }
02423 }
02424
02425
02426
02427 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02428 struct mgcp_request **queue, ast_mutex_t *l, int ident)
02429 {
02430 struct mgcp_request *prev, *req;
02431
02432 ast_mutex_lock(l);
02433 for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02434 if (req->trid == ident) {
02435
02436 if (!prev)
02437 *queue = req->next;
02438 else
02439 prev->next = req->next;
02440
02441
02442 if (*queue) {
02443 if (mgcpdebug) {
02444 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
02445 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02446 }
02447
02448 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02449 }
02450 break;
02451 }
02452 }
02453 ast_mutex_unlock(l);
02454 return req;
02455 }
02456
02457
02458 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02459 int result, unsigned int ident, struct mgcp_request *resp)
02460 {
02461 char *c;
02462 struct mgcp_request *req;
02463 struct mgcp_gateway *gw = p->parent;
02464
02465 if (result < 200) {
02466
02467 return;
02468 }
02469
02470 if (p->slowsequence)
02471 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02472 else if (sub)
02473 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
02474 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
02475 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02476
02477 if (!req) {
02478 if (option_verbose > 2) {
02479 ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n",
02480 gw->name, ident);
02481 }
02482 return;
02483 }
02484
02485 if (p && (result >= 400) && (result <= 599)) {
02486 switch (result) {
02487 case 401:
02488 p->hookstate = MGCP_OFFHOOK;
02489 break;
02490 case 402:
02491 p->hookstate = MGCP_ONHOOK;
02492 break;
02493 case 406:
02494 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
02495 break;
02496 case 407:
02497 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
02498 break;
02499 }
02500 if (sub) {
02501 if (sub->owner) {
02502 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02503 result, p->name, p->parent->name, sub ? sub->id:-1);
02504 mgcp_queue_hangup(sub);
02505 }
02506 } else {
02507 if (p->sub->next->owner) {
02508 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02509 result, p->name, p->parent->name, sub ? sub->id:-1);
02510 mgcp_queue_hangup(p->sub);
02511 }
02512
02513 if (p->sub->owner) {
02514 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02515 result, p->name, p->parent->name, sub ? sub->id:-1);
02516 mgcp_queue_hangup(p->sub);
02517 }
02518
02519 dump_cmd_queues(p, NULL);
02520 }
02521 }
02522
02523 if (resp) {
02524 if (req->cmd == MGCP_CMD_CRCX) {
02525 if ((c = get_header(resp, "I"))) {
02526 if (!ast_strlen_zero(c) && sub) {
02527
02528 if (sub->owner) {
02529 if (!ast_strlen_zero(sub->cxident)) {
02530 if (strcasecmp(c, sub->cxident)) {
02531 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
02532 }
02533 }
02534 ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
02535 if (sub->tmpdest.sin_addr.s_addr) {
02536 transmit_modify_with_sdp(sub, NULL, 0);
02537 }
02538 } else {
02539
02540
02541
02542
02543 transmit_connection_del(sub);
02544 }
02545 }
02546 }
02547 }
02548
02549 if (req->cmd == MGCP_CMD_AUEP) {
02550
02551 if ((c = get_header(resp, "I"))) {
02552 char *v, *n;
02553 int len;
02554 while ((v = get_csv(c, &len, &n))) {
02555 if (len) {
02556 if (strncasecmp(v, p->sub->cxident, len) &&
02557 strncasecmp(v, p->sub->next->cxident, len)) {
02558
02559 char cxident[80] = "";
02560
02561 if (len > (sizeof(cxident) - 1))
02562 len = sizeof(cxident) - 1;
02563 ast_copy_string(cxident, v, len);
02564 if (option_verbose > 2) {
02565 ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n",
02566 cxident, p->name, gw->name);
02567 }
02568 transmit_connection_del_w_params(p, NULL, cxident);
02569 }
02570 }
02571 c = n;
02572 }
02573 }
02574
02575
02576 if ((c = get_header(resp, "ES"))) {
02577 if (!ast_strlen_zero(c)) {
02578 if (strstr(c, "hu")) {
02579 if (p->hookstate != MGCP_ONHOOK) {
02580
02581 if ((p->sub->owner || p->sub->next->owner ) &&
02582 p->hookstate == MGCP_OFFHOOK)
02583 mgcp_queue_hangup(sub);
02584 p->hookstate = MGCP_ONHOOK;
02585
02586
02587 transmit_notify_request(p->sub, "");
02588
02589
02590 if (option_verbose > 2) {
02591 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
02592 }
02593 }
02594 } else if (strstr(c, "hd")) {
02595 if (p->hookstate != MGCP_OFFHOOK) {
02596 p->hookstate = MGCP_OFFHOOK;
02597
02598
02599 transmit_notify_request(p->sub, "");
02600
02601
02602 if (option_verbose > 2) {
02603 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
02604 }
02605 }
02606 }
02607 }
02608 }
02609 }
02610
02611 if (resp && resp->lines) {
02612
02613 if (sub && sub->owner) {
02614 if (!sub->rtp)
02615 start_rtp(sub);
02616 if (sub->rtp)
02617 process_sdp(sub, resp);
02618 }
02619 }
02620 }
02621
02622 free(req);
02623 }
02624
02625 static void start_rtp(struct mgcp_subchannel *sub)
02626 {
02627 ast_mutex_lock(&sub->lock);
02628
02629 if (sub->rtp) {
02630 ast_rtp_destroy(sub->rtp);
02631 sub->rtp = NULL;
02632 }
02633
02634 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
02635 if (sub->rtp && sub->owner)
02636 sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
02637 if (sub->rtp)
02638 ast_rtp_setnat(sub->rtp, sub->nat);
02639 #if 0
02640 ast_rtp_set_callback(p->rtp, rtpready);
02641 ast_rtp_set_data(p->rtp, p);
02642 #endif
02643
02644 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
02645
02646 transmit_connect_with_sdp(sub, NULL);
02647 ast_mutex_unlock(&sub->lock);
02648 }
02649
02650 static void *mgcp_ss(void *data)
02651 {
02652 struct ast_channel *chan = data;
02653 struct mgcp_subchannel *sub = chan->tech_pvt;
02654 struct mgcp_endpoint *p = sub->parent;
02655
02656 int len = 0;
02657 int timeout = firstdigittimeout;
02658 int res= 0;
02659 int getforward = 0;
02660 int loop_pause = 100;
02661
02662 len = strlen(p->dtmf_buf);
02663
02664 while(len < AST_MAX_EXTENSION-1) {
02665 res = 1;
02666 while (strlen(p->dtmf_buf) == len){
02667 ast_safe_sleep(chan, loop_pause);
02668 timeout -= loop_pause;
02669 if (timeout <= 0){
02670 res = 0;
02671 break;
02672 }
02673 res = 1;
02674 }
02675
02676 timeout = 0;
02677 len = strlen(p->dtmf_buf);
02678
02679 if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) {
02680
02681 ast_indicate(chan, -1);
02682 } else {
02683
02684
02685 transmit_notify_request(sub, "L/dl");
02686 }
02687 if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02688 if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02689 if (getforward) {
02690
02691 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward));
02692 if (option_verbose > 2) {
02693 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
02694 p->call_forward, chan->name);
02695 }
02696
02697 transmit_notify_request(sub, "L/sl");
02698 if (res)
02699 break;
02700 usleep(500000);
02701
02702 ast_indicate(chan, -1);
02703 sleep(1);
02704 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02705
02706 transmit_notify_request(sub, "L/dl");
02707 len = 0;
02708 getforward = 0;
02709 } else {
02710
02711 ast_indicate(chan, -1);
02712 ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten));
02713 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02714 ast_set_callerid(chan,
02715 p->hidecallerid ? "" : p->cid_num,
02716 p->hidecallerid ? "" : p->cid_name,
02717 chan->cid.cid_ani ? NULL : p->cid_num);
02718 ast_setstate(chan, AST_STATE_RING);
02719
02720 if (p->dtmfmode & MGCP_DTMF_HYBRID) {
02721 p->dtmfmode |= MGCP_DTMF_INBAND;
02722 ast_indicate(chan, -1);
02723 }
02724 res = ast_pbx_run(chan);
02725 if (res) {
02726 ast_log(LOG_WARNING, "PBX exited non-zero\n");
02727
02728
02729 transmit_notify_request(sub, "G/cg");
02730 }
02731 return NULL;
02732 }
02733 } else {
02734
02735
02736 timeout = matchdigittimeout;
02737 }
02738 } else if (res == 0) {
02739 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
02740
02741 transmit_notify_request(sub, "G/cg");
02742
02743 ast_hangup(chan);
02744 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02745 return NULL;
02746 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) {
02747 if (option_verbose > 2) {
02748 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
02749 }
02750
02751 p->callwaiting = 0;
02752
02753 transmit_notify_request(sub, "L/sl");
02754 len = 0;
02755 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02756 timeout = firstdigittimeout;
02757 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) {
02758
02759
02760
02761
02762 if (ast_pickup_call(chan)) {
02763 ast_log(LOG_WARNING, "No call pickup possible...\n");
02764
02765 transmit_notify_request(sub, "G/cg");
02766 }
02767 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02768 ast_hangup(chan);
02769 return NULL;
02770 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) {
02771 if (option_verbose > 2) {
02772 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
02773 }
02774
02775 p->hidecallerid = 1;
02776 ast_set_callerid(chan, "", "", NULL);
02777
02778 transmit_notify_request(sub, "L/sl");
02779 len = 0;
02780 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02781 timeout = firstdigittimeout;
02782 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) {
02783 res = 0;
02784 if (!ast_strlen_zero(p->lastcallerid)) {
02785 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
02786 }
02787 if (!res)
02788
02789 transmit_notify_request(sub, "L/sl");
02790 break;
02791 } else if (!strcmp(p->dtmf_buf, "*78")) {
02792
02793 if (option_verbose > 2) {
02794 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
02795 }
02796
02797 transmit_notify_request(sub, "L/sl");
02798 p->dnd = 1;
02799 getforward = 0;
02800 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02801 len = 0;
02802 } else if (!strcmp(p->dtmf_buf, "*79")) {
02803
02804 if (option_verbose > 2) {
02805 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
02806 }
02807
02808 transmit_notify_request(sub, "L/sl");
02809 p->dnd = 0;
02810 getforward = 0;
02811 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02812 len = 0;
02813 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) {
02814
02815 transmit_notify_request(sub, "L/sl");
02816 getforward = 1;
02817 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02818 len = 0;
02819 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) {
02820 if (option_verbose > 2) {
02821 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
02822 }
02823
02824 transmit_notify_request(sub, "L/sl");
02825 memset(p->call_forward, 0, sizeof(p->call_forward));
02826 getforward = 0;
02827 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02828 len = 0;
02829 } else if (!strcmp(p->dtmf_buf, ast_parking_ext()) &&
02830 sub->next->owner && ast_bridged_channel(sub->next->owner)) {
02831
02832
02833 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
02834 if (option_verbose > 2) {
02835 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
02836 }
02837 break;
02838 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) {
02839 if (option_verbose > 2) {
02840 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
02841 }
02842 res = ast_db_put("blacklist", p->lastcallerid, "1");
02843 if (!res) {
02844
02845 transmit_notify_request(sub, "L/sl");
02846 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02847 len = 0;
02848 }
02849 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) {
02850 if (option_verbose > 2) {
02851 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
02852 }
02853
02854 p->hidecallerid = 0;
02855 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
02856
02857 transmit_notify_request(sub, "L/sl");
02858 len = 0;
02859 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02860 timeout = firstdigittimeout;
02861 } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, chan->cid.cid_num) &&
02862 ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
02863 if (option_debug)
02864 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", p->dtmf_buf, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
02865 break;
02866 }
02867 if (!timeout)
02868 timeout = gendigittimeout;
02869 if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf))
02870
02871 ast_indicate(chan, -1);
02872 }
02873 #if 0
02874 for (;;) {
02875 res = ast_waitfordigit(chan, to);
02876 if (!res) {
02877 ast_log(LOG_DEBUG, "Timeout...\n");
02878 break;
02879 }
02880 if (res < 0) {
02881 ast_log(LOG_DEBUG, "Got hangup...\n");
02882 ast_hangup(chan);
02883 break;
02884 }
02885 exten[pos++] = res;
02886 if (!ast_ignore_pattern(chan->context, exten))
02887 ast_indicate(chan, -1);
02888 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
02889 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
02890 to = 3000;
02891 else
02892 to = 8000;
02893 } else
02894 break;
02895 }
02896 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
02897 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1);
02898 if (!p->rtp) {
02899 start_rtp(p);
02900 }
02901 ast_setstate(chan, AST_STATE_RING);
02902 chan->rings = 1;
02903 if (ast_pbx_run(chan)) {
02904 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
02905 } else {
02906 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02907 return NULL;
02908 }
02909 }
02910 #endif
02911 ast_hangup(chan);
02912 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02913 return NULL;
02914 }
02915
02916 static int attempt_transfer(struct mgcp_endpoint *p)
02917 {
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927 if (ast_bridged_channel(p->sub->owner)) {
02928
02929
02930 if (ast_bridged_channel(p->sub->next->owner))
02931 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
02932 if (p->sub->owner->_state == AST_STATE_RINGING) {
02933 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02934 }
02935 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
02936 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02937 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
02938 return -1;
02939 }
02940
02941 unalloc_sub(p->sub->next);
02942 } else if (ast_bridged_channel(p->sub->next->owner)) {
02943 if (p->sub->owner->_state == AST_STATE_RINGING) {
02944 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02945 }
02946 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
02947 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
02948 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02949 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
02950 return -1;
02951 }
02952
02953 if (option_verbose > 2) {
02954 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);
02955 }
02956 p->sub = p->sub->next;
02957 unalloc_sub(p->sub->next);
02958
02959 return 1;
02960 } else {
02961 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
02962 p->sub->owner->name, p->sub->next->owner->name);
02963 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02964 if (p->sub->next->owner) {
02965 p->sub->next->alreadygone = 1;
02966 mgcp_queue_hangup(p->sub->next);
02967 }
02968 }
02969 return 0;
02970 }
02971
02972 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
02973 {
02974 struct mgcp_endpoint *p = sub->parent;
02975 struct ast_channel *c;
02976 pthread_t t;
02977 pthread_attr_t attr;
02978 pthread_attr_init(&attr);
02979 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02980
02981
02982 if (sub->outgoing) {
02983
02984 if (sub->owner) {
02985 if (ast_bridged_channel(sub->owner))
02986 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
02987 sub->cxmode = MGCP_CX_SENDRECV;
02988 if (!sub->rtp) {
02989 start_rtp(sub);
02990 } else {
02991 transmit_modify_request(sub);
02992 }
02993
02994 transmit_notify_request(sub, "");
02995 mgcp_queue_control(sub, AST_CONTROL_ANSWER);
02996 }
02997 } else {
02998
02999
03000 if (!sub->owner) {
03001 if (!sub->rtp) {
03002 start_rtp(sub);
03003 } else {
03004 transmit_modify_request(sub);
03005 }
03006 if (p->immediate) {
03007
03008 #ifdef DLINK_BUGGY_FIRMWARE
03009 transmit_notify_request(sub, "rt");
03010 #else
03011 transmit_notify_request(sub, "G/rt");
03012 #endif
03013 c = mgcp_new(sub, AST_STATE_RING);
03014 if (!c) {
03015 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
03016 transmit_notify_request(sub, "G/cg");
03017 ast_hangup(c);
03018 }
03019 } else {
03020 if (has_voicemail(p)) {
03021 transmit_notify_request(sub, "L/sl");
03022 } else {
03023 transmit_notify_request(sub, "L/dl");
03024 }
03025 c = mgcp_new(sub, AST_STATE_DOWN);
03026 if (c) {
03027 if (ast_pthread_create(&t, &attr, mgcp_ss, c)) {
03028 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
03029 ast_hangup(c);
03030 }
03031 } else {
03032 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
03033 }
03034 }
03035 } else {
03036 if (p->hookstate == MGCP_OFFHOOK) {
03037 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03038 } else {
03039 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03040 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
03041 }
03042 if (ast_bridged_channel(sub->owner))
03043 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03044 sub->cxmode = MGCP_CX_SENDRECV;
03045 if (!sub->rtp) {
03046 start_rtp(sub);
03047 } else {
03048 transmit_modify_request(sub);
03049 }
03050
03051 transmit_notify_request(sub, "");
03052
03053 }
03054 }
03055 pthread_attr_destroy(&attr);
03056 }
03057
03058 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
03059 {
03060 char *ev, *s;
03061 struct ast_frame f = { 0, };
03062 struct mgcp_endpoint *p = sub->parent;
03063 struct mgcp_gateway *g = NULL;
03064 int res;
03065
03066 if (mgcpdebug) {
03067 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
03068 }
03069
03070 if (!strcasecmp(req->verb, "RSIP")) {
03071
03072 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
03073 if (option_verbose > 2)
03074 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
03075 transmit_response(sub, "200", req, "OK");
03076 } else {
03077 dump_queue(p->parent, p);
03078 dump_cmd_queues(p, NULL);
03079
03080 if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) {
03081 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
03082 }
03083
03084 if (!strcmp(p->name, p->parent->wcardep)) {
03085
03086 struct mgcp_endpoint *tmp_ep;
03087
03088 g = p->parent;
03089 tmp_ep = g->endpoints;
03090 while (tmp_ep) {
03091
03092 if (strcmp(tmp_ep->name, g->wcardep) != 0) {
03093 struct mgcp_subchannel *tmp_sub, *first_sub;
03094 if (option_verbose > 2) {
03095 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
03096 }
03097
03098 first_sub = tmp_ep->sub;
03099 tmp_sub = tmp_ep->sub;
03100 while (tmp_sub) {
03101 mgcp_queue_hangup(tmp_sub);
03102 tmp_sub = tmp_sub->next;
03103 if (tmp_sub == first_sub)
03104 break;
03105 }
03106 }
03107 tmp_ep = tmp_ep->next;
03108 }
03109 } else if (sub->owner) {
03110 mgcp_queue_hangup(sub);
03111 }
03112 transmit_response(sub, "200", req, "OK");
03113
03114 if (strcmp(p->name, p->parent->wcardep) != 0) {
03115 transmit_notify_request(sub, "");
03116
03117
03118
03119 transmit_audit_endpoint(p);
03120 }
03121 }
03122 } else if (!strcasecmp(req->verb, "NTFY")) {
03123
03124 transmit_response(sub, "200", req, "OK");
03125
03126 ev = get_header(req, "O");
03127 s = strchr(ev, '/');
03128 if (s) ev = s + 1;
03129 ast_log(LOG_DEBUG, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
03130
03131 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
03132 transmit_notify_request(sub, p->curtone);
03133 }
03134 if (!strcasecmp(ev, "hd")) {
03135 p->hookstate = MGCP_OFFHOOK;
03136 sub->cxmode = MGCP_CX_SENDRECV;
03137 handle_hd_hf(sub, ev);
03138 } else if (!strcasecmp(ev, "hf")) {
03139
03140
03141
03142 if (p->hookstate != MGCP_OFFHOOK) {
03143
03144
03145 return -1;
03146 }
03147
03148 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
03149 return -1;
03150
03151 if (p->callwaiting || p->transfer || p->threewaycalling) {
03152 if (option_verbose > 2) {
03153 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);
03154 }
03155 p->sub = p->sub->next;
03156
03157
03158 if (!sub->next->owner) {
03159
03160 sub->cxmode = MGCP_CX_MUTE;
03161 if (option_verbose > 2) {
03162 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03163 }
03164 transmit_modify_request(sub);
03165 if (sub->owner && ast_bridged_channel(sub->owner))
03166 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03167 sub->next->cxmode = MGCP_CX_RECVONLY;
03168 handle_hd_hf(sub->next, ev);
03169 } else if (sub->owner && sub->next->owner) {
03170
03171 if ((!sub->outgoing) && (!sub->next->outgoing)) {
03172
03173 if (option_verbose > 2) {
03174 ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n",
03175 sub->id, sub->next->id, p->name, p->parent->name);
03176 }
03177 sub->cxmode = MGCP_CX_CONF;
03178 sub->next->cxmode = MGCP_CX_CONF;
03179 if (ast_bridged_channel(sub->next->owner))
03180 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD);
03181 transmit_modify_request(sub);
03182 transmit_modify_request(sub->next);
03183 } else {
03184
03185
03186
03187 if (option_verbose > 2) {
03188 ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
03189 sub->id, sub->next->id, p->name, p->parent->name);
03190 }
03191 sub->cxmode = MGCP_CX_MUTE;
03192 if (option_verbose > 2) {
03193 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03194 }
03195 transmit_modify_request(sub);
03196 if (ast_bridged_channel(sub->owner))
03197 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03198
03199 if (ast_bridged_channel(sub->next->owner))
03200 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD);
03201
03202 handle_hd_hf(sub->next, ev);
03203 }
03204 } else {
03205
03206 if (sub->owner) {
03207 p->sub = sub;
03208 } else if (sub->next->owner) {
03209 p->sub = sub->next;
03210 } else {
03211
03212
03213 return -1;
03214 }
03215 if (ast_bridged_channel(p->sub->owner))
03216 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD);
03217 p->sub->cxmode = MGCP_CX_SENDRECV;
03218 transmit_modify_request(p->sub);
03219 }
03220 } else {
03221 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
03222 p->name, p->parent->name);
03223 }
03224 } else if (!strcasecmp(ev, "hu")) {
03225 p->hookstate = MGCP_ONHOOK;
03226 sub->cxmode = MGCP_CX_RECVONLY;
03227 ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
03228
03229
03230
03231
03232
03233 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
03234
03235
03236 ast_mutex_lock(&p->sub->next->lock);
03237 res = attempt_transfer(p);
03238 if (res < 0) {
03239 if (p->sub->next->owner) {
03240 sub->next->alreadygone = 1;
03241 mgcp_queue_hangup(sub->next);
03242 }
03243 } else if (res) {
03244 ast_log(LOG_WARNING, "Transfer attempt failed\n");
03245 ast_mutex_unlock(&p->sub->next->lock);
03246 return -1;
03247 }
03248 ast_mutex_unlock(&p->sub->next->lock);
03249 } else {
03250
03251
03252 if (sub->owner) {
03253 sub->alreadygone = 1;
03254 mgcp_queue_hangup(sub);
03255 } else {
03256
03257 if (option_verbose > 2) {
03258 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
03259 p->name, p->parent->name, sub->id);
03260 }
03261
03262
03263
03264 transmit_connection_del(sub);
03265 }
03266 }
03267 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
03268 p->hidecallerid = 0;
03269 if (p->hascallwaiting && !p->callwaiting) {
03270 if (option_verbose > 2)
03271 ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
03272 p->callwaiting = -1;
03273 }
03274 if (has_voicemail(p)) {
03275 if (option_verbose > 2) {
03276 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
03277 }
03278 transmit_notify_request(sub, "L/vmwi(+)");
03279 } else {
03280 if (option_verbose > 2) {
03281 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
03282 }
03283 transmit_notify_request(sub, "L/vmwi(-)");
03284 }
03285 }
03286 } else if ((strlen(ev) == 1) &&
03287 (((ev[0] >= '0') && (ev[0] <= '9')) ||
03288 ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
03289 (ev[0] == '*') || (ev[0] == '#'))) {
03290 if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) {
03291 f.frametype = AST_FRAME_DTMF;
03292 f.subclass = ev[0];
03293 f.src = "mgcp";
03294
03295 mgcp_queue_frame(sub, &f);
03296 ast_mutex_lock(&sub->next->lock);
03297 if (sub->next->owner)
03298 mgcp_queue_frame(sub->next, &f);
03299 ast_mutex_unlock(&sub->next->lock);
03300 if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
03301 memset(p->curtone, 0, sizeof(p->curtone));
03302 }
03303 } else {
03304 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
03305 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
03306 }
03307 } else if (!strcasecmp(ev, "T")) {
03308
03309 } else if (!strcasecmp(ev, "ping")) {
03310
03311 } else {
03312 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
03313 }
03314 } else {
03315 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
03316 transmit_response(sub, "510", req, "Unknown verb");
03317 }
03318 return 0;
03319 }
03320
03321 static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
03322 {
03323 int seqno=0;
03324 time_t now;
03325 struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
03326 time(&now);
03327 if (sscanf(req->identifier, "%d", &seqno) != 1)
03328 seqno = 0;
03329 cur = sub->parent->parent->responses;
03330 while(cur) {
03331 next = cur->next;
03332 if (now - cur->whensent > RESPONSE_TIMEOUT) {
03333
03334 if (prev)
03335 prev->next = next;
03336 else
03337 sub->parent->parent->responses = next;
03338 free(cur);
03339 } else {
03340 if (seqno == cur->seqno)
03341 answer = cur;
03342 prev = cur;
03343 }
03344 cur = next;
03345 }
03346 if (answer) {
03347 resend_response(sub, answer);
03348 return 1;
03349 }
03350 return 0;
03351 }
03352
03353 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
03354 {
03355 struct mgcp_request req;
03356 struct sockaddr_in sin;
03357 struct mgcp_subchannel *sub;
03358 int res;
03359 socklen_t len;
03360 int result;
03361 int ident;
03362 len = sizeof(sin);
03363 memset(&req, 0, sizeof(req));
03364 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03365 if (res < 0) {
03366 if (errno != ECONNREFUSED)
03367 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03368 return 1;
03369 }
03370 req.data[res] = '\0';
03371 req.len = res;
03372 if (mgcpdebug) {
03373 ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
03374 }
03375 parse(&req);
03376 if (req.headers < 1) {
03377
03378 return 1;
03379 }
03380 if (ast_strlen_zero(req.identifier)) {
03381 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
03382 return 1;
03383 }
03384
03385 if (sscanf(req.verb, "%d", &result) && sscanf(req.identifier, "%d", &ident)) {
03386
03387 sub = find_subchannel_and_lock(NULL, ident, &sin);
03388 if (sub) {
03389 struct mgcp_gateway *gw = sub->parent->parent;
03390 struct mgcp_message *cur, *prev;
03391
03392 ast_mutex_unlock(&sub->lock);
03393 ast_mutex_lock(&gw->msgs_lock);
03394 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03395 if (cur->seqno == ident) {
03396 ast_log(LOG_DEBUG, "Got response back on transaction %d\n", ident);
03397 if (prev)
03398 prev->next = cur->next;
03399 else
03400 gw->msgs = cur->next;
03401 break;
03402 }
03403 }
03404
03405
03406 if (!gw->msgs) {
03407 AST_SCHED_DEL(sched, gw->retransid);
03408 }
03409
03410 ast_mutex_unlock(&gw->msgs_lock);
03411 if (cur) {
03412 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03413 free(cur);
03414 return 1;
03415 }
03416
03417 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
03418 gw->name, ident);
03419 }
03420 } else {
03421 if (ast_strlen_zero(req.endpoint) ||
03422 ast_strlen_zero(req.version) ||
03423 ast_strlen_zero(req.verb)) {
03424 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03425 return 1;
03426 }
03427
03428 sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03429 if (sub) {
03430
03431 if (!find_and_retrans(sub, &req))
03432
03433 handle_request(sub, &req, &sin);
03434 ast_mutex_unlock(&sub->lock);
03435 }
03436 }
03437 return 1;
03438 }
03439
03440 static int *mgcpsock_read_id = NULL;
03441
03442 static void *do_monitor(void *data)
03443 {
03444 int res;
03445 int reloading;
03446
03447
03448
03449
03450
03451 if (mgcpsock > -1)
03452 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03453
03454
03455
03456
03457 for(;;) {
03458
03459 ast_mutex_lock(&mgcp_reload_lock);
03460 reloading = mgcp_reloading;
03461 mgcp_reloading = 0;
03462 ast_mutex_unlock(&mgcp_reload_lock);
03463 if (reloading) {
03464 if (option_verbose > 0)
03465 ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n");
03466 mgcp_do_reload();
03467
03468 if (mgcpsock > -1)
03469 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03470 }
03471
03472
03473
03474
03475 ast_mutex_lock(&monlock);
03476
03477 ast_mutex_lock(&netlock);
03478
03479 #if 0
03480
03481
03482
03483 lastpass = thispass;
03484 thispass = time(NULL);
03485 g = gateways;
03486 while(g) {
03487 if (thispass != lastpass) {
03488 e = g->endpoints;
03489 while(e) {
03490 if (e->type == TYPE_LINE) {
03491 res = has_voicemail(e);
03492 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
03493 if (res) {
03494 transmit_notify_request(e, "L/vmwi(+)");
03495 } else {
03496 transmit_notify_request(e, "L/vmwi(-)");
03497 }
03498 e->msgstate = res;
03499 e->onhooktime = thispass;
03500 }
03501 }
03502 e = e->next;
03503 }
03504 }
03505 g = g->next;
03506 }
03507 #endif
03508
03509 ast_mutex_unlock(&netlock);
03510
03511 ast_mutex_unlock(&monlock);
03512 pthread_testcancel();
03513
03514 res = ast_sched_wait(sched);
03515
03516 if ((res < 0) || (res > 1000))
03517 res = 1000;
03518 res = ast_io_wait(io, res);
03519 ast_mutex_lock(&monlock);
03520 if (res >= 0)
03521 ast_sched_runq(sched);
03522 ast_mutex_unlock(&monlock);
03523 }
03524
03525 return NULL;
03526 }
03527
03528 static int restart_monitor(void)
03529 {
03530
03531 if (monitor_thread == AST_PTHREADT_STOP)
03532 return 0;
03533 if (ast_mutex_lock(&monlock)) {
03534 ast_log(LOG_WARNING, "Unable to lock monitor\n");
03535 return -1;
03536 }
03537 if (monitor_thread == pthread_self()) {
03538 ast_mutex_unlock(&monlock);
03539 ast_log(LOG_WARNING, "Cannot kill myself\n");
03540 return -1;
03541 }
03542 if (monitor_thread != AST_PTHREADT_NULL) {
03543
03544 pthread_kill(monitor_thread, SIGURG);
03545 } else {
03546
03547 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03548 ast_mutex_unlock(&monlock);
03549 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03550 return -1;
03551 }
03552 }
03553 ast_mutex_unlock(&monlock);
03554 return 0;
03555 }
03556
03557 static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause)
03558 {
03559 int oldformat;
03560 struct mgcp_subchannel *sub;
03561 struct ast_channel *tmpc = NULL;
03562 char tmp[256];
03563 char *dest = data;
03564
03565 oldformat = format;
03566 format &= capability;
03567 if (!format) {
03568 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03569 return NULL;
03570 }
03571 ast_copy_string(tmp, dest, sizeof(tmp));
03572 if (ast_strlen_zero(tmp)) {
03573 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03574 return NULL;
03575 }
03576 sub = find_subchannel_and_lock(tmp, 0, NULL);
03577 if (!sub) {
03578 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03579 *cause = AST_CAUSE_UNREGISTERED;
03580 return NULL;
03581 }
03582
03583 if (option_verbose > 2) {
03584 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
03585 ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
03586 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03587 }
03588
03589 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03590 ((!sub->parent->callwaiting) && (sub->owner)) ||
03591 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03592 if (sub->parent->hookstate == MGCP_ONHOOK) {
03593 if (has_voicemail(sub->parent)) {
03594 transmit_notify_request(sub,"L/vmwi(+)");
03595 } else {
03596 transmit_notify_request(sub,"L/vmwi(-)");
03597 }
03598 }
03599 *cause = AST_CAUSE_BUSY;
03600 ast_mutex_unlock(&sub->lock);
03601 return NULL;
03602 }
03603 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
03604 ast_mutex_unlock(&sub->lock);
03605 if (!tmpc)
03606 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03607 restart_monitor();
03608 return tmpc;
03609 }
03610
03611
03612
03613 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
03614 {
03615 struct mgcp_gateway *gw;
03616 struct mgcp_endpoint *e;
03617 struct mgcp_subchannel *sub;
03618
03619 int i=0, y=0;
03620 int gw_reload = 0;
03621 int ep_reload = 0;
03622 canreinvite = CANREINVITE;
03623
03624
03625 gw = gateways;
03626 while (gw) {
03627 if (!strcasecmp(cat, gw->name)) {
03628
03629 gw->delme = 0;
03630 gw_reload = 1;
03631 break;
03632 }
03633 gw = gw->next;
03634 }
03635
03636 if (!gw)
03637 gw = malloc(sizeof(struct mgcp_gateway));
03638
03639 if (gw) {
03640 if (!gw_reload) {
03641 memset(gw, 0, sizeof(struct mgcp_gateway));
03642 gw->expire = -1;
03643 gw->retransid = -1;
03644 ast_mutex_init(&gw->msgs_lock);
03645 ast_copy_string(gw->name, cat, sizeof(gw->name));
03646
03647 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
03648 gw->isnamedottedip = 1;
03649 }
03650 while(v) {
03651 if (!strcasecmp(v->name, "host")) {
03652 if (!strcasecmp(v->value, "dynamic")) {
03653
03654 gw->dynamic = 1;
03655 memset(&gw->addr.sin_addr, 0, 4);
03656 if (gw->addr.sin_port) {
03657
03658 gw->defaddr.sin_port = gw->addr.sin_port;
03659 gw->addr.sin_port = 0;
03660 }
03661 } else {
03662
03663 AST_SCHED_DEL(sched, gw->expire);
03664 gw->dynamic = 0;
03665 if (ast_get_ip(&gw->addr, v->value)) {
03666 if (!gw_reload) {
03667 ast_mutex_destroy(&gw->msgs_lock);
03668 free(gw);
03669 }
03670 return NULL;
03671 }
03672 }
03673 } else if (!strcasecmp(v->name, "defaultip")) {
03674 if (ast_get_ip(&gw->defaddr, v->value)) {
03675 if (!gw_reload) {
03676 ast_mutex_destroy(&gw->msgs_lock);
03677 free(gw);
03678 }
03679 return NULL;
03680 }
03681 } else if (!strcasecmp(v->name, "permit") ||
03682 !strcasecmp(v->name, "deny")) {
03683 gw->ha = ast_append_ha(v->name, v->value, gw->ha);
03684 } else if (!strcasecmp(v->name, "port")) {
03685 gw->addr.sin_port = htons(atoi(v->value));
03686 } else if (!strcasecmp(v->name, "context")) {
03687 ast_copy_string(context, v->value, sizeof(context));
03688 } else if (!strcasecmp(v->name, "dtmfmode")) {
03689 if (!strcasecmp(v->value, "inband"))
03690 dtmfmode = MGCP_DTMF_INBAND;
03691 else if (!strcasecmp(v->value, "rfc2833"))
03692 dtmfmode = MGCP_DTMF_RFC2833;
03693 else if (!strcasecmp(v->value, "hybrid"))
03694 dtmfmode = MGCP_DTMF_HYBRID;
03695 else if (!strcasecmp(v->value, "none"))
03696 dtmfmode = 0;
03697 else
03698 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
03699 } else if (!strcasecmp(v->name, "nat")) {
03700 nat = ast_true(v->value);
03701 } else if (!strcasecmp(v->name, "callerid")) {
03702 if (!strcasecmp(v->value, "asreceived")) {
03703 cid_num[0] = '\0';
03704 cid_name[0] = '\0';
03705 } else {
03706 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
03707 }
03708 } else if (!strcasecmp(v->name, "language")) {
03709 ast_copy_string(language, v->value, sizeof(language));
03710 } else if (!strcasecmp(v->name, "accountcode")) {
03711 ast_copy_string(accountcode, v->value, sizeof(accountcode));
03712 } else if (!strcasecmp(v->name, "amaflags")) {
03713 y = ast_cdr_amaflags2int(v->value);
03714 if (y < 0) {
03715 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
03716 } else {
03717 amaflags = y;
03718 }
03719 } else if (!strcasecmp(v->name, "musiconhold")) {
03720 ast_copy_string(musicclass, v->value, sizeof(musicclass));
03721 } else if (!strcasecmp(v->name, "callgroup")) {
03722 cur_callergroup = ast_get_group(v->value);
03723 } else if (!strcasecmp(v->name, "pickupgroup")) {
03724 cur_pickupgroup = ast_get_group(v->value);
03725 } else if (!strcasecmp(v->name, "immediate")) {
03726 immediate = ast_true(v->value);
03727 } else if (!strcasecmp(v->name, "cancallforward")) {
03728 cancallforward = ast_true(v->value);
03729 } else if (!strcasecmp(v->name, "singlepath")) {
03730 singlepath = ast_true(v->value);
03731 } else if (!strcasecmp(v->name, "canreinvite")) {
03732 canreinvite = ast_true(v->value);
03733 } else if (!strcasecmp(v->name, "mailbox")) {
03734 ast_copy_string(mailbox, v->value, sizeof(mailbox));
03735 } else if (!strcasecmp(v->name, "adsi")) {
03736 adsi = ast_true(v->value);
03737 } else if (!strcasecmp(v->name, "callreturn")) {
03738 callreturn = ast_true(v->value);
03739 } else if (!strcasecmp(v->name, "callwaiting")) {
03740 callwaiting = ast_true(v->value);
03741 } else if (!strcasecmp(v->name, "slowsequence")) {
03742 slowsequence = ast_true(v->value);
03743 } else if (!strcasecmp(v->name, "transfer")) {
03744 transfer = ast_true(v->value);
03745 } else if (!strcasecmp(v->name, "threewaycalling")) {
03746 threewaycalling = ast_true(v->value);
03747 } else if (!strcasecmp(v->name, "wcardep")) {
03748
03749 e = gw->endpoints;
03750 while (e) {
03751 if (!strcasecmp(v->value, e->name)) {
03752
03753 e->delme = 0;
03754 ep_reload = 1;
03755 break;
03756 }
03757 e = e->next;
03758 }
03759
03760 if (!e) {
03761
03762 e = malloc(sizeof(struct mgcp_endpoint));
03763 ep_reload = 0;
03764 }
03765
03766 if (e) {
03767 if (!ep_reload) {
03768 memset(e, 0, sizeof(struct mgcp_endpoint));
03769 ast_mutex_init(&e->lock);
03770 ast_mutex_init(&e->rqnt_queue_lock);
03771 ast_mutex_init(&e->cmd_queue_lock);
03772 ast_copy_string(e->name, v->value, sizeof(e->name));
03773 e->needaudit = 1;
03774 }
03775 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
03776
03777 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
03778 ast_copy_string(e->context, context, sizeof(e->context));
03779 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
03780 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
03781 ast_copy_string(e->language, language, sizeof(e->language));
03782 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
03783 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
03784 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
03785 e->msgstate = -1;
03786 e->amaflags = amaflags;
03787 e->capability = capability;
03788 e->parent = gw;
03789 e->dtmfmode = dtmfmode;
03790 if (!ep_reload && e->sub && e->sub->rtp)
03791 e->dtmfmode |= MGCP_DTMF_INBAND;
03792 e->adsi = adsi;
03793 e->type = TYPE_LINE;
03794 e->immediate = immediate;
03795 e->callgroup=cur_callergroup;
03796 e->pickupgroup=cur_pickupgroup;
03797 e->callreturn = callreturn;
03798 e->cancallforward = cancallforward;
03799 e->singlepath = singlepath;
03800 e->canreinvite = canreinvite;
03801 e->callwaiting = callwaiting;
03802 e->hascallwaiting = callwaiting;
03803 e->slowsequence = slowsequence;
03804 e->transfer = transfer;
03805 e->threewaycalling = threewaycalling;
03806 e->onhooktime = time(NULL);
03807
03808 e->hookstate = MGCP_ONHOOK;
03809 if (!ep_reload) {
03810
03811 for (i = 0; i < MAX_SUBS; i++) {
03812 sub = malloc(sizeof(struct mgcp_subchannel));
03813 if (sub) {
03814 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03815 memset(sub, 0, sizeof(struct mgcp_subchannel));
03816 ast_mutex_init(&sub->lock);
03817 ast_mutex_init(&sub->cx_queue_lock);
03818 sub->parent = e;
03819 sub->id = i;
03820 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
03821
03822 sub->cxmode = MGCP_CX_INACTIVE;
03823 sub->nat = nat;
03824 sub->next = e->sub;
03825 e->sub = sub;
03826 } else {
03827
03828 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
03829 return NULL;
03830 }
03831 }
03832
03833 sub = e->sub;
03834
03835 while(sub->next){
03836 sub = sub->next;
03837 }
03838
03839 sub->next = e->sub;
03840
03841 e->next = gw->endpoints;
03842 gw->endpoints = e;
03843 }
03844 }
03845 } else if (!strcasecmp(v->name, "trunk") ||
03846 !strcasecmp(v->name, "line")) {
03847
03848
03849 e = gw->endpoints;
03850 while (e) {
03851 if (!strcasecmp(v->value, e->name)) {
03852
03853 e->delme = 0;
03854 ep_reload = 1;
03855 break;
03856 }
03857 e = e->next;
03858 }
03859
03860 if (!e) {
03861 e = malloc(sizeof(struct mgcp_endpoint));
03862 ep_reload = 0;
03863 }
03864
03865 if (e) {
03866 if (!ep_reload) {
03867 memset(e, 0, sizeof(struct mgcp_endpoint));
03868 ast_mutex_init(&e->lock);
03869 ast_mutex_init(&e->rqnt_queue_lock);
03870 ast_mutex_init(&e->cmd_queue_lock);
03871 ast_copy_string(e->name, v->value, sizeof(e->name));
03872 e->needaudit = 1;
03873 }
03874
03875 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
03876 ast_copy_string(e->context, context, sizeof(e->context));
03877 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
03878 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
03879 ast_copy_string(e->language, language, sizeof(e->language));
03880 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
03881 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
03882 if (!ast_strlen_zero(mailbox)) {
03883 ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
03884 }
03885 if (!ep_reload) {
03886
03887 e->msgstate = -1;
03888 e->parent = gw;
03889 }
03890 e->amaflags = amaflags;
03891 e->capability = capability;
03892 e->dtmfmode = dtmfmode;
03893 e->adsi = adsi;
03894 if (!strcasecmp(v->name, "trunk"))
03895 e->type = TYPE_TRUNK;
03896 else
03897 e->type = TYPE_LINE;
03898
03899 e->immediate = immediate;
03900 e->callgroup=cur_callergroup;
03901 e->pickupgroup=cur_pickupgroup;
03902 e->callreturn = callreturn;
03903 e->cancallforward = cancallforward;
03904 e->canreinvite = canreinvite;
03905 e->singlepath = singlepath;
03906 e->callwaiting = callwaiting;
03907 e->hascallwaiting = callwaiting;
03908 e->slowsequence = slowsequence;
03909 e->transfer = transfer;
03910 e->threewaycalling = threewaycalling;
03911 if (!ep_reload) {
03912 e->onhooktime = time(NULL);
03913
03914 e->hookstate = MGCP_ONHOOK;
03915 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
03916 }
03917
03918 for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
03919 if (!ep_reload) {
03920 sub = malloc(sizeof(struct mgcp_subchannel));
03921 } else {
03922 if (!sub)
03923 sub = e->sub;
03924 else
03925 sub = sub->next;
03926 }
03927
03928 if (sub) {
03929 if (!ep_reload) {
03930 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03931 memset(sub, 0, sizeof(struct mgcp_subchannel));
03932 ast_mutex_init(&sub->lock);
03933 ast_mutex_init(&sub->cx_queue_lock);
03934 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
03935 sub->parent = e;
03936 sub->id = i;
03937 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
03938 sub->cxmode = MGCP_CX_INACTIVE;
03939 sub->next = e->sub;
03940 e->sub = sub;
03941 }
03942 sub->nat = nat;
03943 } else {
03944
03945 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
03946 return NULL;
03947 }
03948 }
03949 if (!ep_reload) {
03950
03951 sub = e->sub;
03952
03953 while (sub->next) {
03954 sub = sub->next;
03955 }
03956
03957 sub->next = e->sub;
03958
03959 e->next = gw->endpoints;
03960 gw->endpoints = e;
03961 }
03962 }
03963 } else
03964 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
03965 v = v->next;
03966 }
03967 }
03968 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
03969 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
03970 if (!gw_reload) {
03971 ast_mutex_destroy(&gw->msgs_lock);
03972 free(gw);
03973 }
03974 return NULL;
03975 }
03976 gw->defaddr.sin_family = AF_INET;
03977 gw->addr.sin_family = AF_INET;
03978 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port))
03979 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03980 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
03981 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03982 if (gw->addr.sin_addr.s_addr)
03983 if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip))
03984 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
03985
03986 return (gw_reload ? NULL : gw);
03987 }
03988
03989 static enum ast_rtp_get_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
03990 {
03991 struct mgcp_subchannel *sub = NULL;
03992
03993 if (!(sub = chan->tech_pvt) || !(sub->rtp))
03994 return AST_RTP_GET_FAILED;
03995
03996 *rtp = sub->rtp;
03997
03998 if (sub->parent->canreinvite)
03999 return AST_RTP_TRY_NATIVE;
04000 else
04001 return AST_RTP_TRY_PARTIAL;
04002 }
04003
04004 static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
04005 {
04006
04007 struct mgcp_subchannel *sub;
04008 sub = chan->tech_pvt;
04009 if (sub && !sub->alreadygone) {
04010 transmit_modify_with_sdp(sub, rtp, codecs);
04011 return 0;
04012 }
04013 return -1;
04014 }
04015
04016 static struct ast_rtp_protocol mgcp_rtp = {
04017 .type = "MGCP",
04018 .get_rtp_info = mgcp_get_rtp_peer,
04019 .set_rtp_peer = mgcp_set_rtp_peer,
04020 };
04021
04022 static void destroy_endpoint(struct mgcp_endpoint *e)
04023 {
04024 struct mgcp_subchannel *sub = e->sub->next, *s;
04025 int i;
04026
04027 for (i = 0; i < MAX_SUBS; i++) {
04028 ast_mutex_lock(&sub->lock);
04029 if (!ast_strlen_zero(sub->cxident)) {
04030 transmit_connection_del(sub);
04031 }
04032 if (sub->rtp) {
04033 ast_rtp_destroy(sub->rtp);
04034 sub->rtp = NULL;
04035 }
04036 memset(sub->magic, 0, sizeof(sub->magic));
04037 mgcp_queue_hangup(sub);
04038 dump_cmd_queues(NULL, sub);
04039 ast_mutex_unlock(&sub->lock);
04040 sub = sub->next;
04041 }
04042
04043 if (e->dsp) {
04044 ast_dsp_free(e->dsp);
04045 }
04046
04047 dump_queue(e->parent, e);
04048 dump_cmd_queues(e, NULL);
04049
04050 sub = e->sub;
04051 for (i = 0; (i < MAX_SUBS) && sub; i++) {
04052 s = sub;
04053 sub = sub->next;
04054 ast_mutex_destroy(&s->lock);
04055 ast_mutex_destroy(&s->cx_queue_lock);
04056 free(s);
04057 }
04058 ast_mutex_destroy(&e->lock);
04059 ast_mutex_destroy(&e->rqnt_queue_lock);
04060 ast_mutex_destroy(&e->cmd_queue_lock);
04061 free(e);
04062 }
04063
04064 static void destroy_gateway(struct mgcp_gateway *g)
04065 {
04066 if (g->ha)
04067 ast_free_ha(g->ha);
04068
04069 dump_queue(g, NULL);
04070
04071 free (g);
04072 }
04073
04074 static void prune_gateways(void)
04075 {
04076 struct mgcp_gateway *g, *z, *r;
04077 struct mgcp_endpoint *e, *p, *t;
04078
04079 ast_mutex_lock(&gatelock);
04080
04081
04082 for (z = NULL, g = gateways; g;) {
04083
04084 for (p = NULL, e = g->endpoints; e; ) {
04085 if (e->delme || g->delme) {
04086 t = e;
04087 e = e->next;
04088 if (!p)
04089 g->endpoints = e;
04090 else
04091 p->next = e;
04092 destroy_endpoint(t);
04093 } else {
04094 p = e;
04095 e = e->next;
04096 }
04097 }
04098
04099 if (g->delme) {
04100 r = g;
04101 g = g->next;
04102 if (!z)
04103 gateways = g;
04104 else
04105 z->next = g;
04106
04107 destroy_gateway(r);
04108 } else {
04109 z = g;
04110 g = g->next;
04111 }
04112 }
04113
04114 ast_mutex_unlock(&gatelock);
04115 }
04116
04117 static int reload_config(void)
04118 {
04119 struct ast_config *cfg;
04120 struct ast_variable *v;
04121 struct mgcp_gateway *g;
04122 struct mgcp_endpoint *e;
04123 char *cat;
04124 struct ast_hostent ahp;
04125 struct hostent *hp;
04126 int format;
04127
04128 if (gethostname(ourhost, sizeof(ourhost)-1)) {
04129 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
04130 return 0;
04131 }
04132 cfg = ast_config_load(config);
04133
04134
04135 if (!cfg) {
04136 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
04137 return 0;
04138 }
04139 memset(&bindaddr, 0, sizeof(bindaddr));
04140 dtmfmode = 0;
04141
04142
04143 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
04144
04145 v = ast_variable_browse(cfg, "general");
04146 while (v) {
04147
04148 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
04149 v = v->next;
04150 continue;
04151 }
04152
04153
04154 if (!strcasecmp(v->name, "bindaddr")) {
04155 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04156 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04157 } else {
04158 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04159 }
04160 } else if (!strcasecmp(v->name, "allow")) {
04161 format = ast_getformatbyname(v->value);
04162 if (format < 1)
04163 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04164 else
04165 capability |= format;
04166 } else if (!strcasecmp(v->name, "disallow")) {
04167 format = ast_getformatbyname(v->value);
04168 if (format < 1)
04169 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
04170 else
04171 capability &= ~format;
04172 } else if (!strcasecmp(v->name, "tos")) {
04173 if (sscanf(v->value, "%d", &format) == 1)
04174 tos = format & 0xff;
04175 else if (!strcasecmp(v->value, "lowdelay"))
04176 tos = IPTOS_LOWDELAY;
04177 else if (!strcasecmp(v->value, "throughput"))
04178 tos = IPTOS_THROUGHPUT;
04179 else if (!strcasecmp(v->value, "reliability"))
04180 tos = IPTOS_RELIABILITY;
04181 else if (!strcasecmp(v->value, "mincost"))
04182 tos = IPTOS_MINCOST;
04183 else if (!strcasecmp(v->value, "none"))
04184 tos = 0;
04185 else
04186 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
04187 } else if (!strcasecmp(v->name, "port")) {
04188 if (sscanf(v->value, "%d", &ourport) == 1) {
04189 bindaddr.sin_port = htons(ourport);
04190 } else {
04191 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
04192 }
04193 }
04194 v = v->next;
04195 }
04196
04197
04198 ast_mutex_lock(&gatelock);
04199 g = gateways;
04200 while (g) {
04201 g->delme = 1;
04202 e = g->endpoints;
04203 while (e) {
04204 e->delme = 1;
04205 e = e->next;
04206 }
04207 g = g->next;
04208 }
04209 ast_mutex_unlock(&gatelock);
04210
04211 cat = ast_category_browse(cfg, NULL);
04212 while(cat) {
04213 if (strcasecmp(cat, "general")) {
04214 ast_mutex_lock(&gatelock);
04215 g = build_gateway(cat, ast_variable_browse(cfg, cat));
04216 if (g) {
04217 if (option_verbose > 2) {
04218 ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
04219 }
04220 g->next = gateways;
04221 gateways = g;
04222 }
04223 ast_mutex_unlock(&gatelock);
04224
04225
04226 if (monitor_thread == pthread_self()) {
04227 if (sched) ast_sched_runq(sched);
04228 if (io) ast_io_wait(io, 10);
04229 }
04230 }
04231 cat = ast_category_browse(cfg, cat);
04232 }
04233
04234
04235 prune_gateways();
04236
04237 if (ntohl(bindaddr.sin_addr.s_addr)) {
04238 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
04239 } else {
04240 hp = ast_gethostbyname(ourhost, &ahp);
04241 if (!hp) {
04242 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
04243 ast_config_destroy(cfg);
04244 return 0;
04245 }
04246 memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04247 }
04248 if (!ntohs(bindaddr.sin_port))
04249 bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
04250 bindaddr.sin_family = AF_INET;
04251 ast_mutex_lock(&netlock);
04252 if (mgcpsock > -1)
04253 close(mgcpsock);
04254
04255 if (mgcpsock_read_id != NULL)
04256 ast_io_remove(io, mgcpsock_read_id);
04257 mgcpsock_read_id = NULL;
04258
04259 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
04260 if (mgcpsock < 0) {
04261 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
04262 } else {
04263 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04264 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04265 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04266 strerror(errno));
04267 close(mgcpsock);
04268 mgcpsock = -1;
04269 } else {
04270 if (option_verbose > 1) {
04271 ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n",
04272 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04273 ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
04274 }
04275 if (setsockopt(mgcpsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))
04276 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
04277 }
04278 }
04279 ast_mutex_unlock(&netlock);
04280 ast_config_destroy(cfg);
04281
04282
04283 g = gateways;
04284 while (g) {
04285 e = g->endpoints;
04286 while (e && e->needaudit) {
04287 e->needaudit = 0;
04288 transmit_audit_endpoint(e);
04289 ast_verbose(VERBOSE_PREFIX_3 "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
04290 e = e->next;
04291 }
04292 g = g->next;
04293 }
04294
04295 return 0;
04296 }
04297
04298
04299 static int load_module(void)
04300 {
04301 if (!(sched = sched_context_create())) {
04302 ast_log(LOG_WARNING, "Unable to create schedule context\n");
04303 return AST_MODULE_LOAD_FAILURE;
04304 }
04305
04306 if (!(io = io_context_create())) {
04307 ast_log(LOG_WARNING, "Unable to create I/O context\n");
04308 sched_context_destroy(sched);
04309 return AST_MODULE_LOAD_FAILURE;
04310 }
04311
04312 if (reload_config())
04313 return AST_MODULE_LOAD_DECLINE;
04314
04315
04316 if (ast_channel_register(&mgcp_tech)) {
04317 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
04318 io_context_destroy(io);
04319 sched_context_destroy(sched);
04320 return AST_MODULE_LOAD_FAILURE;
04321 }
04322
04323 ast_rtp_proto_register(&mgcp_rtp);
04324 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04325
04326
04327 restart_monitor();
04328
04329 return AST_MODULE_LOAD_SUCCESS;
04330 }
04331
04332
04333 static int mgcp_do_reload(void)
04334 {
04335 reload_config();
04336 return 0;
04337 }
04338
04339 static int mgcp_reload(int fd, int argc, char *argv[])
04340 {
04341 static int deprecated = 0;
04342 if (!deprecated && argc > 0) {
04343 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n");
04344 deprecated = 1;
04345 }
04346
04347 ast_mutex_lock(&mgcp_reload_lock);
04348 if (mgcp_reloading) {
04349 ast_verbose("Previous mgcp reload not yet done\n");
04350 } else
04351 mgcp_reloading = 1;
04352 ast_mutex_unlock(&mgcp_reload_lock);
04353 restart_monitor();
04354 return 0;
04355 }
04356
04357 static int reload(void)
04358 {
04359 mgcp_reload(0, 0, NULL);
04360 return 0;
04361 }
04362
04363 static int unload_module(void)
04364 {
04365 struct mgcp_endpoint *e;
04366 struct mgcp_gateway *g;
04367
04368
04369 if (ast_mutex_trylock(&mgcp_reload_lock)) {
04370 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n");
04371 return -1;
04372 } else {
04373 mgcp_reloading = 1;
04374 ast_mutex_unlock(&mgcp_reload_lock);
04375 }
04376
04377
04378 ast_channel_unregister(&mgcp_tech);
04379
04380
04381 if (!ast_mutex_lock(&monlock)) {
04382 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04383 pthread_cancel(monitor_thread);
04384 pthread_kill(monitor_thread, SIGURG);
04385 pthread_join(monitor_thread, NULL);
04386 }
04387 monitor_thread = AST_PTHREADT_STOP;
04388 ast_mutex_unlock(&monlock);
04389 } else {
04390 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04391
04392 ast_channel_register(&mgcp_tech);
04393 mgcp_reloading = 0;
04394 mgcp_reload(0, 0, NULL);
04395 return -1;
04396 }
04397
04398 if (!ast_mutex_lock(&gatelock)) {
04399 for (g = gateways; g; g = g->next) {
04400 g->delme = 1;
04401 for (e = g->endpoints; e; e = e->next)
04402 e->delme = 1;
04403 }
04404
04405 prune_gateways();
04406 ast_mutex_unlock(&gatelock);
04407 } else {
04408 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
04409
04410 ast_channel_register(&mgcp_tech);
04411
04412 monitor_thread = AST_PTHREADT_NULL;
04413 mgcp_reloading = 0;
04414 mgcp_reload(0, 0, NULL);
04415 return -1;
04416 }
04417
04418 close(mgcpsock);
04419 ast_rtp_proto_unregister(&mgcp_rtp);
04420 ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04421 sched_context_destroy(sched);
04422
04423 return 0;
04424 }
04425
04426 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Media Gateway Control Protocol (MGCP)",
04427 .load = load_module,
04428 .unload = unload_module,
04429 .reload = reload,
04430 );