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