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