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