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