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