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: 9609 $")
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 if (!ast_strlen_zero(i->cid_num))
01432 tmp->cid.cid_num = strdup(i->cid_num);
01433 if (!ast_strlen_zero(i->cid_name))
01434 tmp->cid.cid_name = strdup(i->cid_name);
01435 if (!i->adsi)
01436 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01437 tmp->priority = 1;
01438 if (state != AST_STATE_DOWN) {
01439 if (ast_pbx_start(tmp)) {
01440 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01441 ast_hangup(tmp);
01442 tmp = NULL;
01443 }
01444 }
01445
01446 if (option_verbose > 2) {
01447 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
01448 tmp->name, ast_state2str(state));
01449 }
01450 } else {
01451 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01452 }
01453 return tmp;
01454 }
01455
01456 static char* get_sdp_by_line(char* line, char *name, int nameLen)
01457 {
01458 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01459 char* r = line + nameLen + 1;
01460 while (*r && (*r < 33)) ++r;
01461 return r;
01462 }
01463 return "";
01464 }
01465
01466 static char *get_sdp(struct mgcp_request *req, char *name)
01467 {
01468 int x;
01469 int len = strlen(name);
01470 char *r;
01471
01472 for (x=0; x<req->lines; x++) {
01473 r = get_sdp_by_line(req->line[x], name, len);
01474 if (r[0] != '\0') return r;
01475 }
01476 return "";
01477 }
01478
01479 static void sdpLineNum_iterator_init(int* iterator)
01480 {
01481 *iterator = 0;
01482 }
01483
01484 static char* get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
01485 {
01486 int len = strlen(name);
01487 char *r;
01488 while (*iterator < req->lines) {
01489 r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01490 if (r[0] != '\0') return r;
01491 }
01492 return "";
01493 }
01494
01495 static char *__get_header(struct mgcp_request *req, char *name, int *start)
01496 {
01497 int x;
01498 int len = strlen(name);
01499 char *r;
01500 for (x=*start;x<req->headers;x++) {
01501 if (!strncasecmp(req->header[x], name, len) &&
01502 (req->header[x][len] == ':')) {
01503 r = req->header[x] + len + 1;
01504 while(*r && (*r < 33))
01505 r++;
01506 *start = x+1;
01507 return r;
01508 }
01509 }
01510
01511 return "";
01512 }
01513
01514 static char *get_header(struct mgcp_request *req, char *name)
01515 {
01516 int start = 0;
01517 return __get_header(req, name, &start);
01518 }
01519
01520
01521 static char *get_csv(char *c, int *len, char **next)
01522 {
01523 char *s;
01524
01525 *next = NULL, *len = 0;
01526 if (!c) return NULL;
01527
01528 while (*c && (*c < 33 || *c == ','))
01529 c++;
01530
01531 s = c;
01532 while (*c && (*c >= 33 && *c != ','))
01533 c++, (*len)++;
01534 *next = c;
01535
01536 if (*len == 0)
01537 s = NULL, *next = NULL;
01538
01539 return s;
01540 }
01541
01542 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
01543 {
01544 struct mgcp_endpoint *p = NULL;
01545 struct mgcp_subchannel *sub = NULL;
01546 struct mgcp_gateway *g;
01547 char iabuf[INET_ADDRSTRLEN];
01548 char tmp[256] = "";
01549 char *at = NULL, *c;
01550 int found = 0;
01551 if (name) {
01552 strncpy(tmp, name, sizeof(tmp) - 1);
01553 at = strchr(tmp, '@');
01554 if (!at) {
01555 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01556 return NULL;
01557 }
01558 *at = '\0';
01559 at++;
01560 }
01561 ast_mutex_lock(&gatelock);
01562 if (at && (at[0] == '[')) {
01563 at++;
01564 c = strrchr(at, ']');
01565 if (c)
01566 *c = '\0';
01567 }
01568 g = gateways;
01569 while(g) {
01570 if ((!name || !strcasecmp(g->name, at)) &&
01571 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01572
01573 if (sin && g->dynamic && name) {
01574 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01575 (g->addr.sin_port != sin->sin_port)) {
01576 memcpy(&g->addr, sin, sizeof(g->addr));
01577 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
01578 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01579 if (option_verbose > 2)
01580 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));
01581 }
01582 }
01583
01584 else if (name) {
01585 if (strcasecmp(g->name, at)) {
01586 g = g->next;
01587 continue;
01588 }
01589 }
01590
01591 else if (!name && sin) {
01592 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01593 (g->addr.sin_port != sin->sin_port)) {
01594 g = g->next;
01595 continue;
01596 }
01597 } else {
01598 g = g->next;
01599 continue;
01600 }
01601
01602 p = g->endpoints;
01603 while(p) {
01604 if (option_debug)
01605 ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n",
01606 p->name, g->name);
01607 if (msgid) {
01608 #if 0
01609 sub = p->sub;
01610 do {
01611 if (option_debug)
01612 ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
01613 p->name, g->name, sub->id, msgid);
01614 if (sub->lastout == msgid) {
01615 if (option_debug)
01616 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
01617 sub->id, msgid, sub->lastout);
01618 found = 1;
01619 break;
01620 }
01621 sub = sub->next;
01622 } while (sub != p->sub);
01623 if (found) {
01624 break;
01625 }
01626 #endif
01627
01628 sub = p->sub;
01629 found = 1;
01630
01631 break;
01632 } else if (name && !strcasecmp(p->name, tmp)) {
01633 ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
01634 p->name, g->name, p->sub->id);
01635 sub = p->sub;
01636 found = 1;
01637 break;
01638 }
01639 p = p->next;
01640 }
01641 if (sub && found) {
01642 ast_mutex_lock(&sub->lock);
01643 break;
01644 }
01645 }
01646 g = g->next;
01647 }
01648 ast_mutex_unlock(&gatelock);
01649 if (!sub) {
01650 if (name) {
01651 if (g)
01652 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01653 else
01654 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01655 }
01656 }
01657 return sub;
01658 }
01659
01660 static void parse(struct mgcp_request *req)
01661 {
01662
01663 char *c;
01664 int f = 0;
01665 c = req->data;
01666
01667
01668 req->header[f] = c;
01669 while(*c) {
01670 if (*c == '\n') {
01671
01672 *c = 0;
01673 #if 0
01674 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
01675 #endif
01676 if (ast_strlen_zero(req->header[f])) {
01677
01678 c++;
01679 break;
01680 }
01681 if (f >= MGCP_MAX_HEADERS - 1) {
01682 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01683 } else
01684 f++;
01685 req->header[f] = c + 1;
01686 } else if (*c == '\r') {
01687
01688 *c = 0;
01689 }
01690 c++;
01691 }
01692
01693 if (!ast_strlen_zero(req->header[f]))
01694 f++;
01695 req->headers = f;
01696
01697 f = 0;
01698 req->line[f] = c;
01699 while(*c) {
01700 if (*c == '\n') {
01701
01702 *c = 0;
01703 #if 0
01704 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
01705 #endif
01706 if (f >= MGCP_MAX_LINES - 1) {
01707 ast_log(LOG_WARNING, "Too many SDP lines...\n");
01708 } else
01709 f++;
01710 req->line[f] = c + 1;
01711 } else if (*c == '\r') {
01712
01713 *c = 0;
01714 }
01715 c++;
01716 }
01717
01718 if (!ast_strlen_zero(req->line[f]))
01719 f++;
01720 req->lines = f;
01721
01722 c = req->header[0];
01723 while(*c && *c < 33) c++;
01724
01725 req->verb = c;
01726 while(*c && (*c > 32)) c++;
01727 if (*c) {
01728 *c = '\0';
01729 c++;
01730 while(*c && (*c < 33)) c++;
01731 req->identifier = c;
01732 while(*c && (*c > 32)) c++;
01733 if (*c) {
01734 *c = '\0';
01735 c++;
01736 while(*c && (*c < 33)) c++;
01737 req->endpoint = c;
01738 while(*c && (*c > 32)) c++;
01739 if (*c) {
01740 *c = '\0';
01741 c++;
01742 while(*c && (*c < 33)) c++;
01743 req->version = c;
01744 while(*c && (*c > 32)) c++;
01745 while(*c && (*c < 33)) c++;
01746 while(*c && (*c > 32)) c++;
01747 *c = '\0';
01748 }
01749 }
01750 }
01751
01752 if (mgcpdebug) {
01753 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01754 req->verb, req->identifier, req->endpoint, req->version);
01755 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
01756 }
01757 if (*c)
01758 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01759 }
01760
01761 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
01762 {
01763 char *m;
01764 char *c;
01765 char *a;
01766 char host[258];
01767 int len;
01768 int portno;
01769 int peercapability, peerNonCodecCapability;
01770 struct sockaddr_in sin;
01771 char *codecs;
01772 struct ast_hostent ahp; struct hostent *hp;
01773 int codec, codec_count=0;
01774 int iterator;
01775 struct mgcp_endpoint *p = sub->parent;
01776
01777
01778 m = get_sdp(req, "m");
01779 c = get_sdp(req, "c");
01780 if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
01781 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
01782 return -1;
01783 }
01784 if (sscanf(c, "IN IP4 %256s", host) != 1) {
01785 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
01786 return -1;
01787 }
01788
01789 hp = ast_gethostbyname(host, &ahp);
01790 if (!hp) {
01791 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
01792 return -1;
01793 }
01794 if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
01795 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
01796 return -1;
01797 }
01798 sin.sin_family = AF_INET;
01799 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01800 sin.sin_port = htons(portno);
01801 ast_rtp_set_peer(sub->rtp, &sin);
01802 #if 0
01803 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
01804 #endif
01805
01806 ast_rtp_pt_clear(sub->rtp);
01807 codecs = ast_strdupa(m + len);
01808 while (!ast_strlen_zero(codecs)) {
01809 if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
01810 if (codec_count)
01811 break;
01812 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
01813 return -1;
01814 }
01815 ast_rtp_set_m_type(sub->rtp, codec);
01816 codec_count++;
01817 codecs += len;
01818 }
01819
01820
01821
01822 sdpLineNum_iterator_init(&iterator);
01823 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
01824 char* mimeSubtype = ast_strdupa(a);
01825 if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
01826 continue;
01827
01828 ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype);
01829 }
01830
01831
01832 ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
01833 p->capability = capability & peercapability;
01834 if (mgcpdebug) {
01835 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
01836 capability, peercapability, p->capability);
01837 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
01838 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
01839 }
01840 if (!p->capability) {
01841 ast_log(LOG_WARNING, "No compatible codecs!\n");
01842 return -1;
01843 }
01844 return 0;
01845 }
01846
01847 static int add_header(struct mgcp_request *req, char *var, char *value)
01848 {
01849 if (req->len >= sizeof(req->data) - 4) {
01850 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01851 return -1;
01852 }
01853 if (req->lines) {
01854 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
01855 return -1;
01856 }
01857 req->header[req->headers] = req->data + req->len;
01858 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
01859 req->len += strlen(req->header[req->headers]);
01860 if (req->headers < MGCP_MAX_HEADERS)
01861 req->headers++;
01862 else {
01863 ast_log(LOG_WARNING, "Out of header space\n");
01864 return -1;
01865 }
01866 return 0;
01867 }
01868
01869 static int add_line(struct mgcp_request *req, char *line)
01870 {
01871 if (req->len >= sizeof(req->data) - 4) {
01872 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01873 return -1;
01874 }
01875 if (!req->lines) {
01876
01877 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
01878 req->len += strlen(req->data + req->len);
01879 }
01880 req->line[req->lines] = req->data + req->len;
01881 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
01882 req->len += strlen(req->line[req->lines]);
01883 if (req->lines < MGCP_MAX_LINES)
01884 req->lines++;
01885 else {
01886 ast_log(LOG_WARNING, "Out of line space\n");
01887 return -1;
01888 }
01889 return 0;
01890 }
01891
01892 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
01893 {
01894
01895 if (req->headers || req->len) {
01896 ast_log(LOG_WARNING, "Request already initialized?!?\n");
01897 return -1;
01898 }
01899 req->header[req->headers] = req->data + req->len;
01900 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
01901 req->len += strlen(req->header[req->headers]);
01902 if (req->headers < MGCP_MAX_HEADERS)
01903 req->headers++;
01904 else
01905 ast_log(LOG_WARNING, "Out of header space\n");
01906 return 0;
01907 }
01908
01909 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
01910 {
01911
01912 if (req->headers || req->len) {
01913 ast_log(LOG_WARNING, "Request already initialized?!?\n");
01914 return -1;
01915 }
01916 req->header[req->headers] = req->data + req->len;
01917
01918 if (p->parent->isnamedottedip)
01919 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);
01920 else
01921 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);
01922 req->len += strlen(req->header[req->headers]);
01923 if (req->headers < MGCP_MAX_HEADERS)
01924 req->headers++;
01925 else
01926 ast_log(LOG_WARNING, "Out of header space\n");
01927 return 0;
01928 }
01929
01930
01931 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
01932 {
01933 memset(resp, 0, sizeof(*resp));
01934 init_resp(resp, msg, req, msgrest);
01935 return 0;
01936 }
01937
01938 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
01939 {
01940 memset(req, 0, sizeof(struct mgcp_request));
01941 oseq++;
01942 if (oseq > 999999999)
01943 oseq = 1;
01944 init_req(p, req, verb);
01945 return 0;
01946 }
01947
01948 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
01949 {
01950 struct mgcp_request resp;
01951 struct mgcp_endpoint *p = sub->parent;
01952 struct mgcp_response *mgr;
01953
01954 respprep(&resp, p, msg, req, msgrest);
01955 mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
01956 if (mgr) {
01957
01958 memset(mgr, 0, sizeof(struct mgcp_response));
01959 sscanf(req->identifier, "%d", &mgr->seqno);
01960 time(&mgr->whensent);
01961 mgr->len = resp.len;
01962 memcpy(mgr->buf, resp.data, resp.len);
01963 mgr->buf[resp.len] = '\0';
01964 mgr->next = p->parent->responses;
01965 p->parent->responses = mgr;
01966 }
01967 return send_response(sub, &resp);
01968 }
01969
01970
01971 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
01972 {
01973 int len;
01974 int codec;
01975 char costr[80];
01976 struct sockaddr_in sin;
01977 char v[256];
01978 char s[256];
01979 char o[256];
01980 char c[256];
01981 char t[256];
01982 char m[256] = "";
01983 char a[1024] = "";
01984 char iabuf[INET_ADDRSTRLEN];
01985 int x;
01986 struct sockaddr_in dest;
01987 struct mgcp_endpoint *p = sub->parent;
01988
01989
01990 len = 0;
01991 if (!sub->rtp) {
01992 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
01993 return -1;
01994 }
01995 ast_rtp_get_us(sub->rtp, &sin);
01996 if (rtp) {
01997 ast_rtp_get_peer(rtp, &dest);
01998 } else {
01999 if (sub->tmpdest.sin_addr.s_addr) {
02000 dest.sin_addr = sub->tmpdest.sin_addr;
02001 dest.sin_port = sub->tmpdest.sin_port;
02002
02003 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
02004 } else {
02005 dest.sin_addr = p->parent->ourip;
02006 dest.sin_port = sin.sin_port;
02007 }
02008 }
02009 if (mgcpdebug) {
02010 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->ourip), ntohs(sin.sin_port));
02011 }
02012 snprintf(v, sizeof(v), "v=0\r\n");
02013 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), ast_inet_ntoa(iabuf, sizeof(iabuf), dest.sin_addr));
02014 snprintf(s, sizeof(s), "s=session\r\n");
02015 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(iabuf, sizeof(iabuf), dest.sin_addr));
02016 snprintf(t, sizeof(t), "t=0 0\r\n");
02017 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
02018 for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02019 if (p->capability & x) {
02020 if (mgcpdebug) {
02021 ast_verbose("Answering with capability %d\n", x);
02022 }
02023 codec = ast_rtp_lookup_code(sub->rtp, 1, x);
02024 if (codec > -1) {
02025 snprintf(costr, sizeof(costr), " %d", codec);
02026 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02027 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
02028 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02029 }
02030 }
02031 }
02032 for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
02033 if (p->nonCodecCapability & x) {
02034 if (mgcpdebug) {
02035 ast_verbose("Answering with non-codec capability %d\n", x);
02036 }
02037 codec = ast_rtp_lookup_code(sub->rtp, 0, x);
02038 if (codec > -1) {
02039 snprintf(costr, sizeof(costr), " %d", codec);
02040 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02041 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x));
02042 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02043 if (x == AST_RTP_DTMF) {
02044
02045
02046 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
02047 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02048 }
02049 }
02050 }
02051 }
02052 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
02053 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
02054 snprintf(costr, sizeof(costr), "%d", len);
02055 add_line(resp, v);
02056 add_line(resp, o);
02057 add_line(resp, s);
02058 add_line(resp, c);
02059 add_line(resp, t);
02060 add_line(resp, m);
02061 add_line(resp, a);
02062 return 0;
02063 }
02064
02065 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
02066 {
02067 struct mgcp_request resp;
02068 char local[256];
02069 char tmp[80];
02070 int x;
02071 int capability;
02072 struct mgcp_endpoint *p = sub->parent;
02073
02074 capability = p->capability;
02075 if (codecs)
02076 capability = codecs;
02077 if (ast_strlen_zero(sub->cxident) && rtp) {
02078
02079
02080 ast_rtp_get_peer(rtp, &sub->tmpdest);
02081 return 0;
02082 }
02083 snprintf(local, sizeof(local), "p:20");
02084 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02085 if (p->capability & x) {
02086 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
02087 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02088 }
02089 }
02090 reqprep(&resp, p, "MDCX");
02091 add_header(&resp, "C", sub->callid);
02092 add_header(&resp, "L", local);
02093 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02094
02095 add_header(&resp, "X", sub->txident);
02096 add_header(&resp, "I", sub->cxident);
02097
02098 ast_rtp_offered_from_local(sub->rtp, 0);
02099 add_sdp(&resp, sub, rtp);
02100
02101 resp.cmd = MGCP_CMD_MDCX;
02102 resp.trid = oseq;
02103 return send_request(p, sub, &resp, oseq);
02104 }
02105
02106 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
02107 {
02108 struct mgcp_request resp;
02109 char local[256];
02110 char tmp[80];
02111 int x;
02112 struct mgcp_endpoint *p = sub->parent;
02113
02114 snprintf(local, sizeof(local), "p:20");
02115 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02116 if (p->capability & x) {
02117 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
02118 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02119 }
02120 }
02121 if (mgcpdebug) {
02122 ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02123 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02124 }
02125 reqprep(&resp, p, "CRCX");
02126 add_header(&resp, "C", sub->callid);
02127 add_header(&resp, "L", local);
02128 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02129
02130 add_header(&resp, "X", sub->txident);
02131
02132 ast_rtp_offered_from_local(sub->rtp, 1);
02133 add_sdp(&resp, sub, rtp);
02134
02135 resp.cmd = MGCP_CMD_CRCX;
02136 resp.trid = oseq;
02137 return send_request(p, sub, &resp, oseq);
02138 }
02139
02140 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
02141 {
02142 struct mgcp_request resp;
02143 struct mgcp_endpoint *p = sub->parent;
02144
02145 if (mgcpdebug) {
02146 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02147 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02148 }
02149 strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
02150 reqprep(&resp, p, "RQNT");
02151 add_header(&resp, "X", p->rqnt_ident);
02152 switch (p->hookstate) {
02153 case MGCP_ONHOOK:
02154 add_header(&resp, "R", "L/hd(N)");
02155 break;
02156 case MGCP_OFFHOOK:
02157 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)");
02158 break;
02159 }
02160 if (!ast_strlen_zero(tone)) {
02161 add_header(&resp, "S", tone);
02162 }
02163
02164 resp.cmd = MGCP_CMD_RQNT;
02165 resp.trid = oseq;
02166 return send_request(p, NULL, &resp, oseq);
02167 }
02168
02169 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
02170 {
02171 struct mgcp_request resp;
02172 char tone2[256];
02173 char *l, *n;
02174 time_t t;
02175 struct tm tm;
02176 struct mgcp_endpoint *p = sub->parent;
02177
02178 time(&t);
02179 localtime_r(&t,&tm);
02180 n = callername;
02181 l = callernum;
02182 if (!n)
02183 n = "";
02184 if (!l)
02185 l = "";
02186
02187
02188 strncpy(p->lastcallerid, l, sizeof(p->lastcallerid) - 1);
02189
02190 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
02191 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02192 strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
02193 reqprep(&resp, p, "RQNT");
02194 add_header(&resp, "X", p->rqnt_ident);
02195 switch (p->hookstate) {
02196 case MGCP_ONHOOK:
02197 add_header(&resp, "R", "L/hd(N)");
02198 break;
02199 case MGCP_OFFHOOK:
02200 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)");
02201 break;
02202 }
02203 if (!ast_strlen_zero(tone2)) {
02204 add_header(&resp, "S", tone2);
02205 }
02206 if (mgcpdebug) {
02207 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02208 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02209 }
02210
02211 resp.cmd = MGCP_CMD_RQNT;
02212 resp.trid = oseq;
02213 return send_request(p, NULL, &resp, oseq);
02214 }
02215
02216 static int transmit_modify_request(struct mgcp_subchannel *sub)
02217 {
02218 struct mgcp_request resp;
02219 struct mgcp_endpoint *p = sub->parent;
02220
02221 if (ast_strlen_zero(sub->cxident)) {
02222
02223
02224 return 0;
02225 }
02226 if (mgcpdebug) {
02227 ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n",
02228 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02229 }
02230 reqprep(&resp, p, "MDCX");
02231 add_header(&resp, "C", sub->callid);
02232 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02233
02234 add_header(&resp, "X", sub->txident);
02235 add_header(&resp, "I", sub->cxident);
02236 switch (sub->parent->hookstate) {
02237 case MGCP_ONHOOK:
02238 add_header(&resp, "R", "L/hd(N)");
02239 break;
02240 case MGCP_OFFHOOK:
02241 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)");
02242 break;
02243 }
02244
02245 resp.cmd = MGCP_CMD_MDCX;
02246 resp.trid = oseq;
02247 return send_request(p, sub, &resp, oseq);
02248 }
02249
02250
02251 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
02252 {
02253 struct mgcp_request resp;
02254 reqprep(&resp, p, "AUEP");
02255
02256
02257 add_header(&resp, "F", "A");
02258
02259 resp.cmd = MGCP_CMD_AUEP;
02260 resp.trid = oseq;
02261 return send_request(p, NULL, &resp, oseq);
02262 }
02263
02264 static int transmit_connection_del(struct mgcp_subchannel *sub)
02265 {
02266 struct mgcp_endpoint *p = sub->parent;
02267 struct mgcp_request resp;
02268
02269 if (mgcpdebug) {
02270 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
02271 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02272 }
02273 reqprep(&resp, p, "DLCX");
02274
02275 if (sub->callid[0])
02276 add_header(&resp, "C", sub->callid);
02277
02278 add_header(&resp, "X", sub->txident);
02279
02280 if (sub->cxident[0])
02281 add_header(&resp, "I", sub->cxident);
02282
02283 resp.cmd = MGCP_CMD_DLCX;
02284 resp.trid = oseq;
02285 return send_request(p, sub, &resp, oseq);
02286 }
02287
02288 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
02289 {
02290 struct mgcp_request resp;
02291
02292 if (mgcpdebug) {
02293 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n",
02294 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02295 }
02296 reqprep(&resp, p, "DLCX");
02297
02298 if (callid && *callid)
02299 add_header(&resp, "C", callid);
02300
02301 if (cxident && *cxident)
02302 add_header(&resp, "I", cxident);
02303
02304 resp.cmd = MGCP_CMD_DLCX;
02305 resp.trid = oseq;
02306 return send_request(p, p->sub, &resp, oseq);
02307 }
02308
02309
02310 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
02311 {
02312 struct mgcp_request *t, *q;
02313
02314 if (p) {
02315 ast_mutex_lock(&p->rqnt_queue_lock);
02316 for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
02317 p->rqnt_queue = NULL;
02318 ast_mutex_unlock(&p->rqnt_queue_lock);
02319
02320 ast_mutex_lock(&p->cmd_queue_lock);
02321 for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
02322 p->cmd_queue = NULL;
02323 ast_mutex_unlock(&p->cmd_queue_lock);
02324
02325 ast_mutex_lock(&p->sub->cx_queue_lock);
02326 for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
02327 p->sub->cx_queue = NULL;
02328 ast_mutex_unlock(&p->sub->cx_queue_lock);
02329
02330 ast_mutex_lock(&p->sub->next->cx_queue_lock);
02331 for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
02332 p->sub->next->cx_queue = NULL;
02333 ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02334 } else if (sub) {
02335 ast_mutex_lock(&sub->cx_queue_lock);
02336 for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
02337 sub->cx_queue = NULL;
02338 ast_mutex_unlock(&sub->cx_queue_lock);
02339 }
02340 }
02341
02342
02343
02344 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02345 struct mgcp_request **queue, ast_mutex_t *l, int ident)
02346 {
02347 struct mgcp_request *prev, *req;
02348 char iabuf[INET_ADDRSTRLEN];
02349
02350 ast_mutex_lock(l);
02351 for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02352 if (req->trid == ident) {
02353
02354 if (!prev)
02355 *queue = req->next;
02356 else
02357 prev->next = req->next;
02358
02359
02360 if (*queue) {
02361 if (mgcpdebug) {
02362 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
02363 ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02364 }
02365
02366 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02367 }
02368 break;
02369 }
02370 }
02371 ast_mutex_unlock(l);
02372 return req;
02373 }
02374
02375
02376 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02377 int result, unsigned int ident, struct mgcp_request *resp)
02378 {
02379 char *c;
02380 struct mgcp_request *req;
02381 struct mgcp_gateway *gw = p->parent;
02382
02383 if (result < 200) {
02384
02385 return;
02386 }
02387
02388 if (p->slowsequence)
02389 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02390 else if (sub)
02391 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
02392 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
02393 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02394
02395 if (!req) {
02396 if (option_verbose > 2) {
02397 ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n",
02398 gw->name, ident);
02399 }
02400 return;
02401 }
02402
02403 if (p && (result >= 400) && (result <= 599)) {
02404 switch (result) {
02405 case 401:
02406 p->hookstate = MGCP_OFFHOOK;
02407 break;
02408 case 402:
02409 p->hookstate = MGCP_ONHOOK;
02410 break;
02411 case 406:
02412 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
02413 break;
02414 case 407:
02415 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
02416 break;
02417 }
02418 if (sub) {
02419 if (sub->owner) {
02420 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02421 result, p->name, p->parent->name, sub ? sub->id:-1);
02422 mgcp_queue_hangup(sub);
02423 }
02424 } else {
02425 if (p->sub->next->owner) {
02426 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02427 result, p->name, p->parent->name, sub ? sub->id:-1);
02428 mgcp_queue_hangup(p->sub);
02429 }
02430
02431 if (p->sub->owner) {
02432 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02433 result, p->name, p->parent->name, sub ? sub->id:-1);
02434 mgcp_queue_hangup(p->sub);
02435 }
02436
02437 dump_cmd_queues(p, NULL);
02438 }
02439 }
02440
02441 if (resp) {
02442 if (req->cmd == MGCP_CMD_CRCX) {
02443 if ((c = get_header(resp, "I"))) {
02444 if (!ast_strlen_zero(c) && sub) {
02445
02446 if (sub->owner) {
02447 if (!ast_strlen_zero(sub->cxident)) {
02448 if (strcasecmp(c, sub->cxident)) {
02449 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
02450 }
02451 }
02452 strncpy(sub->cxident, c, sizeof(sub->cxident) - 1);
02453 if (sub->tmpdest.sin_addr.s_addr) {
02454 transmit_modify_with_sdp(sub, NULL, 0);
02455 }
02456 } else {
02457
02458
02459
02460
02461 transmit_connection_del(sub);
02462 }
02463 }
02464 }
02465 }
02466
02467 if (req->cmd == MGCP_CMD_AUEP) {
02468
02469 if ((c = get_header(resp, "I"))) {
02470 char *v, *n;
02471 int len;
02472 while ((v = get_csv(c, &len, &n))) {
02473 if (len) {
02474 if (strncasecmp(v, p->sub->cxident, len) &&
02475 strncasecmp(v, p->sub->next->cxident, len)) {
02476
02477 char cxident[80];
02478 memcpy(cxident, v, len);
02479 cxident[len] = '\0';
02480 if (option_verbose > 2) {
02481 ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n",
02482 cxident, p->name, gw->name);
02483 }
02484 transmit_connection_del_w_params(p, NULL, cxident);
02485 }
02486 }
02487 c = n;
02488 }
02489 }
02490
02491
02492 if ((c = get_header(resp, "ES"))) {
02493 if (!ast_strlen_zero(c)) {
02494 if (strstr(c, "hu")) {
02495 if (p->hookstate != MGCP_ONHOOK) {
02496
02497 if ((p->sub->owner || p->sub->next->owner ) &&
02498 p->hookstate == MGCP_OFFHOOK)
02499 mgcp_queue_hangup(sub);
02500 p->hookstate = MGCP_ONHOOK;
02501
02502
02503 transmit_notify_request(p->sub, "");
02504
02505
02506 if (option_verbose > 2) {
02507 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
02508 }
02509 }
02510 } else if (strstr(c, "hd")) {
02511 if (p->hookstate != MGCP_OFFHOOK) {
02512 p->hookstate = MGCP_OFFHOOK;
02513
02514
02515 transmit_notify_request(p->sub, "");
02516
02517
02518 if (option_verbose > 2) {
02519 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
02520 }
02521 }
02522 }
02523 }
02524 }
02525 }
02526
02527 if (resp && resp->lines) {
02528
02529 if (sub && sub->owner) {
02530 if (!sub->rtp)
02531 start_rtp(sub);
02532 if (sub->rtp)
02533 process_sdp(sub, resp);
02534 }
02535 }
02536 }
02537
02538 free(req);
02539 }
02540
02541 static void start_rtp(struct mgcp_subchannel *sub)
02542 {
02543 ast_mutex_lock(&sub->lock);
02544
02545 if (sub->rtp) {
02546 ast_rtp_destroy(sub->rtp);
02547 sub->rtp = NULL;
02548 }
02549
02550 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
02551 if (sub->rtp && sub->owner)
02552 sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
02553 if (sub->rtp)
02554 ast_rtp_setnat(sub->rtp, sub->nat);
02555 #if 0
02556 ast_rtp_set_callback(p->rtp, rtpready);
02557 ast_rtp_set_data(p->rtp, p);
02558 #endif
02559
02560 snprintf(sub->callid, sizeof(sub->callid), "%08x%s", rand(), sub->txident);
02561
02562 transmit_connect_with_sdp(sub, NULL);
02563 ast_mutex_unlock(&sub->lock);
02564 }
02565
02566 static void *mgcp_ss(void *data)
02567 {
02568 struct ast_channel *chan = data;
02569 struct mgcp_subchannel *sub = chan->tech_pvt;
02570 struct mgcp_endpoint *p = sub->parent;
02571 char exten[AST_MAX_EXTENSION] = "";
02572 int len = 0;
02573 int timeout = firstdigittimeout;
02574 int res;
02575 int getforward = 0;
02576
02577 while(len < AST_MAX_EXTENSION-1) {
02578 res = ast_waitfordigit(chan, timeout);
02579 timeout = 0;
02580 if (res < 0) {
02581 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
02582
02583 ast_indicate(chan, -1);
02584 ast_hangup(chan);
02585 return NULL;
02586 } else if (res) {
02587 exten[len++]=res;
02588 exten[len] = '\0';
02589 }
02590 if (!ast_ignore_pattern(chan->context, exten)) {
02591
02592 ast_indicate(chan, -1);
02593 } else {
02594
02595
02596 transmit_notify_request(sub, "L/dl");
02597 }
02598 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
02599 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
02600 if (getforward) {
02601
02602 strncpy(p->call_forward, exten, sizeof(p->call_forward) - 1);
02603 if (option_verbose > 2) {
02604 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
02605 p->call_forward, chan->name);
02606 }
02607
02608 transmit_notify_request(sub, "L/sl");
02609 if (res)
02610 break;
02611 usleep(500000);
02612
02613 ast_indicate(chan, -1);
02614 sleep(1);
02615 memset(exten, 0, sizeof(exten));
02616
02617 transmit_notify_request(sub, "L/dl");
02618 len = 0;
02619 getforward = 0;
02620 } else {
02621
02622 ast_indicate(chan, -1);
02623 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
02624 if (!ast_strlen_zero(p->cid_num)) {
02625 if (!p->hidecallerid) {
02626
02627 if (chan->cid.cid_num)
02628 free(chan->cid.cid_num);
02629 chan->cid.cid_num = strdup(p->cid_num);
02630
02631 if (chan->cid.cid_name)
02632 free(chan->cid.cid_name);
02633 chan->cid.cid_name = strdup(p->cid_name);
02634 }
02635 if (chan->cid.cid_ani)
02636 free(chan->cid.cid_ani);
02637 chan->cid.cid_ani = strdup(p->cid_num);
02638 }
02639 ast_setstate(chan, AST_STATE_RING);
02640
02641 if (p->dtmfmode & MGCP_DTMF_HYBRID) {
02642 p->dtmfmode |= MGCP_DTMF_INBAND;
02643 ast_indicate(chan, -1);
02644 }
02645 res = ast_pbx_run(chan);
02646 if (res) {
02647 ast_log(LOG_WARNING, "PBX exited non-zero\n");
02648
02649
02650 transmit_notify_request(sub, "G/cg");
02651 }
02652 return NULL;
02653 }
02654 } else {
02655
02656
02657 timeout = matchdigittimeout;
02658 }
02659 } else if (res == 0) {
02660 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
02661
02662 transmit_notify_request(sub, "G/cg");
02663
02664 ast_hangup(chan);
02665 return NULL;
02666 } else if (p->hascallwaiting && p->callwaiting && !strcmp(exten, "*70")) {
02667 if (option_verbose > 2) {
02668 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
02669 }
02670
02671 p->callwaiting = 0;
02672
02673 transmit_notify_request(sub, "L/sl");
02674 len = 0;
02675 memset(exten, 0, sizeof(exten));
02676 timeout = firstdigittimeout;
02677 } else if (!strcmp(exten,ast_pickup_ext())) {
02678
02679
02680
02681
02682 if (ast_pickup_call(chan)) {
02683 ast_log(LOG_WARNING, "No call pickup possible...\n");
02684
02685 transmit_notify_request(sub, "G/cg");
02686 }
02687 ast_hangup(chan);
02688 return NULL;
02689 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
02690 if (option_verbose > 2) {
02691 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
02692 }
02693
02694 p->hidecallerid = 1;
02695 if (chan->cid.cid_num)
02696 free(chan->cid.cid_num);
02697 chan->cid.cid_num = NULL;
02698 if (chan->cid.cid_name)
02699 free(chan->cid.cid_name);
02700 chan->cid.cid_name = NULL;
02701
02702 transmit_notify_request(sub, "L/sl");
02703 len = 0;
02704 memset(exten, 0, sizeof(exten));
02705 timeout = firstdigittimeout;
02706 } else if (p->callreturn && !strcmp(exten, "*69")) {
02707 res = 0;
02708 if (!ast_strlen_zero(p->lastcallerid)) {
02709 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
02710 }
02711 if (!res)
02712
02713 transmit_notify_request(sub, "L/sl");
02714 break;
02715 } else if (!strcmp(exten, "*78")) {
02716
02717 if (option_verbose > 2) {
02718 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
02719 }
02720
02721 transmit_notify_request(sub, "L/sl");
02722 p->dnd = 1;
02723 getforward = 0;
02724 memset(exten, 0, sizeof(exten));
02725 len = 0;
02726 } else if (!strcmp(exten, "*79")) {
02727
02728 if (option_verbose > 2) {
02729 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
02730 }
02731
02732 transmit_notify_request(sub, "L/sl");
02733 p->dnd = 0;
02734 getforward = 0;
02735 memset(exten, 0, sizeof(exten));
02736 len = 0;
02737 } else if (p->cancallforward && !strcmp(exten, "*72")) {
02738
02739 transmit_notify_request(sub, "L/sl");
02740 getforward = 1;
02741 memset(exten, 0, sizeof(exten));
02742 len = 0;
02743 } else if (p->cancallforward && !strcmp(exten, "*73")) {
02744 if (option_verbose > 2) {
02745 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
02746 }
02747
02748 transmit_notify_request(sub, "L/sl");
02749 memset(p->call_forward, 0, sizeof(p->call_forward));
02750 getforward = 0;
02751 memset(exten, 0, sizeof(exten));
02752 len = 0;
02753 } else if (!strcmp(exten, ast_parking_ext()) &&
02754 sub->next->owner && ast_bridged_channel(sub->next->owner)) {
02755
02756
02757 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
02758 if (option_verbose > 2) {
02759 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
02760 }
02761 break;
02762 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(exten, "*60")) {
02763 if (option_verbose > 2) {
02764 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
02765 }
02766 res = ast_db_put("blacklist", p->lastcallerid, "1");
02767 if (!res) {
02768
02769 transmit_notify_request(sub, "L/sl");
02770 memset(exten, 0, sizeof(exten));
02771 len = 0;
02772 }
02773 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
02774 if (option_verbose > 2) {
02775 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
02776 }
02777
02778 p->hidecallerid = 0;
02779 if (chan->cid.cid_num)
02780 free(chan->cid.cid_num);
02781 if (!ast_strlen_zero(p->cid_num))
02782 chan->cid.cid_num = strdup(p->cid_num);
02783 if (chan->cid.cid_name)
02784 free(chan->cid.cid_name);
02785 if (!ast_strlen_zero(p->cid_name))
02786 chan->cid.cid_name = strdup(p->cid_name);
02787
02788 transmit_notify_request(sub, "L/sl");
02789 len = 0;
02790 memset(exten, 0, sizeof(exten));
02791 timeout = firstdigittimeout;
02792 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
02793 ((exten[0] != '*') || (strlen(exten) > 2))) {
02794 if (option_debug)
02795 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);
02796 break;
02797 }
02798 if (!timeout)
02799 timeout = gendigittimeout;
02800 if (len && !ast_ignore_pattern(chan->context, exten))
02801
02802 ast_indicate(chan, -1);
02803 }
02804 #if 0
02805 for (;;) {
02806 res = ast_waitfordigit(chan, to);
02807 if (!res) {
02808 ast_log(LOG_DEBUG, "Timeout...\n");
02809 break;
02810 }
02811 if (res < 0) {
02812 ast_log(LOG_DEBUG, "Got hangup...\n");
02813 ast_hangup(chan);
02814 break;
02815 }
02816 exten[pos++] = res;
02817 if (!ast_ignore_pattern(chan->context, exten))
02818 ast_indicate(chan, -1);
02819 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
02820 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
02821 to = 3000;
02822 else
02823 to = 8000;
02824 } else
02825 break;
02826 }
02827 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
02828 strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
02829 if (!p->rtp) {
02830 start_rtp(p);
02831 }
02832 ast_setstate(chan, AST_STATE_RING);
02833 chan->rings = 1;
02834 if (ast_pbx_run(chan)) {
02835 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
02836 } else
02837 return NULL;
02838 }
02839 #endif
02840 ast_hangup(chan);
02841 return NULL;
02842 }
02843
02844 static int attempt_transfer(struct mgcp_endpoint *p)
02845 {
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855 if (ast_bridged_channel(p->sub->owner)) {
02856
02857
02858 if (ast_bridged_channel(p->sub->next->owner))
02859 ast_moh_stop(ast_bridged_channel(p->sub->next->owner));
02860 if (p->sub->owner->_state == AST_STATE_RINGING) {
02861 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02862 }
02863 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
02864 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02865 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
02866 return -1;
02867 }
02868
02869 unalloc_sub(p->sub->next);
02870 } else if (ast_bridged_channel(p->sub->next->owner)) {
02871 if (p->sub->owner->_state == AST_STATE_RINGING) {
02872 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02873 }
02874 ast_moh_stop(ast_bridged_channel(p->sub->next->owner));
02875 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
02876 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02877 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
02878 return -1;
02879 }
02880
02881 if (option_verbose > 2) {
02882 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);
02883 }
02884 p->sub = p->sub->next;
02885 unalloc_sub(p->sub->next);
02886
02887 return 1;
02888 } else {
02889 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
02890 p->sub->owner->name, p->sub->next->owner->name);
02891 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02892 if (p->sub->next->owner) {
02893 p->sub->next->alreadygone = 1;
02894 mgcp_queue_hangup(p->sub->next);
02895 }
02896 }
02897 return 0;
02898 }
02899
02900 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
02901 {
02902 struct mgcp_endpoint *p = sub->parent;
02903 struct ast_channel *c;
02904 pthread_t t;
02905 pthread_attr_t attr;
02906 pthread_attr_init(&attr);
02907 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02908
02909
02910 if (sub->outgoing) {
02911
02912 if (sub->owner) {
02913 if (ast_bridged_channel(sub->owner)) {
02914 ast_moh_stop(ast_bridged_channel(sub->owner));
02915 }
02916 sub->cxmode = MGCP_CX_SENDRECV;
02917 if (!sub->rtp) {
02918 start_rtp(sub);
02919 } else {
02920 transmit_modify_request(sub);
02921 }
02922
02923 transmit_notify_request(sub, "");
02924 mgcp_queue_control(sub, AST_CONTROL_ANSWER);
02925 }
02926 } else {
02927
02928
02929 if (!sub->owner) {
02930 if (!sub->rtp) {
02931 start_rtp(sub);
02932 } else {
02933 transmit_modify_request(sub);
02934 }
02935 if (p->immediate) {
02936
02937 #ifdef DLINK_BUGGY_FIRMWARE
02938 transmit_notify_request(sub, "rt");
02939 #else
02940 transmit_notify_request(sub, "G/rt");
02941 #endif
02942 c = mgcp_new(sub, AST_STATE_RING);
02943 if (!c) {
02944 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
02945 transmit_notify_request(sub, "G/cg");
02946 ast_hangup(c);
02947 }
02948 } else {
02949 if (has_voicemail(p)) {
02950 transmit_notify_request(sub, "L/sl");
02951 } else {
02952 transmit_notify_request(sub, "L/dl");
02953 }
02954 c = mgcp_new(sub, AST_STATE_DOWN);
02955 if (c) {
02956 if (ast_pthread_create(&t, &attr, mgcp_ss, c)) {
02957 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
02958 ast_hangup(c);
02959 }
02960 } else {
02961 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
02962 }
02963 }
02964 } else {
02965 if (p->hookstate == MGCP_OFFHOOK) {
02966 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
02967 } else {
02968 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
02969 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
02970 }
02971 if (ast_bridged_channel(sub->owner)) {
02972 ast_moh_stop(ast_bridged_channel(sub->owner));
02973 }
02974 sub->cxmode = MGCP_CX_SENDRECV;
02975 if (!sub->rtp) {
02976 start_rtp(sub);
02977 } else {
02978 transmit_modify_request(sub);
02979 }
02980
02981 transmit_notify_request(sub, "");
02982
02983 }
02984 }
02985 }
02986
02987 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
02988 {
02989 char *ev, *s;
02990 struct ast_frame f = { 0, };
02991 struct mgcp_endpoint *p = sub->parent;
02992 struct mgcp_gateway *g = NULL;
02993 char iabuf[INET_ADDRSTRLEN];
02994 int res;
02995
02996 if (mgcpdebug) {
02997 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
02998 }
02999
03000 if (!strcasecmp(req->verb, "RSIP")) {
03001
03002 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
03003 if (option_verbose > 2)
03004 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
03005 transmit_response(sub, "200", req, "OK");
03006 } else {
03007 dump_queue(p->parent, p);
03008 dump_cmd_queues(p, NULL);
03009
03010 if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) {
03011 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
03012 }
03013
03014 if (!strcmp(p->name, p->parent->wcardep)) {
03015
03016 struct mgcp_endpoint *tmp_ep;
03017
03018 g = p->parent;
03019 tmp_ep = g->endpoints;
03020 while (tmp_ep) {
03021
03022 if (strcmp(tmp_ep->name, g->wcardep) != 0) {
03023 struct mgcp_subchannel *tmp_sub, *first_sub;
03024 if (option_verbose > 2) {
03025 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
03026 }
03027
03028 first_sub = tmp_ep->sub;
03029 tmp_sub = tmp_ep->sub;
03030 while (tmp_sub) {
03031 mgcp_queue_hangup(tmp_sub);
03032 tmp_sub = tmp_sub->next;
03033 if (tmp_sub == first_sub)
03034 break;
03035 }
03036 }
03037 tmp_ep = tmp_ep->next;
03038 }
03039 } else if (sub->owner) {
03040 mgcp_queue_hangup(sub);
03041 }
03042 transmit_response(sub, "200", req, "OK");
03043
03044 if (strcmp(p->name, p->parent->wcardep) != 0) {
03045 transmit_notify_request(sub, "");
03046
03047
03048
03049 transmit_audit_endpoint(p);
03050 }
03051 }
03052 } else if (!strcasecmp(req->verb, "NTFY")) {
03053
03054 transmit_response(sub, "200", req, "OK");
03055
03056 ev = get_header(req, "O");
03057 s = strchr(ev, '/');
03058 if (s) ev = s + 1;
03059 ast_log(LOG_DEBUG, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
03060
03061 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
03062 transmit_notify_request(sub, p->curtone);
03063 }
03064 if (!strcasecmp(ev, "hd")) {
03065 p->hookstate = MGCP_OFFHOOK;
03066 sub->cxmode = MGCP_CX_SENDRECV;
03067 handle_hd_hf(sub, ev);
03068 } else if (!strcasecmp(ev, "hf")) {
03069
03070
03071
03072 if (p->hookstate != MGCP_OFFHOOK) {
03073
03074
03075 return -1;
03076 }
03077
03078 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
03079 return -1;
03080
03081 if (p->callwaiting || p->transfer || p->threewaycalling) {
03082 if (option_verbose > 2) {
03083 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);
03084 }
03085 p->sub = p->sub->next;
03086
03087
03088 if (!sub->next->owner) {
03089
03090 sub->cxmode = MGCP_CX_MUTE;
03091 if (option_verbose > 2) {
03092 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03093 }
03094 transmit_modify_request(sub);
03095 if (sub->owner && ast_bridged_channel(sub->owner)) {
03096 ast_moh_start(ast_bridged_channel(sub->owner), NULL);
03097 }
03098 sub->next->cxmode = MGCP_CX_RECVONLY;
03099 handle_hd_hf(sub->next, ev);
03100 } else if (sub->owner && sub->next->owner) {
03101
03102 if ((!sub->outgoing) && (!sub->next->outgoing)) {
03103
03104 if (option_verbose > 2) {
03105 ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n",
03106 sub->id, sub->next->id, p->name, p->parent->name);
03107 }
03108 sub->cxmode = MGCP_CX_CONF;
03109 sub->next->cxmode = MGCP_CX_CONF;
03110 if (ast_bridged_channel(sub->next->owner))
03111 ast_moh_stop(ast_bridged_channel(sub->next->owner));
03112 transmit_modify_request(sub);
03113 transmit_modify_request(sub->next);
03114 } else {
03115
03116
03117
03118 if (option_verbose > 2) {
03119 ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
03120 sub->id, sub->next->id, p->name, p->parent->name);
03121 }
03122 sub->cxmode = MGCP_CX_MUTE;
03123 if (option_verbose > 2) {
03124 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03125 }
03126 transmit_modify_request(sub);
03127 if (ast_bridged_channel(sub->owner))
03128 ast_moh_start(ast_bridged_channel(sub->owner), NULL);
03129
03130 if (ast_bridged_channel(sub->next->owner))
03131 ast_moh_stop(ast_bridged_channel(sub->next->owner));
03132
03133 handle_hd_hf(sub->next, ev);
03134 #if 0
03135 if (sub->next->owner && (sub->next->owner->_state != AST_STATE_UP)) {
03136 handle_hd_hf(sub->next, ev);
03137 } else {
03138 ast_verbose(VERBOSE_PREFIX_3 "MGCP Unmuting %d on %s@%s\n", sub->next->id, p->name, p->parent->name);
03139 sub->next->cxmode = MGCP_CX_SENDRECV;
03140 transmit_modify_request(sub->next);
03141 }
03142 #endif
03143 }
03144 } else {
03145
03146 if (sub->owner) {
03147 p->sub = sub;
03148 } else if (sub->next->owner) {
03149 p->sub = sub->next;
03150 } else {
03151
03152
03153 return -1;
03154 }
03155 if (ast_bridged_channel(p->sub->owner)) {
03156 ast_moh_stop(ast_bridged_channel(p->sub->owner));
03157 }
03158 p->sub->cxmode = MGCP_CX_SENDRECV;
03159 transmit_modify_request(p->sub);
03160 }
03161 } else {
03162 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
03163 p->name, p->parent->name);
03164 }
03165
03166 } else if (!strcasecmp(ev, "hu")) {
03167 p->hookstate = MGCP_ONHOOK;
03168 sub->cxmode = MGCP_CX_RECVONLY;
03169 ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
03170
03171
03172
03173
03174
03175 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
03176
03177
03178 ast_mutex_lock(&p->sub->next->lock);
03179 res = attempt_transfer(p);
03180 if (res < 0) {
03181 if (p->sub->next->owner) {
03182 sub->next->alreadygone = 1;
03183 mgcp_queue_hangup(sub->next);
03184 }
03185 } else if (res) {
03186 ast_log(LOG_WARNING, "Transfer attempt failed\n");
03187 ast_mutex_unlock(&p->sub->next->lock);
03188 return -1;
03189 }
03190 ast_mutex_unlock(&p->sub->next->lock);
03191 } else {
03192
03193
03194 if (sub->owner) {
03195 sub->alreadygone = 1;
03196 mgcp_queue_hangup(sub);
03197 } else {
03198
03199 if (option_verbose > 2) {
03200 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
03201 p->name, p->parent->name, sub->id);
03202 }
03203
03204
03205
03206 transmit_connection_del(sub);
03207 }
03208 }
03209 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
03210 p->hidecallerid = 0;
03211 if (p->hascallwaiting && !p->callwaiting) {
03212 if (option_verbose > 2)
03213 ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
03214 p->callwaiting = -1;
03215 }
03216 if (has_voicemail(p)) {
03217 if (option_verbose > 2) {
03218 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
03219 }
03220 transmit_notify_request(sub, "L/vmwi(+)");
03221 } else {
03222 if (option_verbose > 2) {
03223 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
03224 }
03225 transmit_notify_request(sub, "L/vmwi(-)");
03226 }
03227 }
03228 } else if ((strlen(ev) == 1) &&
03229 (((ev[0] >= '0') && (ev[0] <= '9')) ||
03230 ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
03231 (ev[0] == '*') || (ev[0] == '#'))) {
03232 f.frametype = AST_FRAME_DTMF;
03233 f.subclass = ev[0];
03234 f.src = "mgcp";
03235 if (sub->owner) {
03236
03237 mgcp_queue_frame(sub, &f);
03238 ast_mutex_lock(&sub->next->lock);
03239 if (sub->next->owner) {
03240 mgcp_queue_frame(sub->next, &f);
03241 }
03242 ast_mutex_unlock(&sub->next->lock);
03243 }
03244 if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
03245 memset(p->curtone, 0, sizeof(p->curtone));
03246 }
03247 } else if (!strcasecmp(ev, "T")) {
03248
03249 } else if (!strcasecmp(ev, "ping")) {
03250
03251 } else {
03252 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
03253 }
03254 } else {
03255 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr));
03256 transmit_response(sub, "510", req, "Unknown verb");
03257 }
03258 return 0;
03259 }
03260
03261 static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
03262 {
03263 int seqno=0;
03264 time_t now;
03265 struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
03266 time(&now);
03267 if (sscanf(req->identifier, "%d", &seqno) != 1)
03268 seqno = 0;
03269 cur = sub->parent->parent->responses;
03270 while(cur) {
03271 next = cur->next;
03272 if (now - cur->whensent > RESPONSE_TIMEOUT) {
03273
03274 if (prev)
03275 prev->next = next;
03276 else
03277 sub->parent->parent->responses = next;
03278 free(cur);
03279 } else {
03280 if (seqno == cur->seqno)
03281 answer = cur;
03282 prev = cur;
03283 }
03284 cur = next;
03285 }
03286 if (answer) {
03287 resend_response(sub, answer);
03288 return 1;
03289 }
03290 return 0;
03291 }
03292
03293 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
03294 {
03295 struct mgcp_request req;
03296 struct sockaddr_in sin;
03297 struct mgcp_subchannel *sub;
03298 int res;
03299 socklen_t len;
03300 int result;
03301 int ident;
03302 char iabuf[INET_ADDRSTRLEN];
03303 len = sizeof(sin);
03304 memset(&req, 0, sizeof(req));
03305 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03306 if (res < 0) {
03307 if (errno != ECONNREFUSED)
03308 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03309 return 1;
03310 }
03311 req.data[res] = '\0';
03312 req.len = res;
03313 if (mgcpdebug) {
03314 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));
03315 }
03316 parse(&req);
03317 if (req.headers < 1) {
03318
03319 return 1;
03320 }
03321 if (ast_strlen_zero(req.identifier)) {
03322 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr));
03323 return 1;
03324 }
03325
03326 if (sscanf(req.verb, "%d", &result) && sscanf(req.identifier, "%d", &ident)) {
03327
03328 sub = find_subchannel_and_lock(NULL, ident, &sin);
03329 if (sub) {
03330 struct mgcp_gateway *gw = sub->parent->parent;
03331 struct mgcp_message *cur, *prev;
03332
03333 ast_mutex_unlock(&sub->lock);
03334 ast_mutex_lock(&gw->msgs_lock);
03335 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03336 if (cur->seqno == ident) {
03337 ast_log(LOG_DEBUG, "Got response back on transaction %d\n", ident);
03338 if (prev)
03339 prev->next = cur->next;
03340 else
03341 gw->msgs = cur->next;
03342 break;
03343 }
03344 }
03345
03346
03347 if (!gw->msgs && (gw->retransid != -1)) {
03348 ast_sched_del(sched, gw->retransid);
03349 gw->retransid = -1;
03350 }
03351
03352 ast_mutex_unlock(&gw->msgs_lock);
03353 if (cur) {
03354 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03355 free(cur);
03356 return 1;
03357 }
03358
03359 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
03360 gw->name, ident);
03361 }
03362 } else {
03363 if (ast_strlen_zero(req.endpoint) ||
03364 ast_strlen_zero(req.version) ||
03365 ast_strlen_zero(req.verb)) {
03366 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03367 return 1;
03368 }
03369
03370 sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03371 if (sub) {
03372
03373 if (!find_and_retrans(sub, &req))
03374
03375 handle_request(sub, &req, &sin);
03376 ast_mutex_unlock(&sub->lock);
03377 }
03378 }
03379 return 1;
03380 }
03381
03382 static int *mgcpsock_read_id = NULL;
03383
03384 static void *do_monitor(void *data)
03385 {
03386 int res;
03387 int reloading;
03388
03389
03390
03391
03392
03393 if (mgcpsock > -1)
03394 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03395
03396
03397
03398
03399 for(;;) {
03400
03401 ast_mutex_lock(&mgcp_reload_lock);
03402 reloading = mgcp_reloading;
03403 mgcp_reloading = 0;
03404 ast_mutex_unlock(&mgcp_reload_lock);
03405 if (reloading) {
03406 if (option_verbose > 0)
03407 ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n");
03408 mgcp_do_reload();
03409
03410 if (mgcpsock > -1)
03411 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03412 }
03413
03414
03415
03416
03417 ast_mutex_lock(&monlock);
03418
03419 ast_mutex_lock(&netlock);
03420
03421 #if 0
03422
03423
03424
03425 lastpass = thispass;
03426 thispass = time(NULL);
03427 g = gateways;
03428 while(g) {
03429 if (thispass != lastpass) {
03430 e = g->endpoints;
03431 while(e) {
03432 if (e->type == TYPE_LINE) {
03433 res = has_voicemail(e);
03434 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
03435 if (res) {
03436 transmit_notify_request(e, "L/vmwi(+)");
03437 } else {
03438 transmit_notify_request(e, "L/vmwi(-)");
03439 }
03440 e->msgstate = res;
03441 e->onhooktime = thispass;
03442 }
03443 }
03444 e = e->next;
03445 }
03446 }
03447 g = g->next;
03448 }
03449 #endif
03450
03451 ast_mutex_unlock(&netlock);
03452
03453 ast_mutex_unlock(&monlock);
03454 pthread_testcancel();
03455
03456 res = ast_sched_wait(sched);
03457
03458 if ((res < 0) || (res > 1000))
03459 res = 1000;
03460 res = ast_io_wait(io, res);
03461 ast_mutex_lock(&monlock);
03462 if (res >= 0)
03463 ast_sched_runq(sched);
03464 ast_mutex_unlock(&monlock);
03465 }
03466
03467 return NULL;
03468 }
03469
03470 static int restart_monitor(void)
03471 {
03472
03473 if (monitor_thread == AST_PTHREADT_STOP)
03474 return 0;
03475 if (ast_mutex_lock(&monlock)) {
03476 ast_log(LOG_WARNING, "Unable to lock monitor\n");
03477 return -1;
03478 }
03479 if (monitor_thread == pthread_self()) {
03480 ast_mutex_unlock(&monlock);
03481 ast_log(LOG_WARNING, "Cannot kill myself\n");
03482 return -1;
03483 }
03484 if (monitor_thread != AST_PTHREADT_NULL) {
03485
03486 pthread_kill(monitor_thread, SIGURG);
03487 } else {
03488
03489 if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03490 ast_mutex_unlock(&monlock);
03491 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03492 return -1;
03493 }
03494 }
03495 ast_mutex_unlock(&monlock);
03496 return 0;
03497 }
03498
03499 static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause)
03500 {
03501 int oldformat;
03502 struct mgcp_subchannel *sub;
03503 struct ast_channel *tmpc = NULL;
03504 char tmp[256];
03505 char *dest = data;
03506
03507 oldformat = format;
03508 format &= capability;
03509 if (!format) {
03510 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03511 return NULL;
03512 }
03513 strncpy(tmp, dest, sizeof(tmp) - 1);
03514 if (ast_strlen_zero(tmp)) {
03515 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03516 return NULL;
03517 }
03518 sub = find_subchannel_and_lock(tmp, 0, NULL);
03519 if (!sub) {
03520 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03521 *cause = AST_CAUSE_UNREGISTERED;
03522 return NULL;
03523 }
03524
03525 if (option_verbose > 2) {
03526 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
03527 ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
03528 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03529 }
03530
03531 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03532 ((!sub->parent->callwaiting) && (sub->owner)) ||
03533 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03534 if (sub->parent->hookstate == MGCP_ONHOOK) {
03535 if (has_voicemail(sub->parent)) {
03536 transmit_notify_request(sub,"L/vmwi(+)");
03537 } else {
03538 transmit_notify_request(sub,"L/vmwi(-)");
03539 }
03540 }
03541 *cause = AST_CAUSE_BUSY;
03542 ast_mutex_unlock(&sub->lock);
03543 return NULL;
03544 }
03545 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
03546 ast_mutex_unlock(&sub->lock);
03547 if (!tmpc)
03548 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03549 restart_monitor();
03550 return tmpc;
03551 }
03552
03553
03554 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
03555 {
03556 struct mgcp_gateway *gw;
03557 struct mgcp_endpoint *e;
03558 struct mgcp_subchannel *sub;
03559
03560 int i=0, y=0;
03561 int gw_reload = 0;
03562 int ep_reload = 0;
03563 canreinvite = CANREINVITE;
03564
03565
03566 gw = gateways;
03567 while (gw) {
03568 if (!strcasecmp(cat, gw->name)) {
03569
03570 gw->delme = 0;
03571 gw_reload = 1;
03572 break;
03573 }
03574 gw = gw->next;
03575 }
03576
03577 if (!gw)
03578 gw = malloc(sizeof(struct mgcp_gateway));
03579
03580 if (gw) {
03581 if (!gw_reload) {
03582 memset(gw, 0, sizeof(struct mgcp_gateway));
03583 gw->expire = -1;
03584 gw->retransid = -1;
03585 ast_mutex_init(&gw->msgs_lock);
03586 strncpy(gw->name, cat, sizeof(gw->name) - 1);
03587
03588 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
03589 gw->isnamedottedip = 1;
03590 }
03591 while(v) {
03592 if (!strcasecmp(v->name, "host")) {
03593 if (!strcasecmp(v->value, "dynamic")) {
03594
03595 gw->dynamic = 1;
03596 memset(&gw->addr.sin_addr, 0, 4);
03597 if (gw->addr.sin_port) {
03598
03599 gw->defaddr.sin_port = gw->addr.sin_port;
03600 gw->addr.sin_port = 0;
03601 }
03602 } else {
03603
03604 if (gw->expire > -1)
03605 ast_sched_del(sched, gw->expire);
03606 gw->expire = -1;
03607 gw->dynamic = 0;
03608 if (ast_get_ip(&gw->addr, v->value)) {
03609 if (!gw_reload) {
03610 ast_mutex_destroy(&gw->msgs_lock);
03611 free(gw);
03612 }
03613 return NULL;
03614 }
03615 }
03616 } else if (!strcasecmp(v->name, "defaultip")) {
03617 if (ast_get_ip(&gw->defaddr, v->value)) {
03618 if (!gw_reload) {
03619 ast_mutex_destroy(&gw->msgs_lock);
03620 free(gw);
03621 }
03622 return NULL;
03623 }
03624 } else if (!strcasecmp(v->name, "permit") ||
03625 !strcasecmp(v->name, "deny")) {
03626 gw->ha = ast_append_ha(v->name, v->value, gw->ha);
03627 } else if (!strcasecmp(v->name, "port")) {
03628 gw->addr.sin_port = htons(atoi(v->value));
03629 } else if (!strcasecmp(v->name, "context")) {
03630 strncpy(context, v->value, sizeof(context) - 1);
03631 } else if (!strcasecmp(v->name, "dtmfmode")) {
03632 if (!strcasecmp(v->value, "inband"))
03633 dtmfmode = MGCP_DTMF_INBAND;
03634 else if (!strcasecmp(v->value, "rfc2833"))
03635 dtmfmode = MGCP_DTMF_RFC2833;
03636 else if (!strcasecmp(v->value, "hybrid"))
03637 dtmfmode = MGCP_DTMF_HYBRID;
03638 else if (!strcasecmp(v->value, "none"))
03639 dtmfmode = 0;
03640 else
03641 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
03642 } else if (!strcasecmp(v->name, "nat")) {
03643 nat = ast_true(v->value);
03644 } else if (!strcasecmp(v->name, "callerid")) {
03645 if (!strcasecmp(v->value, "asreceived")) {
03646 cid_num[0] = '\0';
03647 cid_name[0] = '\0';
03648 } else {
03649 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
03650 }
03651 } else if (!strcasecmp(v->name, "language")) {
03652 strncpy(language, v->value, sizeof(language)-1);
03653 } else if (!strcasecmp(v->name, "accountcode")) {
03654 strncpy(accountcode, v->value, sizeof(accountcode)-1);
03655 } else if (!strcasecmp(v->name, "amaflags")) {
03656 y = ast_cdr_amaflags2int(v->value);
03657 if (y < 0) {
03658 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
03659 } else {
03660 amaflags = y;
03661 }
03662 } else if (!strcasecmp(v->name, "musiconhold")) {
03663 strncpy(musicclass, v->value, sizeof(musicclass)-1);
03664 } else if (!strcasecmp(v->name, "callgroup")) {
03665 cur_callergroup = ast_get_group(v->value);
03666 } else if (!strcasecmp(v->name, "pickupgroup")) {
03667 cur_pickupgroup = ast_get_group(v->value);
03668 } else if (!strcasecmp(v->name, "immediate")) {
03669 immediate = ast_true(v->value);
03670 } else if (!strcasecmp(v->name, "cancallforward")) {
03671 cancallforward = ast_true(v->value);
03672 } else if (!strcasecmp(v->name, "singlepath")) {
03673 singlepath = ast_true(v->value);
03674 } else if (!strcasecmp(v->name, "canreinvite")) {
03675 canreinvite = ast_true(v->value);
03676 } else if (!strcasecmp(v->name, "mailbox")) {
03677 strncpy(mailbox, v->value, sizeof(mailbox) -1);
03678 } else if (!strcasecmp(v->name, "adsi")) {
03679 adsi = ast_true(v->value);
03680 } else if (!strcasecmp(v->name, "callreturn")) {
03681 callreturn = ast_true(v->value);
03682 } else if (!strcasecmp(v->name, "callwaiting")) {
03683 callwaiting = ast_true(v->value);
03684 } else if (!strcasecmp(v->name, "slowsequence")) {
03685 slowsequence = ast_true(v->value);
03686 } else if (!strcasecmp(v->name, "transfer")) {
03687 transfer = ast_true(v->value);
03688 } else if (!strcasecmp(v->name, "threewaycalling")) {
03689 threewaycalling = ast_true(v->value);
03690 } else if (!strcasecmp(v->name, "wcardep")) {
03691
03692 e = gw->endpoints;
03693 while (e) {
03694 if (!strcasecmp(v->value, e->name)) {
03695
03696 e->delme = 0;
03697 ep_reload = 1;
03698 break;
03699 }
03700 e = e->next;
03701 }
03702
03703 if (!e) {
03704
03705 e = malloc(sizeof(struct mgcp_endpoint));
03706 ep_reload = 0;
03707 }
03708
03709 if (e) {
03710 if (!ep_reload) {
03711 memset(e, 0, sizeof(struct mgcp_endpoint));
03712 ast_mutex_init(&e->lock);
03713 ast_mutex_init(&e->rqnt_queue_lock);
03714 ast_mutex_init(&e->cmd_queue_lock);
03715 strncpy(e->name, v->value, sizeof(e->name) - 1);
03716 e->needaudit = 1;
03717 }
03718 strncpy(gw->wcardep, v->value, sizeof(gw->wcardep) - 1);
03719
03720
03721 strncpy(e->accountcode, accountcode, sizeof(e->accountcode) - 1);
03722 strncpy(e->context, context, sizeof(e->context) - 1);
03723 strncpy(e->cid_num, cid_num, sizeof(e->cid_num) - 1);
03724 strncpy(e->cid_name, cid_name, sizeof(e->cid_name) - 1);
03725 strncpy(e->language, language, sizeof(e->language) - 1);
03726 strncpy(e->musicclass, musicclass, sizeof(e->musicclass) - 1);
03727 strncpy(e->mailbox, mailbox, sizeof(e->mailbox) - 1);
03728 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08x", rand());
03729 e->msgstate = -1;
03730 e->amaflags = amaflags;
03731 e->capability = capability;
03732 e->parent = gw;
03733 e->dtmfmode = dtmfmode;
03734 if (!ep_reload && e->sub && e->sub->rtp)
03735 e->dtmfmode |= MGCP_DTMF_INBAND;
03736 e->adsi = adsi;
03737 e->type = TYPE_LINE;
03738 e->immediate = immediate;
03739 e->callgroup=cur_callergroup;
03740 e->pickupgroup=cur_pickupgroup;
03741 e->callreturn = callreturn;
03742 e->cancallforward = cancallforward;
03743 e->singlepath = singlepath;
03744 e->canreinvite = canreinvite;
03745 e->callwaiting = callwaiting;
03746 e->hascallwaiting = callwaiting;
03747 e->slowsequence = slowsequence;
03748 e->transfer = transfer;
03749 e->threewaycalling = threewaycalling;
03750 e->onhooktime = time(NULL);
03751
03752 e->hookstate = MGCP_ONHOOK;
03753 if (!ep_reload) {
03754
03755 for (i = 0; i < MAX_SUBS; i++) {
03756 sub = malloc(sizeof(struct mgcp_subchannel));
03757 if (sub) {
03758 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03759 memset(sub, 0, sizeof(struct mgcp_subchannel));
03760 ast_mutex_init(&sub->lock);
03761 ast_mutex_init(&sub->cx_queue_lock);
03762 sub->parent = e;
03763 sub->id = i;
03764 snprintf(sub->txident, sizeof(sub->txident), "%08x", rand());
03765
03766 sub->cxmode = MGCP_CX_INACTIVE;
03767 sub->nat = nat;
03768 sub->next = e->sub;
03769 e->sub = sub;
03770 } else {
03771
03772 ast_log(LOG_WARNING, "Out of memory allocating subchannel");
03773 return NULL;
03774 }
03775 }
03776
03777 sub = e->sub;
03778
03779 while(sub->next){
03780 sub = sub->next;
03781 }
03782
03783 sub->next = e->sub;
03784
03785 e->next = gw->endpoints;
03786 gw->endpoints = e;
03787 }
03788 }
03789 } else if (!strcasecmp(v->name, "trunk") ||
03790 !strcasecmp(v->name, "line")) {
03791
03792
03793 e = gw->endpoints;
03794 while (e) {
03795 if (!strcasecmp(v->value, e->name)) {
03796
03797 e->delme = 0;
03798 ep_reload = 1;
03799 break;
03800 }
03801 e = e->next;
03802 }
03803
03804 if (!e) {
03805 e = malloc(sizeof(struct mgcp_endpoint));
03806 ep_reload = 0;
03807 }
03808
03809 if (e) {
03810 if (!ep_reload) {
03811 memset(e, 0, sizeof(struct mgcp_endpoint));
03812 ast_mutex_init(&e->lock);
03813 ast_mutex_init(&e->rqnt_queue_lock);
03814 ast_mutex_init(&e->cmd_queue_lock);
03815 strncpy(e->name, v->value, sizeof(e->name) - 1);
03816 e->needaudit = 1;
03817 }
03818
03819 strncpy(e->accountcode, accountcode, sizeof(e->accountcode) - 1);
03820 strncpy(e->context, context, sizeof(e->context) - 1);
03821 strncpy(e->cid_num, cid_num, sizeof(e->cid_num) - 1);
03822 strncpy(e->cid_name, cid_name, sizeof(e->cid_name) - 1);
03823 strncpy(e->language, language, sizeof(e->language) - 1);
03824 strncpy(e->musicclass, musicclass, sizeof(e->musicclass) - 1);
03825 strncpy(e->mailbox, mailbox, sizeof(e->mailbox)-1);
03826 if (!ast_strlen_zero(mailbox)) {
03827 ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
03828 }
03829 if (!ep_reload) {
03830
03831 e->msgstate = -1;
03832 e->parent = gw;
03833 }
03834 e->amaflags = amaflags;
03835 e->capability = capability;
03836 e->dtmfmode = dtmfmode;
03837 e->adsi = adsi;
03838 if (!strcasecmp(v->name, "trunk"))
03839 e->type = TYPE_TRUNK;
03840 else
03841 e->type = TYPE_LINE;
03842
03843 e->immediate = immediate;
03844 e->callgroup=cur_callergroup;
03845 e->pickupgroup=cur_pickupgroup;
03846 e->callreturn = callreturn;
03847 e->cancallforward = cancallforward;
03848 e->canreinvite = canreinvite;
03849 e->singlepath = singlepath;
03850 e->callwaiting = callwaiting;
03851 e->hascallwaiting = callwaiting;
03852 e->slowsequence = slowsequence;
03853 e->transfer = transfer;
03854 e->threewaycalling = threewaycalling;
03855 if (!ep_reload) {
03856 e->onhooktime = time(NULL);
03857
03858 e->hookstate = MGCP_ONHOOK;
03859 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08x", rand());
03860 }
03861
03862 for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
03863 if (!ep_reload) {
03864 sub = malloc(sizeof(struct mgcp_subchannel));
03865 } else {
03866 if (!sub)
03867 sub = e->sub;
03868 else
03869 sub = sub->next;
03870 }
03871
03872 if (sub) {
03873 if (!ep_reload) {
03874 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03875 memset(sub, 0, sizeof(struct mgcp_subchannel));
03876 ast_mutex_init(&sub->lock);
03877 ast_mutex_init(&sub->cx_queue_lock);
03878 strncpy(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic) - 1);
03879 sub->parent = e;
03880 sub->id = i;
03881 snprintf(sub->txident, sizeof(sub->txident), "%08x", rand());
03882 sub->cxmode = MGCP_CX_INACTIVE;
03883 sub->next = e->sub;
03884 e->sub = sub;
03885 }
03886 sub->nat = nat;
03887 } else {
03888
03889 ast_log(LOG_WARNING, "Out of memory allocating subchannel");
03890 return NULL;
03891 }
03892 }
03893 if (!ep_reload) {
03894
03895 sub = e->sub;
03896
03897 while (sub->next) {
03898 sub = sub->next;
03899 }
03900
03901 sub->next = e->sub;
03902
03903 e->next = gw->endpoints;
03904 gw->endpoints = e;
03905 }
03906 }
03907 } else
03908 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
03909 v = v->next;
03910 }
03911 }
03912 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
03913 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
03914 if (!gw_reload) {
03915 ast_mutex_destroy(&gw->msgs_lock);
03916 free(gw);
03917 }
03918 return NULL;
03919 }
03920 gw->defaddr.sin_family = AF_INET;
03921 gw->addr.sin_family = AF_INET;
03922 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port))
03923 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03924 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
03925 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03926 if (gw->addr.sin_addr.s_addr)
03927 if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip))
03928 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
03929
03930 return (gw_reload ? NULL : gw);
03931 }
03932
03933 static struct ast_rtp *mgcp_get_rtp_peer(struct ast_channel *chan)
03934 {
03935 struct mgcp_subchannel *sub;
03936 sub = chan->tech_pvt;
03937 if (sub && sub->rtp && sub->parent->canreinvite)
03938 return sub->rtp;
03939 return NULL;
03940 }
03941
03942 static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
03943 {
03944
03945 struct mgcp_subchannel *sub;
03946 sub = chan->tech_pvt;
03947 if (sub) {
03948 transmit_modify_with_sdp(sub, rtp, codecs);
03949 return 0;
03950 }
03951 return -1;
03952 }
03953
03954 static struct ast_rtp_protocol mgcp_rtp = {
03955 .type = type,
03956 .get_rtp_info = mgcp_get_rtp_peer,
03957 .set_rtp_peer = mgcp_set_rtp_peer,
03958 };
03959
03960 static int mgcp_do_debug(int fd, int argc, char *argv[])
03961 {
03962 if (argc != 2)
03963 return RESULT_SHOWUSAGE;
03964 mgcpdebug = 1;
03965 ast_cli(fd, "MGCP Debugging Enabled\n");
03966 return RESULT_SUCCESS;
03967 }
03968
03969 static int mgcp_no_debug(int fd, int argc, char *argv[])
03970 {
03971 if (argc != 3)
03972 return RESULT_SHOWUSAGE;
03973 mgcpdebug = 0;
03974 ast_cli(fd, "MGCP Debugging Disabled\n");
03975 return RESULT_SUCCESS;
03976 }
03977
03978 static char debug_usage[] =
03979 "Usage: mgcp debug\n"
03980 " Enables dumping of MGCP packets for debugging purposes\n";
03981
03982 static char no_debug_usage[] =
03983 "Usage: mgcp no debug\n"
03984 " Disables dumping of MGCP packets for debugging purposes\n";
03985
03986 static char mgcp_reload_usage[] =
03987 "Usage: mgcp reload\n"
03988 " Reloads MGCP configuration from mgcp.conf\n";
03989
03990 static struct ast_cli_entry cli_debug =
03991 { { "mgcp", "debug", NULL }, mgcp_do_debug, "Enable MGCP debugging", debug_usage };
03992 static struct ast_cli_entry cli_no_debug =
03993 { { "mgcp", "no", "debug", NULL }, mgcp_no_debug, "Disable MGCP debugging", no_debug_usage };
03994 static struct ast_cli_entry cli_mgcp_reload =
03995 { { "mgcp", "reload", NULL }, mgcp_reload, "Reload MGCP configuration", mgcp_reload_usage };
03996
03997
03998 static void destroy_endpoint(struct mgcp_endpoint *e)
03999 {
04000 struct mgcp_subchannel *sub = e->sub->next, *s;
04001 int i;
04002
04003 for (i = 0; i < MAX_SUBS; i++) {
04004 ast_mutex_lock(&sub->lock);
04005 if (!ast_strlen_zero(sub->cxident)) {
04006 transmit_connection_del(sub);
04007 }
04008 if (sub->rtp) {
04009 ast_rtp_destroy(sub->rtp);
04010 sub->rtp = NULL;
04011 }
04012 memset(sub->magic, 0, sizeof(sub->magic));
04013 mgcp_queue_hangup(sub);
04014 dump_cmd_queues(NULL, sub);
04015 ast_mutex_unlock(&sub->lock);
04016 sub = sub->next;
04017 }
04018
04019 if (e->dsp) {
04020 ast_dsp_free(e->dsp);
04021 }
04022
04023 dump_queue(e->parent, e);
04024 dump_cmd_queues(e, NULL);
04025
04026 sub = e->sub;
04027 for (i = 0; (i < MAX_SUBS) && sub; i++) {
04028 s = sub;
04029 sub = sub->next;
04030 ast_mutex_destroy(&s->lock);
04031 ast_mutex_destroy(&s->cx_queue_lock);
04032 free(s);
04033 }
04034 ast_mutex_destroy(&e->lock);
04035 ast_mutex_destroy(&e->rqnt_queue_lock);
04036 ast_mutex_destroy(&e->cmd_queue_lock);
04037 free(e);
04038 }
04039
04040 static void destroy_gateway(struct mgcp_gateway *g)
04041 {
04042 if (g->ha)
04043 ast_free_ha(g->ha);
04044
04045 dump_queue(g, NULL);
04046
04047 free (g);
04048 }
04049
04050 static void prune_gateways(void)
04051 {
04052 struct mgcp_gateway *g, *z, *r;
04053 struct mgcp_endpoint *e, *p, *t;
04054
04055 ast_mutex_lock(&gatelock);
04056
04057
04058 for (z = NULL, g = gateways; g;) {
04059
04060 for (p = NULL, e = g->endpoints; e; ) {
04061 if (e->delme || g->delme) {
04062 t = e;
04063 e = e->next;
04064 if (!p)
04065 g->endpoints = e;
04066 else
04067 p->next = e;
04068 destroy_endpoint(t);
04069 } else {
04070 p = e;
04071 e = e->next;
04072 }
04073 }
04074
04075 if (g->delme) {
04076 r = g;
04077 g = g->next;
04078 if (!z)
04079 gateways = g;
04080 else
04081 z->next = g;
04082
04083 destroy_gateway(r);
04084 } else {
04085 z = g;
04086 g = g->next;
04087 }
04088 }
04089
04090 ast_mutex_unlock(&gatelock);
04091 }
04092
04093 static int reload_config(void)
04094 {
04095 struct ast_config *cfg;
04096 struct ast_variable *v;
04097 struct mgcp_gateway *g;
04098 struct mgcp_endpoint *e;
04099 char iabuf[INET_ADDRSTRLEN];
04100 char *cat;
04101 struct ast_hostent ahp;
04102 struct hostent *hp;
04103 int format;
04104
04105 if (gethostname(ourhost, sizeof(ourhost)-1)) {
04106 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
04107 return 0;
04108 }
04109 cfg = ast_config_load(config);
04110
04111
04112 if (!cfg) {
04113 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
04114 return 0;
04115 }
04116 memset(&bindaddr, 0, sizeof(bindaddr));
04117 dtmfmode = 0;
04118 v = ast_variable_browse(cfg, "general");
04119 while(v) {
04120
04121 if (!strcasecmp(v->name, "bindaddr")) {
04122 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04123 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04124 } else {
04125 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04126 }
04127 } else if (!strcasecmp(v->name, "allow")) {
04128 format = ast_getformatbyname(v->value);
04129 if (format < 1)
04130 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04131 else
04132 capability |= format;
04133 } else if (!strcasecmp(v->name, "disallow")) {
04134 format = ast_getformatbyname(v->value);
04135 if (format < 1)
04136 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
04137 else
04138 capability &= ~format;
04139 } else if (!strcasecmp(v->name, "tos")) {
04140 if (sscanf(v->value, "%d", &format) == 1)
04141 tos = format & 0xff;
04142 else if (!strcasecmp(v->value, "lowdelay"))
04143 tos = IPTOS_LOWDELAY;
04144 else if (!strcasecmp(v->value, "throughput"))
04145 tos = IPTOS_THROUGHPUT;
04146 else if (!strcasecmp(v->value, "reliability"))
04147 tos = IPTOS_RELIABILITY;
04148 else if (!strcasecmp(v->value, "mincost"))
04149 tos = IPTOS_MINCOST;
04150 else if (!strcasecmp(v->value, "none"))
04151 tos = 0;
04152 else
04153 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
04154 } else if (!strcasecmp(v->name, "port")) {
04155 if (sscanf(v->value, "%d", &ourport) == 1) {
04156 bindaddr.sin_port = htons(ourport);
04157 } else {
04158 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
04159 }
04160 }
04161 v = v->next;
04162 }
04163
04164
04165 ast_mutex_lock(&gatelock);
04166 g = gateways;
04167 while (g) {
04168 g->delme = 1;
04169 e = g->endpoints;
04170 while (e) {
04171 e->delme = 1;
04172 e = e->next;
04173 }
04174 g = g->next;
04175 }
04176 ast_mutex_unlock(&gatelock);
04177
04178 cat = ast_category_browse(cfg, NULL);
04179 while(cat) {
04180 if (strcasecmp(cat, "general")) {
04181 ast_mutex_lock(&gatelock);
04182 g = build_gateway(cat, ast_variable_browse(cfg, cat));
04183 if (g) {
04184 if (option_verbose > 2) {
04185 ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
04186 }
04187 g->next = gateways;
04188 gateways = g;
04189 }
04190 ast_mutex_unlock(&gatelock);
04191
04192
04193 if (monitor_thread == pthread_self()) {
04194 if (sched) ast_sched_runq(sched);
04195 if (io) ast_io_wait(io, 10);
04196 }
04197 }
04198 cat = ast_category_browse(cfg, cat);
04199 }
04200
04201
04202 prune_gateways();
04203
04204 if (ntohl(bindaddr.sin_addr.s_addr)) {
04205 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
04206 } else {
04207 hp = ast_gethostbyname(ourhost, &ahp);
04208 if (!hp) {
04209 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
04210 ast_config_destroy(cfg);
04211 return 0;
04212 }
04213 memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04214 }
04215 if (!ntohs(bindaddr.sin_port))
04216 bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
04217 bindaddr.sin_family = AF_INET;
04218 ast_mutex_lock(&netlock);
04219 if (mgcpsock > -1)
04220 close(mgcpsock);
04221
04222 if (mgcpsock_read_id != NULL)
04223 ast_io_remove(io, mgcpsock_read_id);
04224 mgcpsock_read_id = NULL;
04225
04226 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
04227 if (mgcpsock < 0) {
04228 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
04229 } else {
04230 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04231 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04232 ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04233 strerror(errno));
04234 close(mgcpsock);
04235 mgcpsock = -1;
04236 } else {
04237 if (option_verbose > 1) {
04238 ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n",
04239 ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04240 ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
04241 }
04242 if (setsockopt(mgcpsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))
04243 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
04244 }
04245 }
04246 ast_mutex_unlock(&netlock);
04247 ast_config_destroy(cfg);
04248
04249
04250 g = gateways;
04251 while (g) {
04252 e = g->endpoints;
04253 while (e && e->needaudit) {
04254 e->needaudit = 0;
04255 transmit_audit_endpoint(e);
04256 ast_verbose(VERBOSE_PREFIX_3 "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
04257 e = e->next;
04258 }
04259 g = g->next;
04260 }
04261
04262 return 0;
04263 }
04264
04265 int load_module()
04266 {
04267 int res;
04268
04269 sched = sched_context_create();
04270 if (!sched) {
04271 ast_log(LOG_WARNING, "Unable to create schedule context\n");
04272 return -1;
04273 }
04274 io = io_context_create();
04275 if (!io) {
04276 ast_log(LOG_WARNING, "Unable to create I/O context\n");
04277 return -1;
04278 }
04279
04280 if (!(res = reload_config())) {
04281
04282 if (ast_channel_register(&mgcp_tech)) {
04283 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
04284 return -1;
04285 }
04286 ast_rtp_proto_register(&mgcp_rtp);
04287 ast_cli_register(&cli_show_endpoints);
04288 ast_cli_register(&cli_audit_endpoint);
04289 ast_cli_register(&cli_debug);
04290 ast_cli_register(&cli_no_debug);
04291 ast_cli_register(&cli_mgcp_reload);
04292
04293
04294 restart_monitor();
04295 }
04296
04297 return res;
04298 }
04299
04300 static int mgcp_do_reload(void)
04301 {
04302 reload_config();
04303 return 0;
04304 }
04305
04306 static int mgcp_reload(int fd, int argc, char *argv[])
04307 {
04308 ast_mutex_lock(&mgcp_reload_lock);
04309 if (mgcp_reloading) {
04310 ast_verbose("Previous mgcp reload not yet done\n");
04311 } else
04312 mgcp_reloading = 1;
04313 ast_mutex_unlock(&mgcp_reload_lock);
04314 restart_monitor();
04315 return 0;
04316 }
04317
04318 int reload(void)
04319 {
04320 mgcp_reload(0, 0, NULL);
04321 return 0;
04322 }
04323
04324 int unload_module()
04325 {
04326 struct mgcp_endpoint *e;
04327 struct mgcp_gateway *g;
04328
04329
04330 if (ast_mutex_trylock(&mgcp_reload_lock)) {
04331 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n");
04332 return -1;
04333 } else {
04334 mgcp_reloading = 1;
04335 ast_mutex_unlock(&mgcp_reload_lock);
04336 }
04337
04338
04339 ast_channel_unregister(&mgcp_tech);
04340
04341
04342 if (!ast_mutex_lock(&monlock)) {
04343 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04344 pthread_cancel(monitor_thread);
04345 pthread_kill(monitor_thread, SIGURG);
04346 pthread_join(monitor_thread, NULL);
04347 }
04348 monitor_thread = AST_PTHREADT_STOP;
04349 ast_mutex_unlock(&monlock);
04350 } else {
04351 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04352
04353 ast_channel_register(&mgcp_tech);
04354 mgcp_reloading = 0;
04355 mgcp_reload(0, 0, NULL);
04356 return -1;
04357 }
04358
04359 if (!ast_mutex_lock(&gatelock)) {
04360 g = gateways;
04361 while (g) {
04362 g->delme = 1;
04363 e = g->endpoints;
04364 while (e) {
04365 e->delme = 1;
04366 e = e->next;
04367 }
04368 g = g->next;
04369 }
04370
04371 prune_gateways();
04372 ast_mutex_unlock(&gatelock);
04373 } else {
04374 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
04375
04376 ast_channel_register(&mgcp_tech);
04377
04378 monitor_thread = AST_PTHREADT_NULL;
04379 mgcp_reloading = 0;
04380 mgcp_reload(0, 0, NULL);
04381 return -1;
04382 }
04383
04384 close(mgcpsock);
04385 ast_rtp_proto_unregister(&mgcp_rtp);
04386 ast_cli_unregister(&cli_show_endpoints);
04387 ast_cli_unregister(&cli_audit_endpoint);
04388 ast_cli_unregister(&cli_debug);
04389 ast_cli_unregister(&cli_no_debug);
04390 ast_cli_unregister(&cli_mgcp_reload);
04391 sched_context_destroy(sched);
04392
04393 return 0;
04394 }
04395
04396 int usecount()
04397 {
04398 return usecnt;
04399 }
04400
04401 char *key()
04402 {
04403 return ASTERISK_GPL_KEY;
04404 }
04405
04406 char *description()
04407 {
04408 return (char *) desc;
04409 }