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