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