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