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: 211596 $")
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 DEADLOCK_AVOIDANCE(&sub->lock);
00578 }
00579 } else
00580 break;
00581 }
00582 }
00583
00584 static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
00585 {
00586 for(;;) {
00587 if (sub->owner) {
00588 if (!ast_mutex_trylock(&sub->owner->lock)) {
00589 ast_queue_hangup(sub->owner);
00590 ast_mutex_unlock(&sub->owner->lock);
00591 break;
00592 } else {
00593 DEADLOCK_AVOIDANCE(&sub->lock);
00594 }
00595 } else
00596 break;
00597 }
00598 }
00599
00600 static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
00601 {
00602 struct ast_frame f = { AST_FRAME_CONTROL, };
00603 f.subclass = control;
00604 return mgcp_queue_frame(sub, &f);
00605 }
00606
00607 static int retrans_pkt(const void *data)
00608 {
00609 struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
00610 struct mgcp_message *cur, *exq = NULL, *w, *prev;
00611 int res = 0;
00612
00613
00614 ast_mutex_lock(&gw->msgs_lock);
00615
00616 prev = NULL, cur = gw->msgs;
00617 while (cur) {
00618 if (cur->retrans < MAX_RETRANS) {
00619 cur->retrans++;
00620 if (mgcpdebug) {
00621 ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
00622 cur->retrans, cur->seqno, gw->name);
00623 }
00624 __mgcp_xmit(gw, cur->buf, cur->len);
00625
00626 prev = cur;
00627 cur = cur->next;
00628 } else {
00629 if (prev)
00630 prev->next = cur->next;
00631 else
00632 gw->msgs = cur->next;
00633
00634 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
00635 cur->seqno, gw->name);
00636
00637 w = cur;
00638 cur = cur->next;
00639
00640 if (exq) {
00641 w->next = exq;
00642 } else {
00643 w->next = NULL;
00644 }
00645 exq = w;
00646 }
00647 }
00648
00649 if (!gw->msgs) {
00650 gw->retransid = -1;
00651 res = 0;
00652 } else {
00653 res = 1;
00654 }
00655 ast_mutex_unlock(&gw->msgs_lock);
00656
00657 while (exq) {
00658 cur = exq;
00659
00660 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
00661 exq = exq->next;
00662 free(cur);
00663 }
00664
00665 return res;
00666 }
00667
00668
00669 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
00670 char *data, int len, unsigned int seqno)
00671 {
00672 struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
00673 struct mgcp_message *cur;
00674 struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
00675 struct timeval tv;
00676
00677 if (!msg) {
00678 return -1;
00679 }
00680 if (!gw) {
00681 return -1;
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691 msg->owner_sub = sub;
00692 msg->owner_ep = p;
00693 msg->seqno = seqno;
00694 msg->next = NULL;
00695 msg->len = len;
00696 msg->retrans = 0;
00697 memcpy(msg->buf, data, msg->len);
00698
00699 ast_mutex_lock(&gw->msgs_lock);
00700 cur = gw->msgs;
00701 if (cur) {
00702 while(cur->next)
00703 cur = cur->next;
00704 cur->next = msg;
00705 } else {
00706 gw->msgs = msg;
00707 }
00708
00709 if (gettimeofday(&tv, NULL) < 0) {
00710
00711 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
00712 } else {
00713 msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
00714
00715 if (gw->retransid == -1)
00716 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
00717 }
00718 ast_mutex_unlock(&gw->msgs_lock);
00719
00720
00721
00722
00723
00724
00725 __mgcp_xmit(gw, msg->buf, msg->len);
00726
00727
00728
00729
00730
00731 return 0;
00732 }
00733
00734
00735 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
00736 struct mgcp_request *req, unsigned int seqno)
00737 {
00738 int res = 0;
00739 struct mgcp_request **queue, *q, *r, *t;
00740 ast_mutex_t *l;
00741
00742 ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);
00743 if (p->slowsequence) {
00744 queue = &p->cmd_queue;
00745 l = &p->cmd_queue_lock;
00746 ast_mutex_lock(l);
00747 } else {
00748 switch (req->cmd) {
00749 case MGCP_CMD_DLCX:
00750 queue = &sub->cx_queue;
00751 l = &sub->cx_queue_lock;
00752 ast_mutex_lock(l);
00753 q = sub->cx_queue;
00754
00755 while (q) {
00756 r = q->next;
00757 free(q);
00758 q = r;
00759 }
00760 *queue = NULL;
00761 break;
00762
00763 case MGCP_CMD_CRCX:
00764 case MGCP_CMD_MDCX:
00765 queue = &sub->cx_queue;
00766 l = &sub->cx_queue_lock;
00767 ast_mutex_lock(l);
00768 break;
00769
00770 case MGCP_CMD_RQNT:
00771 queue = &p->rqnt_queue;
00772 l = &p->rqnt_queue_lock;
00773 ast_mutex_lock(l);
00774 break;
00775
00776 default:
00777 queue = &p->cmd_queue;
00778 l = &p->cmd_queue_lock;
00779 ast_mutex_lock(l);
00780 break;
00781 }
00782 }
00783
00784 r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
00785 if (!r) {
00786 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
00787 ast_mutex_unlock(l);
00788 return -1;
00789 }
00790 memcpy(r, req, sizeof(struct mgcp_request));
00791
00792 if (!(*queue)) {
00793 if (mgcpdebug) {
00794 ast_verbose("Posting Request:\n%s to %s:%d\n", req->data,
00795 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00796 }
00797
00798 res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
00799 } else {
00800 if (mgcpdebug) {
00801 ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data,
00802 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00803 }
00804 }
00805
00806
00807 for (t = *queue; t && t->next; t = t->next);
00808
00809 r->next = NULL;
00810 if (t)
00811 t->next = r;
00812 else
00813 *queue = r;
00814
00815 ast_mutex_unlock(l);
00816
00817 return res;
00818 }
00819
00820 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
00821 {
00822 int res;
00823 struct mgcp_endpoint *p;
00824 struct mgcp_subchannel *sub;
00825 char tone[50] = "";
00826 const char *distinctive_ring = NULL;
00827 struct varshead *headp;
00828 struct ast_var_t *current;
00829
00830 if (mgcpdebug) {
00831 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);
00832 }
00833 sub = ast->tech_pvt;
00834 p = sub->parent;
00835 headp = &ast->varshead;
00836 AST_LIST_TRAVERSE(headp,current,entries) {
00837
00838 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {
00839 distinctive_ring = ast_var_value(current);
00840 }
00841 }
00842
00843 ast_mutex_lock(&sub->lock);
00844 switch (p->hookstate) {
00845 case MGCP_OFFHOOK:
00846 if (!ast_strlen_zero(distinctive_ring)) {
00847 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
00848 if (mgcpdebug) {
00849 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive callwait %s\n", tone);
00850 }
00851 } else {
00852 snprintf(tone, sizeof(tone), "L/wt");
00853 if (mgcpdebug) {
00854 ast_verbose(VERBOSE_PREFIX_3 "MGCP normal callwait %s\n", tone);
00855 }
00856 }
00857 break;
00858 case MGCP_ONHOOK:
00859 default:
00860 if (!ast_strlen_zero(distinctive_ring)) {
00861 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
00862 if (mgcpdebug) {
00863 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive ring %s\n", tone);
00864 }
00865 } else {
00866 snprintf(tone, sizeof(tone), "L/rg");
00867 if (mgcpdebug) {
00868 ast_verbose(VERBOSE_PREFIX_3 "MGCP default ring\n");
00869 }
00870 }
00871 break;
00872 }
00873
00874 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00875 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
00876 ast_mutex_unlock(&sub->lock);
00877 return -1;
00878 }
00879
00880 res = 0;
00881 sub->outgoing = 1;
00882 sub->cxmode = MGCP_CX_RECVONLY;
00883 if (p->type == TYPE_LINE) {
00884 if (!sub->rtp) {
00885 start_rtp(sub);
00886 } else {
00887 transmit_modify_request(sub);
00888 }
00889
00890 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00891
00892 sub->next->cxmode = MGCP_CX_RECVONLY;
00893 transmit_modify_request(sub->next);
00894 }
00895
00896 transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
00897 ast_setstate(ast, AST_STATE_RINGING);
00898
00899 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00900
00901 sub->next->cxmode = MGCP_CX_SENDRECV;
00902 transmit_modify_request(sub->next);
00903 }
00904 } else {
00905 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
00906 res = -1;
00907 }
00908 ast_mutex_unlock(&sub->lock);
00909 ast_queue_control(ast, AST_CONTROL_RINGING);
00910 return res;
00911 }
00912
00913 static int mgcp_hangup(struct ast_channel *ast)
00914 {
00915 struct mgcp_subchannel *sub = ast->tech_pvt;
00916 struct mgcp_endpoint *p = sub->parent;
00917
00918 if (option_debug) {
00919 ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
00920 }
00921 if (!ast->tech_pvt) {
00922 ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
00923 return 0;
00924 }
00925 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
00926 ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
00927 return 0;
00928 }
00929 ast_mutex_lock(&sub->lock);
00930 if (mgcpdebug) {
00931 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
00932 }
00933
00934 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
00935
00936 if (!sub->next->owner) {
00937 if (p->dtmfmode & MGCP_DTMF_HYBRID)
00938 p->dtmfmode &= ~MGCP_DTMF_INBAND;
00939 if (mgcpdebug) {
00940 ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
00941 }
00942 ast_dsp_free(p->dsp);
00943 p->dsp = NULL;
00944 }
00945 }
00946
00947 sub->owner = NULL;
00948 if (!ast_strlen_zero(sub->cxident)) {
00949 transmit_connection_del(sub);
00950 }
00951 sub->cxident[0] = '\0';
00952 if ((sub == p->sub) && sub->next->owner) {
00953 if (p->hookstate == MGCP_OFFHOOK) {
00954 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00955 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);
00956 }
00957 } else {
00958
00959 p->sub = sub->next;
00960 p->sub->cxmode = MGCP_CX_RECVONLY;
00961 transmit_modify_request(p->sub);
00962 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00963 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);
00964 }
00965 }
00966
00967 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
00968 transmit_notify_request(sub, "L/v");
00969 } else if (p->hookstate == MGCP_OFFHOOK) {
00970 transmit_notify_request(sub, "L/ro");
00971 } else {
00972 transmit_notify_request(sub, "");
00973 }
00974
00975 ast->tech_pvt = NULL;
00976 sub->alreadygone = 0;
00977 sub->outgoing = 0;
00978 sub->cxmode = MGCP_CX_INACTIVE;
00979 sub->callid[0] = '\0';
00980 if (p) {
00981 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
00982 }
00983
00984 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00985 if (sub->rtp) {
00986 ast_rtp_destroy(sub->rtp);
00987 sub->rtp = NULL;
00988 }
00989
00990 ast_module_unref(ast_module_info->self);
00991
00992 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
00993 p->hidecallerid = 0;
00994 if (p->hascallwaiting && !p->callwaiting) {
00995 if (option_verbose > 2)
00996 ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on %s\n", ast->name);
00997 p->callwaiting = -1;
00998 }
00999 if (has_voicemail(p)) {
01000 if (mgcpdebug) {
01001 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
01002 ast->name, p->name, p->parent->name);
01003 }
01004 transmit_notify_request(sub, "L/vmwi(+)");
01005 } else {
01006 if (mgcpdebug) {
01007 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
01008 ast->name, p->name, p->parent->name);
01009 }
01010 transmit_notify_request(sub, "L/vmwi(-)");
01011 }
01012 }
01013 ast_mutex_unlock(&sub->lock);
01014 return 0;
01015 }
01016
01017 static int mgcp_show_endpoints(int fd, int argc, char *argv[])
01018 {
01019 struct mgcp_gateway *g;
01020 struct mgcp_endpoint *e;
01021 int hasendpoints = 0;
01022
01023 if (argc != 3)
01024 return RESULT_SHOWUSAGE;
01025 ast_mutex_lock(&gatelock);
01026 g = gateways;
01027 while(g) {
01028 e = g->endpoints;
01029 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");
01030 while(e) {
01031
01032 if (strcmp(e->name, g->wcardep) !=0)
01033 ast_cli(fd, " -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
01034 hasendpoints = 1;
01035 e = e->next;
01036 }
01037 if (!hasendpoints) {
01038 ast_cli(fd, " << No Endpoints Defined >> ");
01039 }
01040 g = g->next;
01041 }
01042 ast_mutex_unlock(&gatelock);
01043 return RESULT_SUCCESS;
01044 }
01045
01046 static char show_endpoints_usage[] =
01047 "Usage: mgcp show endpoints\n"
01048 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
01049
01050 static char audit_endpoint_usage[] =
01051 "Usage: mgcp audit endpoint <endpointid>\n"
01052 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
01053 " mgcp debug MUST be on to see the results of this command.\n";
01054
01055 static char debug_usage[] =
01056 "Usage: mgcp set debug\n"
01057 " Enables dumping of MGCP packets for debugging purposes\n";
01058
01059 static char no_debug_usage[] =
01060 "Usage: mgcp set debug off\n"
01061 " Disables dumping of MGCP packets for debugging purposes\n";
01062
01063 static char mgcp_reload_usage[] =
01064 "Usage: mgcp reload\n"
01065 " Reloads MGCP configuration from mgcp.conf\n"
01066 " Deprecated: please use 'reload chan_mgcp.so' instead.\n";
01067
01068 static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
01069 {
01070 struct mgcp_gateway *g;
01071 struct mgcp_endpoint *e;
01072 int found = 0;
01073 char *ename,*gname, *c;
01074
01075 if (!mgcpdebug) {
01076 return RESULT_SHOWUSAGE;
01077 }
01078 if (argc != 4)
01079 return RESULT_SHOWUSAGE;
01080
01081 ename = argv[3];
01082 gname = ename;
01083 while (*gname) {
01084 if (*gname == '@') {
01085 *gname = 0;
01086 gname++;
01087 break;
01088 }
01089 gname++;
01090 }
01091 if (gname[0] == '[')
01092 gname++;
01093 if ((c = strrchr(gname, ']')))
01094 *c = '\0';
01095 ast_mutex_lock(&gatelock);
01096 g = gateways;
01097 while(g) {
01098 if (!strcasecmp(g->name, gname)) {
01099 e = g->endpoints;
01100 while(e) {
01101 if (!strcasecmp(e->name, ename)) {
01102 found = 1;
01103 transmit_audit_endpoint(e);
01104 break;
01105 }
01106 e = e->next;
01107 }
01108 if (found) {
01109 break;
01110 }
01111 }
01112 g = g->next;
01113 }
01114 if (!found) {
01115 ast_cli(fd, " << Could not find endpoint >> ");
01116 }
01117 ast_mutex_unlock(&gatelock);
01118 return RESULT_SUCCESS;
01119 }
01120
01121 static int mgcp_do_debug(int fd, int argc, char *argv[])
01122 {
01123 if (argc != 3)
01124 return RESULT_SHOWUSAGE;
01125 mgcpdebug = 1;
01126 ast_cli(fd, "MGCP Debugging Enabled\n");
01127 return RESULT_SUCCESS;
01128 }
01129
01130 static int mgcp_no_debug(int fd, int argc, char *argv[])
01131 {
01132 if (argc != 4)
01133 return RESULT_SHOWUSAGE;
01134 mgcpdebug = 0;
01135 ast_cli(fd, "MGCP Debugging Disabled\n");
01136 return RESULT_SUCCESS;
01137 }
01138
01139 static struct ast_cli_entry cli_mgcp[] = {
01140 { { "mgcp", "audit", "endpoint", NULL },
01141 mgcp_audit_endpoint, "Audit specified MGCP endpoint",
01142 audit_endpoint_usage },
01143
01144 { { "mgcp", "show", "endpoints", NULL },
01145 mgcp_show_endpoints, "List defined MGCP endpoints",
01146 show_endpoints_usage },
01147
01148 { { "mgcp", "set", "debug", NULL },
01149 mgcp_do_debug, "Enable MGCP debugging",
01150 debug_usage },
01151
01152 { { "mgcp", "set", "debug", "off", NULL },
01153 mgcp_no_debug, "Disable MGCP debugging",
01154 no_debug_usage },
01155
01156 { { "mgcp", "reload", NULL },
01157 mgcp_reload, "Reload MGCP configuration",
01158 mgcp_reload_usage },
01159 };
01160
01161 static int mgcp_answer(struct ast_channel *ast)
01162 {
01163 int res = 0;
01164 struct mgcp_subchannel *sub = ast->tech_pvt;
01165 struct mgcp_endpoint *p = sub->parent;
01166
01167 ast_mutex_lock(&sub->lock);
01168 sub->cxmode = MGCP_CX_SENDRECV;
01169 if (!sub->rtp) {
01170 start_rtp(sub);
01171 } else {
01172 transmit_modify_request(sub);
01173 }
01174
01175 if (option_verbose > 2) {
01176 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n",
01177 ast->name, p->name, p->parent->name, sub->id);
01178 }
01179 if (ast->_state != AST_STATE_UP) {
01180 ast_setstate(ast, AST_STATE_UP);
01181 if (option_debug)
01182 ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
01183 transmit_notify_request(sub, "");
01184 transmit_modify_request(sub);
01185 }
01186 ast_mutex_unlock(&sub->lock);
01187 return res;
01188 }
01189
01190 static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
01191 {
01192
01193 struct ast_frame *f;
01194
01195 f = ast_rtp_read(sub->rtp);
01196
01197 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
01198 return &ast_null_frame;
01199 if (sub->owner) {
01200
01201 if (f->frametype == AST_FRAME_VOICE) {
01202 if (f->subclass != sub->owner->nativeformats) {
01203 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
01204 sub->owner->nativeformats = f->subclass;
01205 ast_set_read_format(sub->owner, sub->owner->readformat);
01206 ast_set_write_format(sub->owner, sub->owner->writeformat);
01207 }
01208
01209 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
01210 #if 0
01211 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
01212 #endif
01213 f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
01214 }
01215 }
01216 }
01217 return f;
01218 }
01219
01220
01221 static struct ast_frame *mgcp_read(struct ast_channel *ast)
01222 {
01223 struct ast_frame *f;
01224 struct mgcp_subchannel *sub = ast->tech_pvt;
01225 ast_mutex_lock(&sub->lock);
01226 f = mgcp_rtp_read(sub);
01227 ast_mutex_unlock(&sub->lock);
01228 return f;
01229 }
01230
01231 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
01232 {
01233 struct mgcp_subchannel *sub = ast->tech_pvt;
01234 int res = 0;
01235 if (frame->frametype != AST_FRAME_VOICE) {
01236 if (frame->frametype == AST_FRAME_IMAGE)
01237 return 0;
01238 else {
01239 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
01240 return 0;
01241 }
01242 } else {
01243 if (!(frame->subclass & ast->nativeformats)) {
01244 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01245 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
01246 return -1;
01247 }
01248 }
01249 if (sub) {
01250 ast_mutex_lock(&sub->lock);
01251 if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
01252 if (sub->rtp) {
01253 res = ast_rtp_write(sub->rtp, frame);
01254 }
01255 }
01256 ast_mutex_unlock(&sub->lock);
01257 }
01258 return res;
01259 }
01260
01261 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
01262 {
01263 struct mgcp_subchannel *sub = newchan->tech_pvt;
01264
01265 ast_mutex_lock(&sub->lock);
01266 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
01267 if (sub->owner != oldchan) {
01268 ast_mutex_unlock(&sub->lock);
01269 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
01270 return -1;
01271 }
01272 sub->owner = newchan;
01273 ast_mutex_unlock(&sub->lock);
01274 return 0;
01275 }
01276
01277 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit)
01278 {
01279 struct mgcp_subchannel *sub = ast->tech_pvt;
01280 struct mgcp_endpoint *p = sub->parent;
01281 int res = 0;
01282
01283 ast_mutex_lock(&sub->lock);
01284 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01285 ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n");
01286 res = -1;
01287 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01288 ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
01289 ast_rtp_senddigit_begin(sub->rtp, digit);
01290 } else {
01291 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01292 }
01293 ast_mutex_unlock(&sub->lock);
01294
01295 return res;
01296 }
01297
01298 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
01299 {
01300 struct mgcp_subchannel *sub = ast->tech_pvt;
01301 struct mgcp_endpoint *p = sub->parent;
01302 int res = 0;
01303 char tmp[4];
01304
01305 ast_mutex_lock(&sub->lock);
01306 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01307 ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n");
01308 res = -1;
01309 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01310 ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n");
01311 tmp[0] = 'D';
01312 tmp[1] = '/';
01313 tmp[2] = digit;
01314 tmp[3] = '\0';
01315 transmit_notify_request(sub, tmp);
01316 ast_rtp_senddigit_end(sub->rtp, digit);
01317 } else {
01318 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01319 }
01320 ast_mutex_unlock(&sub->lock);
01321
01322 return res;
01323 }
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334 static int mgcp_devicestate(void *data)
01335 {
01336 struct mgcp_gateway *g;
01337 struct mgcp_endpoint *e = NULL;
01338 char *tmp, *endpt, *gw;
01339 int ret = AST_DEVICE_INVALID;
01340
01341 endpt = ast_strdupa(data);
01342 if ((tmp = strchr(endpt, '@'))) {
01343 *tmp++ = '\0';
01344 gw = tmp;
01345 } else
01346 goto error;
01347
01348 ast_mutex_lock(&gatelock);
01349 g = gateways;
01350 while (g) {
01351 if (strcasecmp(g->name, gw) == 0) {
01352 e = g->endpoints;
01353 break;
01354 }
01355 g = g->next;
01356 }
01357
01358 if (!e)
01359 goto error;
01360
01361 while (e) {
01362 if (strcasecmp(e->name, endpt) == 0)
01363 break;
01364 e = e->next;
01365 }
01366
01367 if (!e)
01368 goto error;
01369
01370
01371
01372
01373
01374
01375 ret = AST_DEVICE_UNKNOWN;
01376
01377 error:
01378 ast_mutex_unlock(&gatelock);
01379 return ret;
01380 }
01381
01382 static char *control2str(int ind) {
01383 switch (ind) {
01384 case AST_CONTROL_HANGUP:
01385 return "Other end has hungup";
01386 case AST_CONTROL_RING:
01387 return "Local ring";
01388 case AST_CONTROL_RINGING:
01389 return "Remote end is ringing";
01390 case AST_CONTROL_ANSWER:
01391 return "Remote end has answered";
01392 case AST_CONTROL_BUSY:
01393 return "Remote end is busy";
01394 case AST_CONTROL_TAKEOFFHOOK:
01395 return "Make it go off hook";
01396 case AST_CONTROL_OFFHOOK:
01397 return "Line is off hook";
01398 case AST_CONTROL_CONGESTION:
01399 return "Congestion (circuits busy)";
01400 case AST_CONTROL_FLASH:
01401 return "Flash hook";
01402 case AST_CONTROL_WINK:
01403 return "Wink";
01404 case AST_CONTROL_OPTION:
01405 return "Set a low-level option";
01406 case AST_CONTROL_RADIO_KEY:
01407 return "Key Radio";
01408 case AST_CONTROL_RADIO_UNKEY:
01409 return "Un-Key Radio";
01410 }
01411 return "UNKNOWN";
01412 }
01413
01414 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
01415 {
01416 struct mgcp_subchannel *sub = ast->tech_pvt;
01417 int res = 0;
01418
01419 if (mgcpdebug) {
01420 ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n",
01421 ind, control2str(ind), ast->name);
01422 }
01423 ast_mutex_lock(&sub->lock);
01424 switch(ind) {
01425 case AST_CONTROL_RINGING:
01426 #ifdef DLINK_BUGGY_FIRMWARE
01427 transmit_notify_request(sub, "rt");
01428 #else
01429 transmit_notify_request(sub, "G/rt");
01430 #endif
01431 break;
01432 case AST_CONTROL_BUSY:
01433 transmit_notify_request(sub, "L/bz");
01434 break;
01435 case AST_CONTROL_CONGESTION:
01436 transmit_notify_request(sub, "G/cg");
01437 break;
01438 case AST_CONTROL_HOLD:
01439 ast_moh_start(ast, data, NULL);
01440 break;
01441 case AST_CONTROL_UNHOLD:
01442 ast_moh_stop(ast);
01443 break;
01444 case AST_CONTROL_SRCUPDATE:
01445 ast_rtp_new_source(sub->rtp);
01446 break;
01447 case -1:
01448 transmit_notify_request(sub, "");
01449 break;
01450 default:
01451 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01452 res = -1;
01453 }
01454 ast_mutex_unlock(&sub->lock);
01455 return res;
01456 }
01457
01458 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
01459 {
01460 struct ast_channel *tmp;
01461 struct mgcp_endpoint *i = sub->parent;
01462 int fmt;
01463
01464 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);
01465 if (tmp) {
01466 tmp->tech = &mgcp_tech;
01467 tmp->nativeformats = i->capability;
01468 if (!tmp->nativeformats)
01469 tmp->nativeformats = capability;
01470 fmt = ast_best_codec(tmp->nativeformats);
01471 ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01472 if (sub->rtp)
01473 tmp->fds[0] = ast_rtp_fd(sub->rtp);
01474 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
01475 i->dsp = ast_dsp_new();
01476 ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
01477
01478 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
01479 } else {
01480 i->dsp = NULL;
01481 }
01482 if (state == AST_STATE_RING)
01483 tmp->rings = 1;
01484 tmp->writeformat = fmt;
01485 tmp->rawwriteformat = fmt;
01486 tmp->readformat = fmt;
01487 tmp->rawreadformat = fmt;
01488 tmp->tech_pvt = sub;
01489 if (!ast_strlen_zero(i->language))
01490 ast_string_field_set(tmp, language, i->language);
01491 if (!ast_strlen_zero(i->accountcode))
01492 ast_string_field_set(tmp, accountcode, i->accountcode);
01493 if (i->amaflags)
01494 tmp->amaflags = i->amaflags;
01495 sub->owner = tmp;
01496 ast_module_ref(ast_module_info->self);
01497 tmp->callgroup = i->callgroup;
01498 tmp->pickupgroup = i->pickupgroup;
01499 ast_string_field_set(tmp, call_forward, i->call_forward);
01500 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
01501 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
01502
01503
01504
01505 tmp->cid.cid_ani = ast_strdup(i->cid_num);
01506
01507 if (!i->adsi)
01508 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01509 tmp->priority = 1;
01510 if (sub->rtp)
01511 ast_jb_configure(tmp, &global_jbconf);
01512 if (state != AST_STATE_DOWN) {
01513 if (ast_pbx_start(tmp)) {
01514 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01515 ast_hangup(tmp);
01516 tmp = NULL;
01517 }
01518 }
01519
01520 if (option_verbose > 2) {
01521 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
01522 tmp->name, ast_state2str(state));
01523 }
01524 } else {
01525 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01526 }
01527 return tmp;
01528 }
01529
01530 static char* get_sdp_by_line(char* line, char *name, int nameLen)
01531 {
01532 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01533 char* r = line + nameLen + 1;
01534 while (*r && (*r < 33)) ++r;
01535 return r;
01536 }
01537 return "";
01538 }
01539
01540 static char *get_sdp(struct mgcp_request *req, char *name)
01541 {
01542 int x;
01543 int len = strlen(name);
01544 char *r;
01545
01546 for (x=0; x<req->lines; x++) {
01547 r = get_sdp_by_line(req->line[x], name, len);
01548 if (r[0] != '\0') return r;
01549 }
01550 return "";
01551 }
01552
01553 static void sdpLineNum_iterator_init(int* iterator)
01554 {
01555 *iterator = 0;
01556 }
01557
01558 static char* get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
01559 {
01560 int len = strlen(name);
01561 char *r;
01562 while (*iterator < req->lines) {
01563 r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01564 if (r[0] != '\0') return r;
01565 }
01566 return "";
01567 }
01568
01569 static char *__get_header(struct mgcp_request *req, char *name, int *start)
01570 {
01571 int x;
01572 int len = strlen(name);
01573 char *r;
01574 for (x=*start;x<req->headers;x++) {
01575 if (!strncasecmp(req->header[x], name, len) &&
01576 (req->header[x][len] == ':')) {
01577 r = req->header[x] + len + 1;
01578 while(*r && (*r < 33))
01579 r++;
01580 *start = x+1;
01581 return r;
01582 }
01583 }
01584
01585 return "";
01586 }
01587
01588 static char *get_header(struct mgcp_request *req, char *name)
01589 {
01590 int start = 0;
01591 return __get_header(req, name, &start);
01592 }
01593
01594
01595 static char *get_csv(char *c, int *len, char **next)
01596 {
01597 char *s;
01598
01599 *next = NULL, *len = 0;
01600 if (!c) return NULL;
01601
01602 while (*c && (*c < 33 || *c == ','))
01603 c++;
01604
01605 s = c;
01606 while (*c && (*c >= 33 && *c != ','))
01607 c++, (*len)++;
01608 *next = c;
01609
01610 if (*len == 0)
01611 s = NULL, *next = NULL;
01612
01613 return s;
01614 }
01615
01616 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
01617 {
01618 struct mgcp_endpoint *p = NULL;
01619 struct mgcp_subchannel *sub = NULL;
01620 struct mgcp_gateway *g;
01621 char tmp[256] = "";
01622 char *at = NULL, *c;
01623 int found = 0;
01624 if (name) {
01625 ast_copy_string(tmp, name, sizeof(tmp));
01626 at = strchr(tmp, '@');
01627 if (!at) {
01628 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01629 return NULL;
01630 }
01631 *at++ = '\0';
01632 }
01633 ast_mutex_lock(&gatelock);
01634 if (at && (at[0] == '[')) {
01635 at++;
01636 c = strrchr(at, ']');
01637 if (c)
01638 *c = '\0';
01639 }
01640 g = gateways;
01641 while(g) {
01642 if ((!name || !strcasecmp(g->name, at)) &&
01643 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01644
01645 if (sin && g->dynamic && name) {
01646 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01647 (g->addr.sin_port != sin->sin_port)) {
01648 memcpy(&g->addr, sin, sizeof(g->addr));
01649 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
01650 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01651 if (option_verbose > 2)
01652 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));
01653 }
01654 }
01655
01656 else if (name) {
01657 if (strcasecmp(g->name, at)) {
01658 g = g->next;
01659 continue;
01660 }
01661 }
01662
01663 else if (!name && sin) {
01664 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01665 (g->addr.sin_port != sin->sin_port)) {
01666 g = g->next;
01667 continue;
01668 }
01669 } else {
01670 g = g->next;
01671 continue;
01672 }
01673
01674 p = g->endpoints;
01675 while(p) {
01676 if (option_debug)
01677 ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n",
01678 p->name, g->name);
01679 if (msgid) {
01680 #if 0
01681 sub = p->sub;
01682 do {
01683 if (option_debug)
01684 ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
01685 p->name, g->name, sub->id, msgid);
01686 if (sub->lastout == msgid) {
01687 if (option_debug)
01688 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
01689 sub->id, msgid, sub->lastout);
01690 found = 1;
01691 break;
01692 }
01693 sub = sub->next;
01694 } while (sub != p->sub);
01695 if (found) {
01696 break;
01697 }
01698 #endif
01699
01700 sub = p->sub;
01701 found = 1;
01702
01703 break;
01704 } else if (name && !strcasecmp(p->name, tmp)) {
01705 ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
01706 p->name, g->name, p->sub->id);
01707 sub = p->sub;
01708 found = 1;
01709 break;
01710 }
01711 p = p->next;
01712 }
01713 if (sub && found) {
01714 ast_mutex_lock(&sub->lock);
01715 break;
01716 }
01717 }
01718 g = g->next;
01719 }
01720 ast_mutex_unlock(&gatelock);
01721 if (!sub) {
01722 if (name) {
01723 if (g)
01724 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01725 else
01726 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01727 }
01728 }
01729 return sub;
01730 }
01731
01732 static void parse(struct mgcp_request *req)
01733 {
01734
01735 char *c;
01736 int f = 0;
01737 c = req->data;
01738
01739
01740 req->header[f] = c;
01741 while(*c) {
01742 if (*c == '\n') {
01743
01744 *c = 0;
01745 #if 0
01746 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
01747 #endif
01748 if (ast_strlen_zero(req->header[f])) {
01749
01750 c++;
01751 break;
01752 }
01753 if (f >= MGCP_MAX_HEADERS - 1) {
01754 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01755 } else
01756 f++;
01757 req->header[f] = c + 1;
01758 } else if (*c == '\r') {
01759
01760 *c = 0;
01761 }
01762 c++;
01763 }
01764
01765 if (!ast_strlen_zero(req->header[f]))
01766 f++;
01767 req->headers = f;
01768
01769 f = 0;
01770 req->line[f] = c;
01771 while(*c) {
01772 if (*c == '\n') {
01773
01774 *c = 0;
01775 #if 0
01776 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
01777 #endif
01778 if (f >= MGCP_MAX_LINES - 1) {
01779 ast_log(LOG_WARNING, "Too many SDP lines...\n");
01780 } else
01781 f++;
01782 req->line[f] = c + 1;
01783 } else if (*c == '\r') {
01784
01785 *c = 0;
01786 }
01787 c++;
01788 }
01789
01790 if (!ast_strlen_zero(req->line[f]))
01791 f++;
01792 req->lines = f;
01793
01794 c = req->header[0];
01795 while(*c && *c < 33) c++;
01796
01797 req->verb = c;
01798 while(*c && (*c > 32)) c++;
01799 if (*c) {
01800 *c = '\0';
01801 c++;
01802 while(*c && (*c < 33)) c++;
01803 req->identifier = c;
01804 while(*c && (*c > 32)) c++;
01805 if (*c) {
01806 *c = '\0';
01807 c++;
01808 while(*c && (*c < 33)) c++;
01809 req->endpoint = c;
01810 while(*c && (*c > 32)) c++;
01811 if (*c) {
01812 *c = '\0';
01813 c++;
01814 while(*c && (*c < 33)) c++;
01815 req->version = c;
01816 while(*c && (*c > 32)) c++;
01817 while(*c && (*c < 33)) c++;
01818 while(*c && (*c > 32)) c++;
01819 *c = '\0';
01820 }
01821 }
01822 }
01823
01824 if (mgcpdebug) {
01825 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01826 req->verb, req->identifier, req->endpoint, req->version);
01827 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
01828 }
01829 if (*c)
01830 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01831 }
01832
01833 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
01834 {
01835 char *m;
01836 char *c;
01837 char *a;
01838 char host[258];
01839 int len;
01840 int portno;
01841 int peercapability, peerNonCodecCapability;
01842 struct sockaddr_in sin;
01843 char *codecs;
01844 struct ast_hostent ahp; struct hostent *hp;
01845 int codec, codec_count=0;
01846 int iterator;
01847 struct mgcp_endpoint *p = sub->parent;
01848
01849
01850 m = get_sdp(req, "m");
01851 c = get_sdp(req, "c");
01852 if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
01853 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
01854 return -1;
01855 }
01856 if (sscanf(c, "IN IP4 %256s", host) != 1) {
01857 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
01858 return -1;
01859 }
01860
01861 hp = ast_gethostbyname(host, &ahp);
01862 if (!hp) {
01863 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
01864 return -1;
01865 }
01866 if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) {
01867 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
01868 return -1;
01869 }
01870 sin.sin_family = AF_INET;
01871 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01872 sin.sin_port = htons(portno);
01873 ast_rtp_set_peer(sub->rtp, &sin);
01874 #if 0
01875 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
01876 #endif
01877
01878 ast_rtp_pt_clear(sub->rtp);
01879 codecs = ast_strdupa(m + len);
01880 while (!ast_strlen_zero(codecs)) {
01881 if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
01882 if (codec_count)
01883 break;
01884 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
01885 return -1;
01886 }
01887 ast_rtp_set_m_type(sub->rtp, codec);
01888 codec_count++;
01889 codecs += len;
01890 }
01891
01892
01893
01894 sdpLineNum_iterator_init(&iterator);
01895 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
01896 char* mimeSubtype = ast_strdupa(a);
01897 if (sscanf(a, "rtpmap: %30u %[^/]/", &codec, mimeSubtype) != 2)
01898 continue;
01899
01900 ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0);
01901 }
01902
01903
01904 ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
01905 p->capability = capability & peercapability;
01906 if (mgcpdebug) {
01907 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
01908 capability, peercapability, p->capability);
01909 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
01910 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
01911 }
01912 if (!p->capability) {
01913 ast_log(LOG_WARNING, "No compatible codecs!\n");
01914 return -1;
01915 }
01916 return 0;
01917 }
01918
01919 static int add_header(struct mgcp_request *req, char *var, char *value)
01920 {
01921 if (req->len >= sizeof(req->data) - 4) {
01922 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01923 return -1;
01924 }
01925 if (req->lines) {
01926 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
01927 return -1;
01928 }
01929 req->header[req->headers] = req->data + req->len;
01930 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
01931 req->len += strlen(req->header[req->headers]);
01932 if (req->headers < MGCP_MAX_HEADERS)
01933 req->headers++;
01934 else {
01935 ast_log(LOG_WARNING, "Out of header space\n");
01936 return -1;
01937 }
01938 return 0;
01939 }
01940
01941 static int add_line(struct mgcp_request *req, char *line)
01942 {
01943 if (req->len >= sizeof(req->data) - 4) {
01944 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01945 return -1;
01946 }
01947 if (!req->lines) {
01948
01949 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
01950 req->len += strlen(req->data + req->len);
01951 }
01952 req->line[req->lines] = req->data + req->len;
01953 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
01954 req->len += strlen(req->line[req->lines]);
01955 if (req->lines < MGCP_MAX_LINES)
01956 req->lines++;
01957 else {
01958 ast_log(LOG_WARNING, "Out of line space\n");
01959 return -1;
01960 }
01961 return 0;
01962 }
01963
01964 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
01965 {
01966
01967 if (req->headers || req->len) {
01968 ast_log(LOG_WARNING, "Request already initialized?!?\n");
01969 return -1;
01970 }
01971 req->header[req->headers] = req->data + req->len;
01972 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
01973 req->len += strlen(req->header[req->headers]);
01974 if (req->headers < MGCP_MAX_HEADERS)
01975 req->headers++;
01976 else
01977 ast_log(LOG_WARNING, "Out of header space\n");
01978 return 0;
01979 }
01980
01981 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
01982 {
01983
01984 if (req->headers || req->len) {
01985 ast_log(LOG_WARNING, "Request already initialized?!?\n");
01986 return -1;
01987 }
01988 req->header[req->headers] = req->data + req->len;
01989
01990 if (p->parent->isnamedottedip)
01991 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);
01992 else
01993 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);
01994 req->len += strlen(req->header[req->headers]);
01995 if (req->headers < MGCP_MAX_HEADERS)
01996 req->headers++;
01997 else
01998 ast_log(LOG_WARNING, "Out of header space\n");
01999 return 0;
02000 }
02001
02002
02003 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
02004 {
02005 memset(resp, 0, sizeof(*resp));
02006 init_resp(resp, msg, req, msgrest);
02007 return 0;
02008 }
02009
02010 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
02011 {
02012 memset(req, 0, sizeof(struct mgcp_request));
02013 oseq++;
02014 if (oseq > 999999999)
02015 oseq = 1;
02016 init_req(p, req, verb);
02017 return 0;
02018 }
02019
02020 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
02021 {
02022 struct mgcp_request resp;
02023 struct mgcp_endpoint *p = sub->parent;
02024 struct mgcp_response *mgr;
02025
02026 respprep(&resp, p, msg, req, msgrest);
02027 mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
02028 if (mgr) {
02029
02030 memset(mgr, 0, sizeof(struct mgcp_response));
02031 sscanf(req->identifier, "%30d", &mgr->seqno);
02032 time(&mgr->whensent);
02033 mgr->len = resp.len;
02034 memcpy(mgr->buf, resp.data, resp.len);
02035 mgr->buf[resp.len] = '\0';
02036 mgr->next = p->parent->responses;
02037 p->parent->responses = mgr;
02038 }
02039 return send_response(sub, &resp);
02040 }
02041
02042
02043 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
02044 {
02045 int len;
02046 int codec;
02047 char costr[80];
02048 struct sockaddr_in sin;
02049 char v[256];
02050 char s[256];
02051 char o[256];
02052 char c[256];
02053 char t[256];
02054 char m[256] = "";
02055 char a[1024] = "";
02056 int x;
02057 struct sockaddr_in dest;
02058 struct mgcp_endpoint *p = sub->parent;
02059
02060
02061 len = 0;
02062 if (!sub->rtp) {
02063 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
02064 return -1;
02065 }
02066 ast_rtp_get_us(sub->rtp, &sin);
02067 if (rtp) {
02068 ast_rtp_get_peer(rtp, &dest);
02069 } else {
02070 if (sub->tmpdest.sin_addr.s_addr) {
02071 dest.sin_addr = sub->tmpdest.sin_addr;
02072 dest.sin_port = sub->tmpdest.sin_port;
02073
02074 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
02075 } else {
02076 dest.sin_addr = p->parent->ourip;
02077 dest.sin_port = sin.sin_port;
02078 }
02079 }
02080 if (mgcpdebug) {
02081 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
02082 }
02083 snprintf(v, sizeof(v), "v=0\r\n");
02084 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
02085 snprintf(s, sizeof(s), "s=session\r\n");
02086 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
02087 snprintf(t, sizeof(t), "t=0 0\r\n");
02088 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
02089 for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02090 if (p->capability & x) {
02091 if (mgcpdebug) {
02092 ast_verbose("Answering with capability %d\n", x);
02093 }
02094 codec = ast_rtp_lookup_code(sub->rtp, 1, x);
02095 if (codec > -1) {
02096 snprintf(costr, sizeof(costr), " %d", codec);
02097 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02098 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0));
02099 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02100 }
02101 }
02102 }
02103 for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
02104 if (p->nonCodecCapability & x) {
02105 if (mgcpdebug) {
02106 ast_verbose("Answering with non-codec capability %d\n", x);
02107 }
02108 codec = ast_rtp_lookup_code(sub->rtp, 0, x);
02109 if (codec > -1) {
02110 snprintf(costr, sizeof(costr), " %d", codec);
02111 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02112 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0));
02113 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02114 if (x == AST_RTP_DTMF) {
02115
02116
02117 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
02118 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02119 }
02120 }
02121 }
02122 }
02123 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
02124 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
02125 snprintf(costr, sizeof(costr), "%d", len);
02126 add_line(resp, v);
02127 add_line(resp, o);
02128 add_line(resp, s);
02129 add_line(resp, c);
02130 add_line(resp, t);
02131 add_line(resp, m);
02132 add_line(resp, a);
02133 return 0;
02134 }
02135
02136 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
02137 {
02138 struct mgcp_request resp;
02139 char local[256];
02140 char tmp[80];
02141 int x;
02142 int capability;
02143 struct mgcp_endpoint *p = sub->parent;
02144
02145 capability = p->capability;
02146 if (codecs)
02147 capability = codecs;
02148 if (ast_strlen_zero(sub->cxident) && rtp) {
02149
02150
02151 ast_rtp_get_peer(rtp, &sub->tmpdest);
02152 return 0;
02153 }
02154 snprintf(local, sizeof(local), "p:20");
02155 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02156 if (p->capability & x) {
02157 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02158 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02159 }
02160 }
02161 reqprep(&resp, p, "MDCX");
02162 add_header(&resp, "C", sub->callid);
02163 add_header(&resp, "L", local);
02164 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02165
02166 add_header(&resp, "X", sub->txident);
02167 add_header(&resp, "I", sub->cxident);
02168
02169 add_sdp(&resp, sub, rtp);
02170
02171 resp.cmd = MGCP_CMD_MDCX;
02172 resp.trid = oseq;
02173 return send_request(p, sub, &resp, oseq);
02174 }
02175
02176 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
02177 {
02178 struct mgcp_request resp;
02179 char local[256];
02180 char tmp[80];
02181 int x;
02182 struct mgcp_endpoint *p = sub->parent;
02183
02184 snprintf(local, sizeof(local), "p:20");
02185 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02186 if (p->capability & x) {
02187 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02188 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02189 }
02190 }
02191 if (mgcpdebug) {
02192 ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02193 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02194 }
02195 reqprep(&resp, p, "CRCX");
02196 add_header(&resp, "C", sub->callid);
02197 add_header(&resp, "L", local);
02198 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02199
02200 add_header(&resp, "X", sub->txident);
02201
02202 add_sdp(&resp, sub, rtp);
02203
02204 resp.cmd = MGCP_CMD_CRCX;
02205 resp.trid = oseq;
02206 return send_request(p, sub, &resp, oseq);
02207 }
02208
02209 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
02210 {
02211 struct mgcp_request resp;
02212 struct mgcp_endpoint *p = sub->parent;
02213
02214 if (mgcpdebug) {
02215 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02216 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02217 }
02218 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02219 reqprep(&resp, p, "RQNT");
02220 add_header(&resp, "X", p->rqnt_ident);
02221 switch (p->hookstate) {
02222 case MGCP_ONHOOK:
02223 add_header(&resp, "R", "L/hd(N)");
02224 break;
02225 case MGCP_OFFHOOK:
02226 add_header_offhook(sub, &resp);
02227 break;
02228 }
02229 if (!ast_strlen_zero(tone)) {
02230 add_header(&resp, "S", tone);
02231 }
02232
02233 resp.cmd = MGCP_CMD_RQNT;
02234 resp.trid = oseq;
02235 return send_request(p, NULL, &resp, oseq);
02236 }
02237
02238 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
02239 {
02240 struct mgcp_request resp;
02241 char tone2[256];
02242 char *l, *n;
02243 time_t t;
02244 struct tm tm;
02245 struct mgcp_endpoint *p = sub->parent;
02246
02247 time(&t);
02248 ast_localtime(&t, &tm, NULL);
02249 n = callername;
02250 l = callernum;
02251 if (!n)
02252 n = "";
02253 if (!l)
02254 l = "";
02255
02256
02257 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
02258
02259 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
02260 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02261 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02262 reqprep(&resp, p, "RQNT");
02263 add_header(&resp, "X", p->rqnt_ident);
02264 switch (p->hookstate) {
02265 case MGCP_ONHOOK:
02266 add_header(&resp, "R", "L/hd(N)");
02267 break;
02268 case MGCP_OFFHOOK:
02269 add_header_offhook(sub, &resp);
02270 break;
02271 }
02272 if (!ast_strlen_zero(tone2)) {
02273 add_header(&resp, "S", tone2);
02274 }
02275 if (mgcpdebug) {
02276 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02277 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02278 }
02279
02280 resp.cmd = MGCP_CMD_RQNT;
02281 resp.trid = oseq;
02282 return send_request(p, NULL, &resp, oseq);
02283 }
02284
02285 static int transmit_modify_request(struct mgcp_subchannel *sub)
02286 {
02287 struct mgcp_request resp;
02288 struct mgcp_endpoint *p = sub->parent;
02289
02290 if (ast_strlen_zero(sub->cxident)) {
02291
02292
02293 return 0;
02294 }
02295 if (mgcpdebug) {
02296 ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n",
02297 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02298 }
02299 reqprep(&resp, p, "MDCX");
02300 add_header(&resp, "C", sub->callid);
02301 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02302
02303 add_header(&resp, "X", sub->txident);
02304 add_header(&resp, "I", sub->cxident);
02305 switch (sub->parent->hookstate) {
02306 case MGCP_ONHOOK:
02307 add_header(&resp, "R", "L/hd(N)");
02308 break;
02309 case MGCP_OFFHOOK:
02310 add_header_offhook(sub, &resp);
02311 break;
02312 }
02313
02314 resp.cmd = MGCP_CMD_MDCX;
02315 resp.trid = oseq;
02316 return send_request(p, sub, &resp, oseq);
02317 }
02318
02319
02320 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp)
02321 {
02322 struct mgcp_endpoint *p = sub->parent;
02323
02324 if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)))
02325 add_header(resp, "R", "L/hu(N),L/hf(N)");
02326 else
02327 add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
02328 }
02329
02330 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
02331 {
02332 struct mgcp_request resp;
02333 reqprep(&resp, p, "AUEP");
02334
02335
02336 add_header(&resp, "F", "A");
02337
02338 resp.cmd = MGCP_CMD_AUEP;
02339 resp.trid = oseq;
02340 return send_request(p, NULL, &resp, oseq);
02341 }
02342
02343 static int transmit_connection_del(struct mgcp_subchannel *sub)
02344 {
02345 struct mgcp_endpoint *p = sub->parent;
02346 struct mgcp_request resp;
02347
02348 if (mgcpdebug) {
02349 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
02350 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02351 }
02352 reqprep(&resp, p, "DLCX");
02353
02354 if (sub->callid[0])
02355 add_header(&resp, "C", sub->callid);
02356
02357 add_header(&resp, "X", sub->txident);
02358
02359 if (sub->cxident[0])
02360 add_header(&resp, "I", sub->cxident);
02361
02362 resp.cmd = MGCP_CMD_DLCX;
02363 resp.trid = oseq;
02364 return send_request(p, sub, &resp, oseq);
02365 }
02366
02367 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
02368 {
02369 struct mgcp_request resp;
02370
02371 if (mgcpdebug) {
02372 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n",
02373 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02374 }
02375 reqprep(&resp, p, "DLCX");
02376
02377 if (callid && *callid)
02378 add_header(&resp, "C", callid);
02379
02380 if (cxident && *cxident)
02381 add_header(&resp, "I", cxident);
02382
02383 resp.cmd = MGCP_CMD_DLCX;
02384 resp.trid = oseq;
02385 return send_request(p, p->sub, &resp, oseq);
02386 }
02387
02388
02389 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
02390 {
02391 struct mgcp_request *t, *q;
02392
02393 if (p) {
02394 ast_mutex_lock(&p->rqnt_queue_lock);
02395 for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
02396 p->rqnt_queue = NULL;
02397 ast_mutex_unlock(&p->rqnt_queue_lock);
02398
02399 ast_mutex_lock(&p->cmd_queue_lock);
02400 for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
02401 p->cmd_queue = NULL;
02402 ast_mutex_unlock(&p->cmd_queue_lock);
02403
02404 ast_mutex_lock(&p->sub->cx_queue_lock);
02405 for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
02406 p->sub->cx_queue = NULL;
02407 ast_mutex_unlock(&p->sub->cx_queue_lock);
02408
02409 ast_mutex_lock(&p->sub->next->cx_queue_lock);
02410 for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
02411 p->sub->next->cx_queue = NULL;
02412 ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02413 } else if (sub) {
02414 ast_mutex_lock(&sub->cx_queue_lock);
02415 for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
02416 sub->cx_queue = NULL;
02417 ast_mutex_unlock(&sub->cx_queue_lock);
02418 }
02419 }
02420
02421
02422
02423 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02424 struct mgcp_request **queue, ast_mutex_t *l, int ident)
02425 {
02426 struct mgcp_request *prev, *req;
02427
02428 ast_mutex_lock(l);
02429 for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02430 if (req->trid == ident) {
02431
02432 if (!prev)
02433 *queue = req->next;
02434 else
02435 prev->next = req->next;
02436
02437
02438 if (*queue) {
02439 if (mgcpdebug) {
02440 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
02441 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02442 }
02443
02444 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02445 }
02446 break;
02447 }
02448 }
02449 ast_mutex_unlock(l);
02450 return req;
02451 }
02452
02453
02454 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02455 int result, unsigned int ident, struct mgcp_request *resp)
02456 {
02457 char *c;
02458 struct mgcp_request *req;
02459 struct mgcp_gateway *gw = p->parent;
02460
02461 if (result < 200) {
02462
02463 return;
02464 }
02465
02466 if (p->slowsequence)
02467 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02468 else if (sub)
02469 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
02470 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
02471 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02472
02473 if (!req) {
02474 if (option_verbose > 2) {
02475 ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n",
02476 gw->name, ident);
02477 }
02478 return;
02479 }
02480
02481 if (p && (result >= 400) && (result <= 599)) {
02482 switch (result) {
02483 case 401:
02484 p->hookstate = MGCP_OFFHOOK;
02485 break;
02486 case 402:
02487 p->hookstate = MGCP_ONHOOK;
02488 break;
02489 case 406:
02490 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
02491 break;
02492 case 407:
02493 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
02494 break;
02495 }
02496 if (sub) {
02497 if (sub->owner) {
02498 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02499 result, p->name, p->parent->name, sub ? sub->id:-1);
02500 mgcp_queue_hangup(sub);
02501 }
02502 } else {
02503 if (p->sub->next->owner) {
02504 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02505 result, p->name, p->parent->name, sub ? sub->id:-1);
02506 mgcp_queue_hangup(p->sub);
02507 }
02508
02509 if (p->sub->owner) {
02510 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02511 result, p->name, p->parent->name, sub ? sub->id:-1);
02512 mgcp_queue_hangup(p->sub);
02513 }
02514
02515 dump_cmd_queues(p, NULL);
02516 }
02517 }
02518
02519 if (resp) {
02520 if (req->cmd == MGCP_CMD_CRCX) {
02521 if ((c = get_header(resp, "I"))) {
02522 if (!ast_strlen_zero(c) && sub) {
02523
02524 if (sub->owner) {
02525 if (!ast_strlen_zero(sub->cxident)) {
02526 if (strcasecmp(c, sub->cxident)) {
02527 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
02528 }
02529 }
02530 ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
02531 if (sub->tmpdest.sin_addr.s_addr) {
02532 transmit_modify_with_sdp(sub, NULL, 0);
02533 }
02534 } else {
02535
02536
02537
02538
02539 transmit_connection_del(sub);
02540 }
02541 }
02542 }
02543 }
02544
02545 if (req->cmd == MGCP_CMD_AUEP) {
02546
02547 if ((c = get_header(resp, "I"))) {
02548 char *v, *n;
02549 int len;
02550 while ((v = get_csv(c, &len, &n))) {
02551 if (len) {
02552 if (strncasecmp(v, p->sub->cxident, len) &&
02553 strncasecmp(v, p->sub->next->cxident, len)) {
02554
02555 char cxident[80] = "";
02556
02557 if (len > (sizeof(cxident) - 1))
02558 len = sizeof(cxident) - 1;
02559 ast_copy_string(cxident, v, len);
02560 if (option_verbose > 2) {
02561 ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n",
02562 cxident, p->name, gw->name);
02563 }
02564 transmit_connection_del_w_params(p, NULL, cxident);
02565 }
02566 }
02567 c = n;
02568 }
02569 }
02570
02571
02572 if ((c = get_header(resp, "ES"))) {
02573 if (!ast_strlen_zero(c)) {
02574 if (strstr(c, "hu")) {
02575 if (p->hookstate != MGCP_ONHOOK) {
02576
02577 if ((p->sub->owner || p->sub->next->owner ) &&
02578 p->hookstate == MGCP_OFFHOOK)
02579 mgcp_queue_hangup(sub);
02580 p->hookstate = MGCP_ONHOOK;
02581
02582
02583 transmit_notify_request(p->sub, "");
02584
02585
02586 if (option_verbose > 2) {
02587 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
02588 }
02589 }
02590 } else if (strstr(c, "hd")) {
02591 if (p->hookstate != MGCP_OFFHOOK) {
02592 p->hookstate = MGCP_OFFHOOK;
02593
02594
02595 transmit_notify_request(p->sub, "");
02596
02597
02598 if (option_verbose > 2) {
02599 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
02600 }
02601 }
02602 }
02603 }
02604 }
02605 }
02606
02607 if (resp && resp->lines) {
02608
02609 if (sub && sub->owner) {
02610 if (!sub->rtp)
02611 start_rtp(sub);
02612 if (sub->rtp)
02613 process_sdp(sub, resp);
02614 }
02615 }
02616 }
02617
02618 free(req);
02619 }
02620
02621 static void start_rtp(struct mgcp_subchannel *sub)
02622 {
02623 ast_mutex_lock(&sub->lock);
02624
02625 if (sub->rtp) {
02626 ast_rtp_destroy(sub->rtp);
02627 sub->rtp = NULL;
02628 }
02629
02630 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
02631 if (sub->rtp && sub->owner)
02632 sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
02633 if (sub->rtp)
02634 ast_rtp_setnat(sub->rtp, sub->nat);
02635 #if 0
02636 ast_rtp_set_callback(p->rtp, rtpready);
02637 ast_rtp_set_data(p->rtp, p);
02638 #endif
02639
02640 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
02641
02642 transmit_connect_with_sdp(sub, NULL);
02643 ast_mutex_unlock(&sub->lock);
02644 }
02645
02646 static void *mgcp_ss(void *data)
02647 {
02648 struct ast_channel *chan = data;
02649 struct mgcp_subchannel *sub = chan->tech_pvt;
02650 struct mgcp_endpoint *p = sub->parent;
02651
02652 int len = 0;
02653 int timeout = firstdigittimeout;
02654 int res= 0;
02655 int getforward = 0;
02656 int loop_pause = 100;
02657
02658 len = strlen(p->dtmf_buf);
02659
02660 while(len < AST_MAX_EXTENSION-1) {
02661 res = 1;
02662 while (strlen(p->dtmf_buf) == len){
02663 ast_safe_sleep(chan, loop_pause);
02664 timeout -= loop_pause;
02665 if (timeout <= 0){
02666 res = 0;
02667 break;
02668 }
02669 res = 1;
02670 }
02671
02672 timeout = 0;
02673 len = strlen(p->dtmf_buf);
02674
02675 if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) {
02676
02677 ast_indicate(chan, -1);
02678 } else {
02679
02680
02681 transmit_notify_request(sub, "L/dl");
02682 }
02683 if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02684 if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02685 if (getforward) {
02686
02687 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward));
02688 if (option_verbose > 2) {
02689 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
02690 p->call_forward, chan->name);
02691 }
02692
02693 transmit_notify_request(sub, "L/sl");
02694 if (res)
02695 break;
02696 usleep(500000);
02697
02698 ast_indicate(chan, -1);
02699 sleep(1);
02700 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02701
02702 transmit_notify_request(sub, "L/dl");
02703 len = 0;
02704 getforward = 0;
02705 } else {
02706
02707 ast_indicate(chan, -1);
02708 ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten));
02709 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02710 ast_set_callerid(chan,
02711 p->hidecallerid ? "" : p->cid_num,
02712 p->hidecallerid ? "" : p->cid_name,
02713 chan->cid.cid_ani ? NULL : p->cid_num);
02714 ast_setstate(chan, AST_STATE_RING);
02715
02716 if (p->dtmfmode & MGCP_DTMF_HYBRID) {
02717 p->dtmfmode |= MGCP_DTMF_INBAND;
02718 ast_indicate(chan, -1);
02719 }
02720 res = ast_pbx_run(chan);
02721 if (res) {
02722 ast_log(LOG_WARNING, "PBX exited non-zero\n");
02723
02724
02725 transmit_notify_request(sub, "G/cg");
02726 }
02727 return NULL;
02728 }
02729 } else {
02730
02731
02732 timeout = matchdigittimeout;
02733 }
02734 } else if (res == 0) {
02735 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
02736
02737 transmit_notify_request(sub, "G/cg");
02738
02739 ast_hangup(chan);
02740 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02741 return NULL;
02742 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) {
02743 if (option_verbose > 2) {
02744 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
02745 }
02746
02747 p->callwaiting = 0;
02748
02749 transmit_notify_request(sub, "L/sl");
02750 len = 0;
02751 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02752 timeout = firstdigittimeout;
02753 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) {
02754
02755
02756
02757
02758 if (ast_pickup_call(chan)) {
02759 ast_log(LOG_WARNING, "No call pickup possible...\n");
02760
02761 transmit_notify_request(sub, "G/cg");
02762 }
02763 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02764 ast_hangup(chan);
02765 return NULL;
02766 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) {
02767 if (option_verbose > 2) {
02768 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
02769 }
02770
02771 p->hidecallerid = 1;
02772 ast_set_callerid(chan, "", "", NULL);
02773
02774 transmit_notify_request(sub, "L/sl");
02775 len = 0;
02776 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02777 timeout = firstdigittimeout;
02778 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) {
02779 res = 0;
02780 if (!ast_strlen_zero(p->lastcallerid)) {
02781 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
02782 }
02783 if (!res)
02784
02785 transmit_notify_request(sub, "L/sl");
02786 break;
02787 } else if (!strcmp(p->dtmf_buf, "*78")) {
02788
02789 if (option_verbose > 2) {
02790 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
02791 }
02792
02793 transmit_notify_request(sub, "L/sl");
02794 p->dnd = 1;
02795 getforward = 0;
02796 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02797 len = 0;
02798 } else if (!strcmp(p->dtmf_buf, "*79")) {
02799
02800 if (option_verbose > 2) {
02801 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
02802 }
02803
02804 transmit_notify_request(sub, "L/sl");
02805 p->dnd = 0;
02806 getforward = 0;
02807 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02808 len = 0;
02809 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) {
02810
02811 transmit_notify_request(sub, "L/sl");
02812 getforward = 1;
02813 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02814 len = 0;
02815 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) {
02816 if (option_verbose > 2) {
02817 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
02818 }
02819
02820 transmit_notify_request(sub, "L/sl");
02821 memset(p->call_forward, 0, sizeof(p->call_forward));
02822 getforward = 0;
02823 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02824 len = 0;
02825 } else if (!strcmp(p->dtmf_buf, ast_parking_ext()) &&
02826 sub->next->owner && ast_bridged_channel(sub->next->owner)) {
02827
02828
02829 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
02830 if (option_verbose > 2) {
02831 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
02832 }
02833 break;
02834 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) {
02835 if (option_verbose > 2) {
02836 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
02837 }
02838 res = ast_db_put("blacklist", p->lastcallerid, "1");
02839 if (!res) {
02840
02841 transmit_notify_request(sub, "L/sl");
02842 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02843 len = 0;
02844 }
02845 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) {
02846 if (option_verbose > 2) {
02847 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
02848 }
02849
02850 p->hidecallerid = 0;
02851 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
02852
02853 transmit_notify_request(sub, "L/sl");
02854 len = 0;
02855 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02856 timeout = firstdigittimeout;
02857 } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, chan->cid.cid_num) &&
02858 ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
02859 if (option_debug)
02860 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);
02861 break;
02862 }
02863 if (!timeout)
02864 timeout = gendigittimeout;
02865 if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf))
02866
02867 ast_indicate(chan, -1);
02868 }
02869 #if 0
02870 for (;;) {
02871 res = ast_waitfordigit(chan, to);
02872 if (!res) {
02873 ast_log(LOG_DEBUG, "Timeout...\n");
02874 break;
02875 }
02876 if (res < 0) {
02877 ast_log(LOG_DEBUG, "Got hangup...\n");
02878 ast_hangup(chan);
02879 break;
02880 }
02881 exten[pos++] = res;
02882 if (!ast_ignore_pattern(chan->context, exten))
02883 ast_indicate(chan, -1);
02884 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
02885 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
02886 to = 3000;
02887 else
02888 to = 8000;
02889 } else
02890 break;
02891 }
02892 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
02893 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1);
02894 if (!p->rtp) {
02895 start_rtp(p);
02896 }
02897 ast_setstate(chan, AST_STATE_RING);
02898 chan->rings = 1;
02899 if (ast_pbx_run(chan)) {
02900 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
02901 } else {
02902 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02903 return NULL;
02904 }
02905 }
02906 #endif
02907 ast_hangup(chan);
02908 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02909 return NULL;
02910 }
02911
02912 static int attempt_transfer(struct mgcp_endpoint *p)
02913 {
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923 if (ast_bridged_channel(p->sub->owner)) {
02924
02925
02926 if (ast_bridged_channel(p->sub->next->owner))
02927 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
02928 if (p->sub->owner->_state == AST_STATE_RINGING) {
02929 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02930 }
02931 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
02932 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02933 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
02934 return -1;
02935 }
02936
02937 unalloc_sub(p->sub->next);
02938 } else if (ast_bridged_channel(p->sub->next->owner)) {
02939 if (p->sub->owner->_state == AST_STATE_RINGING) {
02940 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02941 }
02942 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
02943 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
02944 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02945 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
02946 return -1;
02947 }
02948
02949 if (option_verbose > 2) {
02950 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);
02951 }
02952 p->sub = p->sub->next;
02953 unalloc_sub(p->sub->next);
02954
02955 return 1;
02956 } else {
02957 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
02958 p->sub->owner->name, p->sub->next->owner->name);
02959 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02960 if (p->sub->next->owner) {
02961 p->sub->next->alreadygone = 1;
02962 mgcp_queue_hangup(p->sub->next);
02963 }
02964 }
02965 return 0;
02966 }
02967
02968 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
02969 {
02970 struct mgcp_endpoint *p = sub->parent;
02971 struct ast_channel *c;
02972 pthread_t t;
02973 pthread_attr_t attr;
02974 pthread_attr_init(&attr);
02975 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02976
02977
02978 if (sub->outgoing) {
02979
02980 if (sub->owner) {
02981 if (ast_bridged_channel(sub->owner))
02982 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
02983 sub->cxmode = MGCP_CX_SENDRECV;
02984 if (!sub->rtp) {
02985 start_rtp(sub);
02986 } else {
02987 transmit_modify_request(sub);
02988 }
02989
02990 transmit_notify_request(sub, "");
02991 mgcp_queue_control(sub, AST_CONTROL_ANSWER);
02992 }
02993 } else {
02994
02995
02996 if (!sub->owner) {
02997 if (!sub->rtp) {
02998 start_rtp(sub);
02999 } else {
03000 transmit_modify_request(sub);
03001 }
03002 if (p->immediate) {
03003
03004 #ifdef DLINK_BUGGY_FIRMWARE
03005 transmit_notify_request(sub, "rt");
03006 #else
03007 transmit_notify_request(sub, "G/rt");
03008 #endif
03009 c = mgcp_new(sub, AST_STATE_RING);
03010 if (!c) {
03011 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
03012 transmit_notify_request(sub, "G/cg");
03013 ast_hangup(c);
03014 }
03015 } else {
03016 if (has_voicemail(p)) {
03017 transmit_notify_request(sub, "L/sl");
03018 } else {
03019 transmit_notify_request(sub, "L/dl");
03020 }
03021 c = mgcp_new(sub, AST_STATE_DOWN);
03022 if (c) {
03023 if (ast_pthread_create(&t, &attr, mgcp_ss, c)) {
03024 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
03025 ast_hangup(c);
03026 }
03027 } else {
03028 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
03029 }
03030 }
03031 } else {
03032 if (p->hookstate == MGCP_OFFHOOK) {
03033 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03034 } else {
03035 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03036 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
03037 }
03038 if (ast_bridged_channel(sub->owner))
03039 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03040 sub->cxmode = MGCP_CX_SENDRECV;
03041 if (!sub->rtp) {
03042 start_rtp(sub);
03043 } else {
03044 transmit_modify_request(sub);
03045 }
03046
03047 transmit_notify_request(sub, "");
03048
03049 }
03050 }
03051 pthread_attr_destroy(&attr);
03052 }
03053
03054 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
03055 {
03056 char *ev, *s;
03057 struct ast_frame f = { 0, };
03058 struct mgcp_endpoint *p = sub->parent;
03059 struct mgcp_gateway *g = NULL;
03060 int res;
03061
03062 if (mgcpdebug) {
03063 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
03064 }
03065
03066 if (!strcasecmp(req->verb, "RSIP")) {
03067
03068 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
03069 if (option_verbose > 2)
03070 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
03071 transmit_response(sub, "200", req, "OK");
03072 } else {
03073 dump_queue(p->parent, p);
03074 dump_cmd_queues(p, NULL);
03075
03076 if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) {
03077 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
03078 }
03079
03080 if (!strcmp(p->name, p->parent->wcardep)) {
03081
03082 struct mgcp_endpoint *tmp_ep;
03083
03084 g = p->parent;
03085 tmp_ep = g->endpoints;
03086 while (tmp_ep) {
03087
03088 if (strcmp(tmp_ep->name, g->wcardep) != 0) {
03089 struct mgcp_subchannel *tmp_sub, *first_sub;
03090 if (option_verbose > 2) {
03091 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
03092 }
03093
03094 first_sub = tmp_ep->sub;
03095 tmp_sub = tmp_ep->sub;
03096 while (tmp_sub) {
03097 mgcp_queue_hangup(tmp_sub);
03098 tmp_sub = tmp_sub->next;
03099 if (tmp_sub == first_sub)
03100 break;
03101 }
03102 }
03103 tmp_ep = tmp_ep->next;
03104 }
03105 } else if (sub->owner) {
03106 mgcp_queue_hangup(sub);
03107 }
03108 transmit_response(sub, "200", req, "OK");
03109
03110 if (strcmp(p->name, p->parent->wcardep) != 0) {
03111 transmit_notify_request(sub, "");
03112
03113
03114
03115 transmit_audit_endpoint(p);
03116 }
03117 }
03118 } else if (!strcasecmp(req->verb, "NTFY")) {
03119
03120 transmit_response(sub, "200", req, "OK");
03121
03122 ev = get_header(req, "O");
03123 s = strchr(ev, '/');
03124 if (s) ev = s + 1;
03125 ast_log(LOG_DEBUG, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
03126
03127 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
03128 transmit_notify_request(sub, p->curtone);
03129 }
03130 if (!strcasecmp(ev, "hd")) {
03131 p->hookstate = MGCP_OFFHOOK;
03132 sub->cxmode = MGCP_CX_SENDRECV;
03133 handle_hd_hf(sub, ev);
03134 } else if (!strcasecmp(ev, "hf")) {
03135
03136
03137
03138 if (p->hookstate != MGCP_OFFHOOK) {
03139
03140
03141 return -1;
03142 }
03143
03144 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
03145 return -1;
03146
03147 if (p->callwaiting || p->transfer || p->threewaycalling) {
03148 if (option_verbose > 2) {
03149 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);
03150 }
03151 p->sub = p->sub->next;
03152
03153
03154 if (!sub->next->owner) {
03155
03156 sub->cxmode = MGCP_CX_MUTE;
03157 if (option_verbose > 2) {
03158 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03159 }
03160 transmit_modify_request(sub);
03161 if (sub->owner && ast_bridged_channel(sub->owner))
03162 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03163 sub->next->cxmode = MGCP_CX_RECVONLY;
03164 handle_hd_hf(sub->next, ev);
03165 } else if (sub->owner && sub->next->owner) {
03166
03167 if ((!sub->outgoing) && (!sub->next->outgoing)) {
03168
03169 if (option_verbose > 2) {
03170 ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n",
03171 sub->id, sub->next->id, p->name, p->parent->name);
03172 }
03173 sub->cxmode = MGCP_CX_CONF;
03174 sub->next->cxmode = MGCP_CX_CONF;
03175 if (ast_bridged_channel(sub->next->owner))
03176 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD);
03177 transmit_modify_request(sub);
03178 transmit_modify_request(sub->next);
03179 } else {
03180
03181
03182
03183 if (option_verbose > 2) {
03184 ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
03185 sub->id, sub->next->id, p->name, p->parent->name);
03186 }
03187 sub->cxmode = MGCP_CX_MUTE;
03188 if (option_verbose > 2) {
03189 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03190 }
03191 transmit_modify_request(sub);
03192 if (ast_bridged_channel(sub->owner))
03193 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03194
03195 if (ast_bridged_channel(sub->next->owner))
03196 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD);
03197
03198 handle_hd_hf(sub->next, ev);
03199 }
03200 } else {
03201
03202 if (sub->owner) {
03203 p->sub = sub;
03204 } else if (sub->next->owner) {
03205 p->sub = sub->next;
03206 } else {
03207
03208
03209 return -1;
03210 }
03211 if (ast_bridged_channel(p->sub->owner))
03212 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD);
03213 p->sub->cxmode = MGCP_CX_SENDRECV;
03214 transmit_modify_request(p->sub);
03215 }
03216 } else {
03217 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
03218 p->name, p->parent->name);
03219 }
03220 } else if (!strcasecmp(ev, "hu")) {
03221 p->hookstate = MGCP_ONHOOK;
03222 sub->cxmode = MGCP_CX_RECVONLY;
03223 ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
03224
03225
03226
03227
03228
03229 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
03230
03231
03232 ast_mutex_lock(&p->sub->next->lock);
03233 res = attempt_transfer(p);
03234 if (res < 0) {
03235 if (p->sub->next->owner) {
03236 sub->next->alreadygone = 1;
03237 mgcp_queue_hangup(sub->next);
03238 }
03239 } else if (res) {
03240 ast_log(LOG_WARNING, "Transfer attempt failed\n");
03241 ast_mutex_unlock(&p->sub->next->lock);
03242 return -1;
03243 }
03244 ast_mutex_unlock(&p->sub->next->lock);
03245 } else {
03246
03247
03248 if (sub->owner) {
03249 sub->alreadygone = 1;
03250 mgcp_queue_hangup(sub);
03251 } else {
03252
03253 if (option_verbose > 2) {
03254 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
03255 p->name, p->parent->name, sub->id);
03256 }
03257
03258
03259
03260 transmit_connection_del(sub);
03261 }
03262 }
03263 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
03264 p->hidecallerid = 0;
03265 if (p->hascallwaiting && !p->callwaiting) {
03266 if (option_verbose > 2)
03267 ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
03268 p->callwaiting = -1;
03269 }
03270 if (has_voicemail(p)) {
03271 if (option_verbose > 2) {
03272 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
03273 }
03274 transmit_notify_request(sub, "L/vmwi(+)");
03275 } else {
03276 if (option_verbose > 2) {
03277 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
03278 }
03279 transmit_notify_request(sub, "L/vmwi(-)");
03280 }
03281 }
03282 } else if ((strlen(ev) == 1) &&
03283 (((ev[0] >= '0') && (ev[0] <= '9')) ||
03284 ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
03285 (ev[0] == '*') || (ev[0] == '#'))) {
03286 if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) {
03287 f.frametype = AST_FRAME_DTMF;
03288 f.subclass = ev[0];
03289 f.src = "mgcp";
03290
03291 mgcp_queue_frame(sub, &f);
03292 ast_mutex_lock(&sub->next->lock);
03293 if (sub->next->owner)
03294 mgcp_queue_frame(sub->next, &f);
03295 ast_mutex_unlock(&sub->next->lock);
03296 if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
03297 memset(p->curtone, 0, sizeof(p->curtone));
03298 }
03299 } else {
03300 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
03301 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
03302 }
03303 } else if (!strcasecmp(ev, "T")) {
03304
03305 } else if (!strcasecmp(ev, "ping")) {
03306
03307 } else {
03308 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
03309 }
03310 } else {
03311 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
03312 transmit_response(sub, "510", req, "Unknown verb");
03313 }
03314 return 0;
03315 }
03316
03317 static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
03318 {
03319 int seqno=0;
03320 time_t now;
03321 struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
03322 time(&now);
03323 if (sscanf(req->identifier, "%30d", &seqno) != 1)
03324 seqno = 0;
03325 cur = sub->parent->parent->responses;
03326 while(cur) {
03327 next = cur->next;
03328 if (now - cur->whensent > RESPONSE_TIMEOUT) {
03329
03330 if (prev)
03331 prev->next = next;
03332 else
03333 sub->parent->parent->responses = next;
03334 free(cur);
03335 } else {
03336 if (seqno == cur->seqno)
03337 answer = cur;
03338 prev = cur;
03339 }
03340 cur = next;
03341 }
03342 if (answer) {
03343 resend_response(sub, answer);
03344 return 1;
03345 }
03346 return 0;
03347 }
03348
03349 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
03350 {
03351 struct mgcp_request req;
03352 struct sockaddr_in sin;
03353 struct mgcp_subchannel *sub;
03354 int res;
03355 socklen_t len;
03356 int result;
03357 int ident;
03358 len = sizeof(sin);
03359 memset(&req, 0, sizeof(req));
03360 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03361 if (res < 0) {
03362 if (errno != ECONNREFUSED)
03363 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03364 return 1;
03365 }
03366 req.data[res] = '\0';
03367 req.len = res;
03368 if (mgcpdebug) {
03369 ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
03370 }
03371 parse(&req);
03372 if (req.headers < 1) {
03373
03374 return 1;
03375 }
03376 if (ast_strlen_zero(req.identifier)) {
03377 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
03378 return 1;
03379 }
03380
03381 if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) {
03382
03383 sub = find_subchannel_and_lock(NULL, ident, &sin);
03384 if (sub) {
03385 struct mgcp_gateway *gw = sub->parent->parent;
03386 struct mgcp_message *cur, *prev;
03387
03388 ast_mutex_unlock(&sub->lock);
03389 ast_mutex_lock(&gw->msgs_lock);
03390 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03391 if (cur->seqno == ident) {
03392 ast_log(LOG_DEBUG, "Got response back on transaction %d\n", ident);
03393 if (prev)
03394 prev->next = cur->next;
03395 else
03396 gw->msgs = cur->next;
03397 break;
03398 }
03399 }
03400
03401
03402 if (!gw->msgs) {
03403 AST_SCHED_DEL(sched, gw->retransid);
03404 }
03405
03406 ast_mutex_unlock(&gw->msgs_lock);
03407 if (cur) {
03408 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03409 free(cur);
03410 return 1;
03411 }
03412
03413 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
03414 gw->name, ident);
03415 }
03416 } else {
03417 if (ast_strlen_zero(req.endpoint) ||
03418 ast_strlen_zero(req.version) ||
03419 ast_strlen_zero(req.verb)) {
03420 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03421 return 1;
03422 }
03423
03424 sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03425 if (sub) {
03426
03427 if (!find_and_retrans(sub, &req))
03428
03429 handle_request(sub, &req, &sin);
03430 ast_mutex_unlock(&sub->lock);
03431 }
03432 }
03433 return 1;
03434 }
03435
03436 static int *mgcpsock_read_id = NULL;
03437
03438 static void *do_monitor(void *data)
03439 {
03440 int res;
03441 int reloading;
03442
03443
03444
03445
03446
03447 if (mgcpsock > -1)
03448 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03449
03450
03451
03452
03453 for(;;) {
03454
03455 ast_mutex_lock(&mgcp_reload_lock);
03456 reloading = mgcp_reloading;
03457 mgcp_reloading = 0;
03458 ast_mutex_unlock(&mgcp_reload_lock);
03459 if (reloading) {
03460 if (option_verbose > 0)
03461 ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n");
03462 mgcp_do_reload();
03463
03464 if (mgcpsock > -1)
03465 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03466 }
03467
03468
03469
03470
03471 ast_mutex_lock(&monlock);
03472
03473 ast_mutex_lock(&netlock);
03474
03475 #if 0
03476
03477
03478
03479 lastpass = thispass;
03480 thispass = time(NULL);
03481 g = gateways;
03482 while(g) {
03483 if (thispass != lastpass) {
03484 e = g->endpoints;
03485 while(e) {
03486 if (e->type == TYPE_LINE) {
03487 res = has_voicemail(e);
03488 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
03489 if (res) {
03490 transmit_notify_request(e, "L/vmwi(+)");
03491 } else {
03492 transmit_notify_request(e, "L/vmwi(-)");
03493 }
03494 e->msgstate = res;
03495 e->onhooktime = thispass;
03496 }
03497 }
03498 e = e->next;
03499 }
03500 }
03501 g = g->next;
03502 }
03503 #endif
03504
03505 ast_mutex_unlock(&netlock);
03506
03507 ast_mutex_unlock(&monlock);
03508 pthread_testcancel();
03509
03510 res = ast_sched_wait(sched);
03511
03512 if ((res < 0) || (res > 1000))
03513 res = 1000;
03514 res = ast_io_wait(io, res);
03515 ast_mutex_lock(&monlock);
03516 if (res >= 0)
03517 ast_sched_runq(sched);
03518 ast_mutex_unlock(&monlock);
03519 }
03520
03521 return NULL;
03522 }
03523
03524 static int restart_monitor(void)
03525 {
03526
03527 if (monitor_thread == AST_PTHREADT_STOP)
03528 return 0;
03529 if (ast_mutex_lock(&monlock)) {
03530 ast_log(LOG_WARNING, "Unable to lock monitor\n");
03531 return -1;
03532 }
03533 if (monitor_thread == pthread_self()) {
03534 ast_mutex_unlock(&monlock);
03535 ast_log(LOG_WARNING, "Cannot kill myself\n");
03536 return -1;
03537 }
03538 if (monitor_thread != AST_PTHREADT_NULL) {
03539
03540 pthread_kill(monitor_thread, SIGURG);
03541 } else {
03542
03543 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03544 ast_mutex_unlock(&monlock);
03545 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03546 return -1;
03547 }
03548 }
03549 ast_mutex_unlock(&monlock);
03550 return 0;
03551 }
03552
03553 static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause)
03554 {
03555 int oldformat;
03556 struct mgcp_subchannel *sub;
03557 struct ast_channel *tmpc = NULL;
03558 char tmp[256];
03559 char *dest = data;
03560
03561 oldformat = format;
03562 format &= capability;
03563 if (!format) {
03564 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03565 return NULL;
03566 }
03567 ast_copy_string(tmp, dest, sizeof(tmp));
03568 if (ast_strlen_zero(tmp)) {
03569 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03570 return NULL;
03571 }
03572 sub = find_subchannel_and_lock(tmp, 0, NULL);
03573 if (!sub) {
03574 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03575 *cause = AST_CAUSE_UNREGISTERED;
03576 return NULL;
03577 }
03578
03579 if (option_verbose > 2) {
03580 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
03581 ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
03582 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03583 }
03584
03585 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03586 ((!sub->parent->callwaiting) && (sub->owner)) ||
03587 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03588 if (sub->parent->hookstate == MGCP_ONHOOK) {
03589 if (has_voicemail(sub->parent)) {
03590 transmit_notify_request(sub,"L/vmwi(+)");
03591 } else {
03592 transmit_notify_request(sub,"L/vmwi(-)");
03593 }
03594 }
03595 *cause = AST_CAUSE_BUSY;
03596 ast_mutex_unlock(&sub->lock);
03597 return NULL;
03598 }
03599 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
03600 ast_mutex_unlock(&sub->lock);
03601 if (!tmpc)
03602 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03603 restart_monitor();
03604 return tmpc;
03605 }
03606
03607
03608
03609 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
03610 {
03611 struct mgcp_gateway *gw;
03612 struct mgcp_endpoint *e;
03613 struct mgcp_subchannel *sub;
03614
03615 int i=0, y=0;
03616 int gw_reload = 0;
03617 int ep_reload = 0;
03618 canreinvite = CANREINVITE;
03619
03620
03621 gw = gateways;
03622 while (gw) {
03623 if (!strcasecmp(cat, gw->name)) {
03624
03625 gw->delme = 0;
03626 gw_reload = 1;
03627 break;
03628 }
03629 gw = gw->next;
03630 }
03631
03632 if (!gw)
03633 gw = malloc(sizeof(struct mgcp_gateway));
03634
03635 if (gw) {
03636 if (!gw_reload) {
03637 memset(gw, 0, sizeof(struct mgcp_gateway));
03638 gw->expire = -1;
03639 gw->retransid = -1;
03640 ast_mutex_init(&gw->msgs_lock);
03641 ast_copy_string(gw->name, cat, sizeof(gw->name));
03642
03643 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
03644 gw->isnamedottedip = 1;
03645 }
03646 while(v) {
03647 if (!strcasecmp(v->name, "host")) {
03648 if (!strcasecmp(v->value, "dynamic")) {
03649
03650 gw->dynamic = 1;
03651 memset(&gw->addr.sin_addr, 0, 4);
03652 if (gw->addr.sin_port) {
03653
03654 gw->defaddr.sin_port = gw->addr.sin_port;
03655 gw->addr.sin_port = 0;
03656 }
03657 } else {
03658
03659 AST_SCHED_DEL(sched, gw->expire);
03660 gw->dynamic = 0;
03661 if (ast_get_ip(&gw->addr, v->value)) {
03662 if (!gw_reload) {
03663 ast_mutex_destroy(&gw->msgs_lock);
03664 free(gw);
03665 }
03666 return NULL;
03667 }
03668 }
03669 } else if (!strcasecmp(v->name, "defaultip")) {
03670 if (ast_get_ip(&gw->defaddr, v->value)) {
03671 if (!gw_reload) {
03672 ast_mutex_destroy(&gw->msgs_lock);
03673 free(gw);
03674 }
03675 return NULL;
03676 }
03677 } else if (!strcasecmp(v->name, "permit") ||
03678 !strcasecmp(v->name, "deny")) {
03679 gw->ha = ast_append_ha(v->name, v->value, gw->ha);
03680 } else if (!strcasecmp(v->name, "port")) {
03681 gw->addr.sin_port = htons(atoi(v->value));
03682 } else if (!strcasecmp(v->name, "context")) {
03683 ast_copy_string(context, v->value, sizeof(context));
03684 } else if (!strcasecmp(v->name, "dtmfmode")) {
03685 if (!strcasecmp(v->value, "inband"))
03686 dtmfmode = MGCP_DTMF_INBAND;
03687 else if (!strcasecmp(v->value, "rfc2833"))
03688 dtmfmode = MGCP_DTMF_RFC2833;
03689 else if (!strcasecmp(v->value, "hybrid"))
03690 dtmfmode = MGCP_DTMF_HYBRID;
03691 else if (!strcasecmp(v->value, "none"))
03692 dtmfmode = 0;
03693 else
03694 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
03695 } else if (!strcasecmp(v->name, "nat")) {
03696 nat = ast_true(v->value);
03697 } else if (!strcasecmp(v->name, "callerid")) {
03698 if (!strcasecmp(v->value, "asreceived")) {
03699 cid_num[0] = '\0';
03700 cid_name[0] = '\0';
03701 } else {
03702 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
03703 }
03704 } else if (!strcasecmp(v->name, "language")) {
03705 ast_copy_string(language, v->value, sizeof(language));
03706 } else if (!strcasecmp(v->name, "accountcode")) {
03707 ast_copy_string(accountcode, v->value, sizeof(accountcode));
03708 } else if (!strcasecmp(v->name, "amaflags")) {
03709 y = ast_cdr_amaflags2int(v->value);
03710 if (y < 0) {
03711 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
03712 } else {
03713 amaflags = y;
03714 }
03715 } else if (!strcasecmp(v->name, "musiconhold")) {
03716 ast_copy_string(musicclass, v->value, sizeof(musicclass));
03717 } else if (!strcasecmp(v->name, "callgroup")) {
03718 cur_callergroup = ast_get_group(v->value);
03719 } else if (!strcasecmp(v->name, "pickupgroup")) {
03720 cur_pickupgroup = ast_get_group(v->value);
03721 } else if (!strcasecmp(v->name, "immediate")) {
03722 immediate = ast_true(v->value);
03723 } else if (!strcasecmp(v->name, "cancallforward")) {
03724 cancallforward = ast_true(v->value);
03725 } else if (!strcasecmp(v->name, "singlepath")) {
03726 singlepath = ast_true(v->value);
03727 } else if (!strcasecmp(v->name, "canreinvite")) {
03728 canreinvite = ast_true(v->value);
03729 } else if (!strcasecmp(v->name, "mailbox")) {
03730 ast_copy_string(mailbox, v->value, sizeof(mailbox));
03731 } else if (!strcasecmp(v->name, "hasvoicemail")) {
03732 if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
03733 ast_copy_string(mailbox, gw->name, sizeof(mailbox));
03734 }
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, "%30d", &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, "%30d", &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 );