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