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: 118953 $")
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_update_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 %d 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, "%d%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: %u %[^/]/", &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, "%d", &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, "%d", &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, "%d", &result) && sscanf(req.identifier, "%d", &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, "adsi")) {
03735 adsi = ast_true(v->value);
03736 } else if (!strcasecmp(v->name, "callreturn")) {
03737 callreturn = ast_true(v->value);
03738 } else if (!strcasecmp(v->name, "callwaiting")) {
03739 callwaiting = ast_true(v->value);
03740 } else if (!strcasecmp(v->name, "slowsequence")) {
03741 slowsequence = ast_true(v->value);
03742 } else if (!strcasecmp(v->name, "transfer")) {
03743 transfer = ast_true(v->value);
03744 } else if (!strcasecmp(v->name, "threewaycalling")) {
03745 threewaycalling = ast_true(v->value);
03746 } else if (!strcasecmp(v->name, "wcardep")) {
03747
03748 e = gw->endpoints;
03749 while (e) {
03750 if (!strcasecmp(v->value, e->name)) {
03751
03752 e->delme = 0;
03753 ep_reload = 1;
03754 break;
03755 }
03756 e = e->next;
03757 }
03758
03759 if (!e) {
03760
03761 e = malloc(sizeof(struct mgcp_endpoint));
03762 ep_reload = 0;
03763 }
03764
03765 if (e) {
03766 if (!ep_reload) {
03767 memset(e, 0, sizeof(struct mgcp_endpoint));
03768 ast_mutex_init(&e->lock);
03769 ast_mutex_init(&e->rqnt_queue_lock);
03770 ast_mutex_init(&e->cmd_queue_lock);
03771 ast_copy_string(e->name, v->value, sizeof(e->name));
03772 e->needaudit = 1;
03773 }
03774 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
03775
03776 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
03777 ast_copy_string(e->context, context, sizeof(e->context));
03778 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
03779 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
03780 ast_copy_string(e->language, language, sizeof(e->language));
03781 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
03782 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
03783 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
03784 e->msgstate = -1;
03785 e->amaflags = amaflags;
03786 e->capability = capability;
03787 e->parent = gw;
03788 e->dtmfmode = dtmfmode;
03789 if (!ep_reload && e->sub && e->sub->rtp)
03790 e->dtmfmode |= MGCP_DTMF_INBAND;
03791 e->adsi = adsi;
03792 e->type = TYPE_LINE;
03793 e->immediate = immediate;
03794 e->callgroup=cur_callergroup;
03795 e->pickupgroup=cur_pickupgroup;
03796 e->callreturn = callreturn;
03797 e->cancallforward = cancallforward;
03798 e->singlepath = singlepath;
03799 e->canreinvite = canreinvite;
03800 e->callwaiting = callwaiting;
03801 e->hascallwaiting = callwaiting;
03802 e->slowsequence = slowsequence;
03803 e->transfer = transfer;
03804 e->threewaycalling = threewaycalling;
03805 e->onhooktime = time(NULL);
03806
03807 e->hookstate = MGCP_ONHOOK;
03808 if (!ep_reload) {
03809
03810 for (i = 0; i < MAX_SUBS; i++) {
03811 sub = malloc(sizeof(struct mgcp_subchannel));
03812 if (sub) {
03813 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03814 memset(sub, 0, sizeof(struct mgcp_subchannel));
03815 ast_mutex_init(&sub->lock);
03816 ast_mutex_init(&sub->cx_queue_lock);
03817 sub->parent = e;
03818 sub->id = i;
03819 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
03820
03821 sub->cxmode = MGCP_CX_INACTIVE;
03822 sub->nat = nat;
03823 sub->next = e->sub;
03824 e->sub = sub;
03825 } else {
03826
03827 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
03828 return NULL;
03829 }
03830 }
03831
03832 sub = e->sub;
03833
03834 while(sub->next){
03835 sub = sub->next;
03836 }
03837
03838 sub->next = e->sub;
03839
03840 e->next = gw->endpoints;
03841 gw->endpoints = e;
03842 }
03843 }
03844 } else if (!strcasecmp(v->name, "trunk") ||
03845 !strcasecmp(v->name, "line")) {
03846
03847
03848 e = gw->endpoints;
03849 while (e) {
03850 if (!strcasecmp(v->value, e->name)) {
03851
03852 e->delme = 0;
03853 ep_reload = 1;
03854 break;
03855 }
03856 e = e->next;
03857 }
03858
03859 if (!e) {
03860 e = malloc(sizeof(struct mgcp_endpoint));
03861 ep_reload = 0;
03862 }
03863
03864 if (e) {
03865 if (!ep_reload) {
03866 memset(e, 0, sizeof(struct mgcp_endpoint));
03867 ast_mutex_init(&e->lock);
03868 ast_mutex_init(&e->rqnt_queue_lock);
03869 ast_mutex_init(&e->cmd_queue_lock);
03870 ast_copy_string(e->name, v->value, sizeof(e->name));
03871 e->needaudit = 1;
03872 }
03873
03874 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
03875 ast_copy_string(e->context, context, sizeof(e->context));
03876 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
03877 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
03878 ast_copy_string(e->language, language, sizeof(e->language));
03879 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
03880 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
03881 if (!ast_strlen_zero(mailbox)) {
03882 ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
03883 }
03884 if (!ep_reload) {
03885
03886 e->msgstate = -1;
03887 e->parent = gw;
03888 }
03889 e->amaflags = amaflags;
03890 e->capability = capability;
03891 e->dtmfmode = dtmfmode;
03892 e->adsi = adsi;
03893 if (!strcasecmp(v->name, "trunk"))
03894 e->type = TYPE_TRUNK;
03895 else
03896 e->type = TYPE_LINE;
03897
03898 e->immediate = immediate;
03899 e->callgroup=cur_callergroup;
03900 e->pickupgroup=cur_pickupgroup;
03901 e->callreturn = callreturn;
03902 e->cancallforward = cancallforward;
03903 e->canreinvite = canreinvite;
03904 e->singlepath = singlepath;
03905 e->callwaiting = callwaiting;
03906 e->hascallwaiting = callwaiting;
03907 e->slowsequence = slowsequence;
03908 e->transfer = transfer;
03909 e->threewaycalling = threewaycalling;
03910 if (!ep_reload) {
03911 e->onhooktime = time(NULL);
03912
03913 e->hookstate = MGCP_ONHOOK;
03914 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
03915 }
03916
03917 for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
03918 if (!ep_reload) {
03919 sub = malloc(sizeof(struct mgcp_subchannel));
03920 } else {
03921 if (!sub)
03922 sub = e->sub;
03923 else
03924 sub = sub->next;
03925 }
03926
03927 if (sub) {
03928 if (!ep_reload) {
03929 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03930 memset(sub, 0, sizeof(struct mgcp_subchannel));
03931 ast_mutex_init(&sub->lock);
03932 ast_mutex_init(&sub->cx_queue_lock);
03933 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
03934 sub->parent = e;
03935 sub->id = i;
03936 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
03937 sub->cxmode = MGCP_CX_INACTIVE;
03938 sub->next = e->sub;
03939 e->sub = sub;
03940 }
03941 sub->nat = nat;
03942 } else {
03943
03944 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
03945 return NULL;
03946 }
03947 }
03948 if (!ep_reload) {
03949
03950 sub = e->sub;
03951
03952 while (sub->next) {
03953 sub = sub->next;
03954 }
03955
03956 sub->next = e->sub;
03957
03958 e->next = gw->endpoints;
03959 gw->endpoints = e;
03960 }
03961 }
03962 } else
03963 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
03964 v = v->next;
03965 }
03966 }
03967 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
03968 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
03969 if (!gw_reload) {
03970 ast_mutex_destroy(&gw->msgs_lock);
03971 free(gw);
03972 }
03973 return NULL;
03974 }
03975 gw->defaddr.sin_family = AF_INET;
03976 gw->addr.sin_family = AF_INET;
03977 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port))
03978 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03979 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
03980 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03981 if (gw->addr.sin_addr.s_addr)
03982 if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip))
03983 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
03984
03985 return (gw_reload ? NULL : gw);
03986 }
03987
03988 static enum ast_rtp_get_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
03989 {
03990 struct mgcp_subchannel *sub = NULL;
03991
03992 if (!(sub = chan->tech_pvt) || !(sub->rtp))
03993 return AST_RTP_GET_FAILED;
03994
03995 *rtp = sub->rtp;
03996
03997 if (sub->parent->canreinvite)
03998 return AST_RTP_TRY_NATIVE;
03999 else
04000 return AST_RTP_TRY_PARTIAL;
04001 }
04002
04003 static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
04004 {
04005
04006 struct mgcp_subchannel *sub;
04007 sub = chan->tech_pvt;
04008 if (sub && !sub->alreadygone) {
04009 transmit_modify_with_sdp(sub, rtp, codecs);
04010 return 0;
04011 }
04012 return -1;
04013 }
04014
04015 static struct ast_rtp_protocol mgcp_rtp = {
04016 .type = "MGCP",
04017 .get_rtp_info = mgcp_get_rtp_peer,
04018 .set_rtp_peer = mgcp_set_rtp_peer,
04019 };
04020
04021 static void destroy_endpoint(struct mgcp_endpoint *e)
04022 {
04023 struct mgcp_subchannel *sub = e->sub->next, *s;
04024 int i;
04025
04026 for (i = 0; i < MAX_SUBS; i++) {
04027 ast_mutex_lock(&sub->lock);
04028 if (!ast_strlen_zero(sub->cxident)) {
04029 transmit_connection_del(sub);
04030 }
04031 if (sub->rtp) {
04032 ast_rtp_destroy(sub->rtp);
04033 sub->rtp = NULL;
04034 }
04035 memset(sub->magic, 0, sizeof(sub->magic));
04036 mgcp_queue_hangup(sub);
04037 dump_cmd_queues(NULL, sub);
04038 ast_mutex_unlock(&sub->lock);
04039 sub = sub->next;
04040 }
04041
04042 if (e->dsp) {
04043 ast_dsp_free(e->dsp);
04044 }
04045
04046 dump_queue(e->parent, e);
04047 dump_cmd_queues(e, NULL);
04048
04049 sub = e->sub;
04050 for (i = 0; (i < MAX_SUBS) && sub; i++) {
04051 s = sub;
04052 sub = sub->next;
04053 ast_mutex_destroy(&s->lock);
04054 ast_mutex_destroy(&s->cx_queue_lock);
04055 free(s);
04056 }
04057 ast_mutex_destroy(&e->lock);
04058 ast_mutex_destroy(&e->rqnt_queue_lock);
04059 ast_mutex_destroy(&e->cmd_queue_lock);
04060 free(e);
04061 }
04062
04063 static void destroy_gateway(struct mgcp_gateway *g)
04064 {
04065 if (g->ha)
04066 ast_free_ha(g->ha);
04067
04068 dump_queue(g, NULL);
04069
04070 free (g);
04071 }
04072
04073 static void prune_gateways(void)
04074 {
04075 struct mgcp_gateway *g, *z, *r;
04076 struct mgcp_endpoint *e, *p, *t;
04077
04078 ast_mutex_lock(&gatelock);
04079
04080
04081 for (z = NULL, g = gateways; g;) {
04082
04083 for (p = NULL, e = g->endpoints; e; ) {
04084 if (e->delme || g->delme) {
04085 t = e;
04086 e = e->next;
04087 if (!p)
04088 g->endpoints = e;
04089 else
04090 p->next = e;
04091 destroy_endpoint(t);
04092 } else {
04093 p = e;
04094 e = e->next;
04095 }
04096 }
04097
04098 if (g->delme) {
04099 r = g;
04100 g = g->next;
04101 if (!z)
04102 gateways = g;
04103 else
04104 z->next = g;
04105
04106 destroy_gateway(r);
04107 } else {
04108 z = g;
04109 g = g->next;
04110 }
04111 }
04112
04113 ast_mutex_unlock(&gatelock);
04114 }
04115
04116 static int reload_config(void)
04117 {
04118 struct ast_config *cfg;
04119 struct ast_variable *v;
04120 struct mgcp_gateway *g;
04121 struct mgcp_endpoint *e;
04122 char *cat;
04123 struct ast_hostent ahp;
04124 struct hostent *hp;
04125 int format;
04126
04127 if (gethostname(ourhost, sizeof(ourhost)-1)) {
04128 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
04129 return 0;
04130 }
04131 cfg = ast_config_load(config);
04132
04133
04134 if (!cfg) {
04135 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
04136 return 0;
04137 }
04138 memset(&bindaddr, 0, sizeof(bindaddr));
04139 dtmfmode = 0;
04140
04141
04142 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
04143
04144 v = ast_variable_browse(cfg, "general");
04145 while (v) {
04146
04147 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
04148 v = v->next;
04149 continue;
04150 }
04151
04152
04153 if (!strcasecmp(v->name, "bindaddr")) {
04154 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04155 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04156 } else {
04157 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04158 }
04159 } else if (!strcasecmp(v->name, "allow")) {
04160 format = ast_getformatbyname(v->value);
04161 if (format < 1)
04162 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04163 else
04164 capability |= format;
04165 } else if (!strcasecmp(v->name, "disallow")) {
04166 format = ast_getformatbyname(v->value);
04167 if (format < 1)
04168 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
04169 else
04170 capability &= ~format;
04171 } else if (!strcasecmp(v->name, "tos")) {
04172 if (sscanf(v->value, "%d", &format) == 1)
04173 tos = format & 0xff;
04174 else if (!strcasecmp(v->value, "lowdelay"))
04175 tos = IPTOS_LOWDELAY;
04176 else if (!strcasecmp(v->value, "throughput"))
04177 tos = IPTOS_THROUGHPUT;
04178 else if (!strcasecmp(v->value, "reliability"))
04179 tos = IPTOS_RELIABILITY;
04180 else if (!strcasecmp(v->value, "mincost"))
04181 tos = IPTOS_MINCOST;
04182 else if (!strcasecmp(v->value, "none"))
04183 tos = 0;
04184 else
04185 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
04186 } else if (!strcasecmp(v->name, "port")) {
04187 if (sscanf(v->value, "%d", &ourport) == 1) {
04188 bindaddr.sin_port = htons(ourport);
04189 } else {
04190 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
04191 }
04192 }
04193 v = v->next;
04194 }
04195
04196
04197 ast_mutex_lock(&gatelock);
04198 g = gateways;
04199 while (g) {
04200 g->delme = 1;
04201 e = g->endpoints;
04202 while (e) {
04203 e->delme = 1;
04204 e = e->next;
04205 }
04206 g = g->next;
04207 }
04208 ast_mutex_unlock(&gatelock);
04209
04210 cat = ast_category_browse(cfg, NULL);
04211 while(cat) {
04212 if (strcasecmp(cat, "general")) {
04213 ast_mutex_lock(&gatelock);
04214 g = build_gateway(cat, ast_variable_browse(cfg, cat));
04215 if (g) {
04216 if (option_verbose > 2) {
04217 ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
04218 }
04219 g->next = gateways;
04220 gateways = g;
04221 }
04222 ast_mutex_unlock(&gatelock);
04223
04224
04225 if (monitor_thread == pthread_self()) {
04226 if (sched) ast_sched_runq(sched);
04227 if (io) ast_io_wait(io, 10);
04228 }
04229 }
04230 cat = ast_category_browse(cfg, cat);
04231 }
04232
04233
04234 prune_gateways();
04235
04236 if (ntohl(bindaddr.sin_addr.s_addr)) {
04237 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
04238 } else {
04239 hp = ast_gethostbyname(ourhost, &ahp);
04240 if (!hp) {
04241 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
04242 ast_config_destroy(cfg);
04243 return 0;
04244 }
04245 memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04246 }
04247 if (!ntohs(bindaddr.sin_port))
04248 bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
04249 bindaddr.sin_family = AF_INET;
04250 ast_mutex_lock(&netlock);
04251 if (mgcpsock > -1)
04252 close(mgcpsock);
04253
04254 if (mgcpsock_read_id != NULL)
04255 ast_io_remove(io, mgcpsock_read_id);
04256 mgcpsock_read_id = NULL;
04257
04258 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
04259 if (mgcpsock < 0) {
04260 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
04261 } else {
04262 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04263 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04264 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04265 strerror(errno));
04266 close(mgcpsock);
04267 mgcpsock = -1;
04268 } else {
04269 if (option_verbose > 1) {
04270 ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n",
04271 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04272 ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
04273 }
04274 if (setsockopt(mgcpsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))
04275 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
04276 }
04277 }
04278 ast_mutex_unlock(&netlock);
04279 ast_config_destroy(cfg);
04280
04281
04282 g = gateways;
04283 while (g) {
04284 e = g->endpoints;
04285 while (e && e->needaudit) {
04286 e->needaudit = 0;
04287 transmit_audit_endpoint(e);
04288 ast_verbose(VERBOSE_PREFIX_3 "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
04289 e = e->next;
04290 }
04291 g = g->next;
04292 }
04293
04294 return 0;
04295 }
04296
04297
04298 static int load_module(void)
04299 {
04300 if (!(sched = sched_context_create())) {
04301 ast_log(LOG_WARNING, "Unable to create schedule context\n");
04302 return AST_MODULE_LOAD_FAILURE;
04303 }
04304
04305 if (!(io = io_context_create())) {
04306 ast_log(LOG_WARNING, "Unable to create I/O context\n");
04307 sched_context_destroy(sched);
04308 return AST_MODULE_LOAD_FAILURE;
04309 }
04310
04311 if (reload_config())
04312 return AST_MODULE_LOAD_DECLINE;
04313
04314
04315 if (ast_channel_register(&mgcp_tech)) {
04316 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
04317 io_context_destroy(io);
04318 sched_context_destroy(sched);
04319 return AST_MODULE_LOAD_FAILURE;
04320 }
04321
04322 ast_rtp_proto_register(&mgcp_rtp);
04323 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04324
04325
04326 restart_monitor();
04327
04328 return AST_MODULE_LOAD_SUCCESS;
04329 }
04330
04331
04332 static int mgcp_do_reload(void)
04333 {
04334 reload_config();
04335 return 0;
04336 }
04337
04338 static int mgcp_reload(int fd, int argc, char *argv[])
04339 {
04340 static int deprecated = 0;
04341 if (!deprecated && argc > 0) {
04342 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n");
04343 deprecated = 1;
04344 }
04345
04346 ast_mutex_lock(&mgcp_reload_lock);
04347 if (mgcp_reloading) {
04348 ast_verbose("Previous mgcp reload not yet done\n");
04349 } else
04350 mgcp_reloading = 1;
04351 ast_mutex_unlock(&mgcp_reload_lock);
04352 restart_monitor();
04353 return 0;
04354 }
04355
04356 static int reload(void)
04357 {
04358 mgcp_reload(0, 0, NULL);
04359 return 0;
04360 }
04361
04362 static int unload_module(void)
04363 {
04364 struct mgcp_endpoint *e;
04365 struct mgcp_gateway *g;
04366
04367
04368 if (ast_mutex_trylock(&mgcp_reload_lock)) {
04369 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n");
04370 return -1;
04371 } else {
04372 mgcp_reloading = 1;
04373 ast_mutex_unlock(&mgcp_reload_lock);
04374 }
04375
04376
04377 ast_channel_unregister(&mgcp_tech);
04378
04379
04380 if (!ast_mutex_lock(&monlock)) {
04381 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04382 pthread_cancel(monitor_thread);
04383 pthread_kill(monitor_thread, SIGURG);
04384 pthread_join(monitor_thread, NULL);
04385 }
04386 monitor_thread = AST_PTHREADT_STOP;
04387 ast_mutex_unlock(&monlock);
04388 } else {
04389 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04390
04391 ast_channel_register(&mgcp_tech);
04392 mgcp_reloading = 0;
04393 mgcp_reload(0, 0, NULL);
04394 return -1;
04395 }
04396
04397 if (!ast_mutex_lock(&gatelock)) {
04398 for (g = gateways; g; g = g->next) {
04399 g->delme = 1;
04400 for (e = g->endpoints; e; e = e->next)
04401 e->delme = 1;
04402 }
04403
04404 prune_gateways();
04405 ast_mutex_unlock(&gatelock);
04406 } else {
04407 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
04408
04409 ast_channel_register(&mgcp_tech);
04410
04411 monitor_thread = AST_PTHREADT_NULL;
04412 mgcp_reloading = 0;
04413 mgcp_reload(0, 0, NULL);
04414 return -1;
04415 }
04416
04417 close(mgcpsock);
04418 ast_rtp_proto_unregister(&mgcp_rtp);
04419 ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04420 sched_context_destroy(sched);
04421
04422 return 0;
04423 }
04424
04425 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Media Gateway Control Protocol (MGCP)",
04426 .load = load_module,
04427 .unload = unload_module,
04428 .reload = reload,
04429 );