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