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